diff --git a/Assets/gamedb/gamedb_vectrex.txt b/Assets/gamedb/gamedb_vectrex.txt
index 1a706121e4..f4042d8ead 100644
--- a/Assets/gamedb/gamedb_vectrex.txt
+++ b/Assets/gamedb/gamedb_vectrex.txt
@@ -1 +1,3 @@
SHA1:67F8513958C04E936B135740ED4EC6E6FA1763D5 Clean Sweep VEC
+SHA1:38E38B5C60466146D4648F8929B5CE3A08DCBE0D Scramble VEC
+
diff --git a/BizHawk.Client.ApiHawk/Classes/Api/MemEventsApi.cs b/BizHawk.Client.ApiHawk/Classes/Api/MemEventsApi.cs
index 5848df5fc3..05993e866a 100644
--- a/BizHawk.Client.ApiHawk/Classes/Api/MemEventsApi.cs
+++ b/BizHawk.Client.ApiHawk/Classes/Api/MemEventsApi.cs
@@ -13,28 +13,28 @@ namespace BizHawk.Client.ApiHawk
public MemEventsApi () : base()
{ }
- public void AddReadCallback(Action cb, uint address, string domain)
+ public void AddReadCallback(MemoryCallbackDelegate cb, uint? address, string domain)
{
if (DebuggableCore.MemoryCallbacksAvailable())
{
DebuggableCore.MemoryCallbacks.Add(new MemoryCallback(domain, MemoryCallbackType.Read, "Plugin Hook", cb, address, null));
}
}
- public void AddWriteCallback(Action cb, uint address, string domain)
+ public void AddWriteCallback(MemoryCallbackDelegate cb, uint? address, string domain)
{
if (DebuggableCore.MemoryCallbacksAvailable())
{
DebuggableCore.MemoryCallbacks.Add(new MemoryCallback(domain, MemoryCallbackType.Write, "Plugin Hook", cb, address, null));
}
}
- public void AddExecCallback(Action cb, uint address, string domain)
+ public void AddExecCallback(MemoryCallbackDelegate cb, uint? address, string domain)
{
if (DebuggableCore.MemoryCallbacksAvailable() && DebuggableCore.MemoryCallbacks.ExecuteCallbacksAvailable)
{
DebuggableCore.MemoryCallbacks.Add(new MemoryCallback(domain, MemoryCallbackType.Execute, "Plugin Hook", cb, address, null));
}
}
- public void RemoveMemoryCallback(Action cb)
+ public void RemoveMemoryCallback(MemoryCallbackDelegate cb)
{
if (DebuggableCore.MemoryCallbacksAvailable())
{
diff --git a/BizHawk.Client.ApiHawk/Interfaces/Api/IMemEvents.cs b/BizHawk.Client.ApiHawk/Interfaces/Api/IMemEvents.cs
index b8650a9139..ef0f5ef0bc 100644
--- a/BizHawk.Client.ApiHawk/Interfaces/Api/IMemEvents.cs
+++ b/BizHawk.Client.ApiHawk/Interfaces/Api/IMemEvents.cs
@@ -1,12 +1,14 @@
-using System;
-
-namespace BizHawk.Client.ApiHawk
-{
- public interface IMemEvents : IExternalApi
- {
- void AddReadCallback(Action cb, uint address, string domain);
- void AddWriteCallback(Action cb, uint address, string domain);
- void AddExecCallback(Action cb, uint address, string domain);
- void RemoveMemoryCallback(Action cb);
- }
-}
+using System;
+
+using BizHawk.Emulation.Common;
+
+namespace BizHawk.Client.ApiHawk
+{
+ public interface IMemEvents : IExternalApi
+ {
+ void AddReadCallback(MemoryCallbackDelegate cb, uint? address, string domain);
+ void AddWriteCallback(MemoryCallbackDelegate cb, uint? address, string domain);
+ void AddExecCallback(MemoryCallbackDelegate cb, uint? address, string domain);
+ void RemoveMemoryCallback(MemoryCallbackDelegate cb);
+ }
+}
diff --git a/BizHawk.Client.Common/BinarySaveStates.cs b/BizHawk.Client.Common/BinarySaveStates.cs
index baa4b327ae..d66beaed24 100644
--- a/BizHawk.Client.Common/BinarySaveStates.cs
+++ b/BizHawk.Client.Common/BinarySaveStates.cs
@@ -60,8 +60,8 @@ namespace BizHawk.Client.Common
public static BinaryStateLump BranchInputLog { get; private set; }
[Name("Branches\\FrameBuffer", "bmp")]
public static BinaryStateLump BranchFrameBuffer { get; private set; }
- [Name("Branches\\LagLog", "bin")]
- public static BinaryStateLump BranchLagLog { get; private set; }
+ [Name("Branches\\CoreFrameBuffer", "bmp")]
+ public static BinaryStateLump BranchCoreFrameBuffer { get; private set; }
[Name("Branches\\Header", "json")]
public static BinaryStateLump BranchHeader { get; private set; }
[Name("Branches\\Markers", "txt")]
diff --git a/BizHawk.Client.Common/lua/EmuLuaLibrary.Events.cs b/BizHawk.Client.Common/lua/EmuLuaLibrary.Events.cs
index 7038915c81..1ec246820e 100644
--- a/BizHawk.Client.Common/lua/EmuLuaLibrary.Events.cs
+++ b/BizHawk.Client.Common/lua/EmuLuaLibrary.Events.cs
@@ -231,7 +231,7 @@ namespace BizHawk.Client.Common
}
DebuggableCore.MemoryCallbacks.Add(
- new MemoryCallback(domain, MemoryCallbackType.Execute, "Lua Hook", nlf.Callback, address, null));
+ new MemoryCallback(domain, MemoryCallbackType.Execute, "Lua Hook", nlf.MemCallback, address, null));
return nlf.Guid.ToString();
}
}
@@ -270,7 +270,7 @@ namespace BizHawk.Client.Common
}
DebuggableCore.MemoryCallbacks.Add(
- new MemoryCallback(domain, MemoryCallbackType.Read, "Lua Hook", nlf.Callback, address, null));
+ new MemoryCallback(domain, MemoryCallbackType.Read, "Lua Hook", nlf.MemCallback, address, null));
return nlf.Guid.ToString();
}
}
@@ -309,7 +309,7 @@ namespace BizHawk.Client.Common
}
DebuggableCore.MemoryCallbacks.Add(
- new MemoryCallback(domain, MemoryCallbackType.Write, "Lua Hook", nlf.Callback, address, null));
+ new MemoryCallback(domain, MemoryCallbackType.Write, "Lua Hook", nlf.MemCallback, address, null));
return nlf.Guid.ToString();
}
}
diff --git a/BizHawk.Client.Common/lua/LuaFunctionList.cs b/BizHawk.Client.Common/lua/LuaFunctionList.cs
index 45ec368722..87d36e9d3b 100644
--- a/BizHawk.Client.Common/lua/LuaFunctionList.cs
+++ b/BizHawk.Client.Common/lua/LuaFunctionList.cs
@@ -24,7 +24,7 @@ namespace BizHawk.Client.Common
if (Global.Emulator.MemoryCallbacksAvailable())
{
- Global.Emulator.AsDebuggable().MemoryCallbacks.Remove(function.Callback);
+ Global.Emulator.AsDebuggable().MemoryCallbacks.Remove(function.MemCallback);
}
return base.Remove(function);
@@ -40,7 +40,7 @@ namespace BizHawk.Client.Common
if (Global.Emulator.MemoryCallbacksAvailable())
{
var memoryCallbacks = Global.Emulator.AsDebuggable().MemoryCallbacks;
- memoryCallbacks.RemoveAll(this.Select(w => w.Callback));
+ memoryCallbacks.RemoveAll(this.Select(w => w.MemCallback));
}
Clear();
diff --git a/BizHawk.Client.Common/lua/NamedLuaFunction.cs b/BizHawk.Client.Common/lua/NamedLuaFunction.cs
index 828f97968a..bb602e8f62 100644
--- a/BizHawk.Client.Common/lua/NamedLuaFunction.cs
+++ b/BizHawk.Client.Common/lua/NamedLuaFunction.cs
@@ -1,6 +1,8 @@
using System;
using NLua;
+using BizHawk.Emulation.Common;
+
namespace BizHawk.Client.Common
{
public class NamedLuaFunction
@@ -26,6 +28,11 @@ namespace BizHawk.Client.Common
logCallback($"error running function attached by the event {Event}\nError message: {ex.Message}");
}
};
+
+ MemCallback = delegate
+ {
+ Callback();
+ };
}
public Guid Guid { get; private set; }
@@ -38,6 +45,8 @@ namespace BizHawk.Client.Common
public Action Callback { get; }
+ public MemoryCallbackDelegate MemCallback { get; }
+
public void Call(string name = null)
{
LuaSandbox.Sandbox(Lua, () =>
diff --git a/BizHawk.Client.Common/movie/tasproj/TasBranch.cs b/BizHawk.Client.Common/movie/tasproj/TasBranch.cs
index 2eae586ab0..a79a3beec2 100644
--- a/BizHawk.Client.Common/movie/tasproj/TasBranch.cs
+++ b/BizHawk.Client.Common/movie/tasproj/TasBranch.cs
@@ -12,8 +12,8 @@ namespace BizHawk.Client.Common
public int Frame { get; set; }
public byte[] CoreData { get; set; }
public IStringLog InputLog { get; set; }
+ public BitmapBuffer CoreFrameBuffer { get; set; }
public BitmapBuffer OSDFrameBuffer { get; set; }
- public TasLagLog LagLog { get; set; }
public TasMovieChangeLog ChangeLog { get; set; }
public DateTime TimeStamp { get; set; }
public TasMovieMarkerList Markers { get; set; }
@@ -50,7 +50,7 @@ namespace BizHawk.Client.Common
var ncore = new IndexedStateLump(BinaryStateLump.BranchCoreData);
var ninput = new IndexedStateLump(BinaryStateLump.BranchInputLog);
var nframebuffer = new IndexedStateLump(BinaryStateLump.BranchFrameBuffer);
- var nlaglog = new IndexedStateLump(BinaryStateLump.BranchLagLog);
+ var ncoreframebuffer = new IndexedStateLump(BinaryStateLump.BranchCoreFrameBuffer);
var nmarkers = new IndexedStateLump(BinaryStateLump.BranchMarkers);
var nusertext = new IndexedStateLump(BinaryStateLump.BranchUserText);
foreach (var b in this)
@@ -86,9 +86,10 @@ namespace BizHawk.Client.Common
QuickBmpFile.Save(vp, s, b.OSDFrameBuffer.Width, b.OSDFrameBuffer.Height);
});
- bs.PutLump(nlaglog, delegate(BinaryWriter bw)
+ bs.PutLump(ncoreframebuffer, delegate(Stream s)
{
- b.LagLog.Save(bw);
+ var vp = new BitmapBufferVideoProvider(b.CoreFrameBuffer);
+ QuickBmpFile.Save(vp, s, b.CoreFrameBuffer.Width, b.CoreFrameBuffer.Height);
});
bs.PutLump(nmarkers, delegate(TextWriter tw)
@@ -105,7 +106,7 @@ namespace BizHawk.Client.Common
ncore.Increment();
ninput.Increment();
nframebuffer.Increment();
- nlaglog.Increment();
+ ncoreframebuffer.Increment();
nmarkers.Increment();
nusertext.Increment();
}
@@ -117,7 +118,7 @@ namespace BizHawk.Client.Common
var ncore = new IndexedStateLump(BinaryStateLump.BranchCoreData);
var ninput = new IndexedStateLump(BinaryStateLump.BranchInputLog);
var nframebuffer = new IndexedStateLump(BinaryStateLump.BranchFrameBuffer);
- var nlaglog = new IndexedStateLump(BinaryStateLump.BranchLagLog);
+ var ncoreframebuffer = new IndexedStateLump(BinaryStateLump.BranchCoreFrameBuffer);
var nmarkers = new IndexedStateLump(BinaryStateLump.BranchMarkers);
var nusertext = new IndexedStateLump(BinaryStateLump.BranchUserText);
@@ -180,10 +181,11 @@ namespace BizHawk.Client.Common
b.OSDFrameBuffer = new BitmapBuffer(vp.BufferWidth, vp.BufferHeight, vp.VideoBuffer);
});
- bl.GetLump(nlaglog, true, delegate(BinaryReader br)
+ bl.GetLump(ncoreframebuffer, false, delegate(Stream s, long length)
{
- b.LagLog = new TasLagLog();
- b.LagLog.Load(br);
+ var vp = new QuickBmpFile.LoadedBMP();
+ QuickBmpFile.Load(vp, s);
+ b.CoreFrameBuffer = new BitmapBuffer(vp.BufferWidth, vp.BufferHeight, vp.VideoBuffer);
});
b.Markers = new TasMovieMarkerList(movie);
@@ -217,7 +219,7 @@ namespace BizHawk.Client.Common
ncore.Increment();
ninput.Increment();
nframebuffer.Increment();
- nlaglog.Increment();
+ ncoreframebuffer.Increment();
nmarkers.Increment();
nusertext.Increment();
}
diff --git a/BizHawk.Client.Common/movie/tasproj/TasLagLog.cs b/BizHawk.Client.Common/movie/tasproj/TasLagLog.cs
index 98ff514ec0..1be5406de8 100644
--- a/BizHawk.Client.Common/movie/tasproj/TasLagLog.cs
+++ b/BizHawk.Client.Common/movie/tasproj/TasLagLog.cs
@@ -146,8 +146,6 @@ namespace BizHawk.Client.Common
{
_lagLog.Clear();
_wasLag.Clear();
- ////if (br.BaseStream.Length > 0)
- ////{ BaseStream.Length does not return the expected value.
int formatVersion = br.ReadByte();
if (formatVersion == 0)
{
@@ -175,7 +173,6 @@ namespace BizHawk.Client.Common
_wasLag.Add(br.ReadBoolean());
}
}
- ////}
}
public bool? History(int frame)
@@ -193,19 +190,6 @@ namespace BizHawk.Client.Common
return null;
}
- public int LastValidFrame
- {
- get
- {
- if (_lagLog.Count == 0)
- {
- return 0;
- }
-
- return _lagLog.Count - 1;
- }
- }
-
public TasLagLog Clone()
{
return new TasLagLog
diff --git a/BizHawk.Client.Common/movie/tasproj/TasMovie.cs b/BizHawk.Client.Common/movie/tasproj/TasMovie.cs
index 0a5aee0af2..3814fcdb11 100644
--- a/BizHawk.Client.Common/movie/tasproj/TasMovie.cs
+++ b/BizHawk.Client.Common/movie/tasproj/TasMovie.cs
@@ -35,7 +35,7 @@ namespace BizHawk.Client.Common
public TasLagLog TasLagLog => _lagLog;
public IStringLog InputLog => Log;
public int BranchCount => Branches.Count;
- public int LastValidFrame => _lagLog.LastValidFrame;
+ public int LastStatedFrame => _stateManager.LastStatedFrame;
public override string PreferredExtension => Extension;
public TasStateManager TasStateManager => _stateManager;
@@ -225,7 +225,9 @@ namespace BizHawk.Client.Common
public void GreenzoneCurrentFrame()
{
- if (Global.Emulator.Frame > LastValidFrame)
+ // todo: this isn't working quite right when autorestore is off and we're editing while seeking
+ // but accounting for that requires access to Mainform.IsSeeking
+ if (Global.Emulator.Frame > LastEditedFrame)
{
// emulated a new frame, current editing segment may change now. taseditor logic
LastPositionStable = false;
diff --git a/BizHawk.Client.EmuHawk/AboutBox.cs b/BizHawk.Client.EmuHawk/AboutBox.cs
index 92817df5bc..cf4643b863 100644
--- a/BizHawk.Client.EmuHawk/AboutBox.cs
+++ b/BizHawk.Client.EmuHawk/AboutBox.cs
@@ -163,24 +163,16 @@ namespace BizHawk.Client.EmuHawk
private void AboutBox_Load(object sender, EventArgs e)
{
#if DEBUG
- Text = $"BizHawk Developer Build (DEBUG MODE) GIT {SubWCRev.GIT_BRANCH}#{SubWCRev.GIT_SHORTHASH}";
+ Text = $"BizHawk Developer Build (DEBUG MODE) GIT {SubWCRev.GIT_BRANCH}#{SubWCRev.GIT_SHORTHASH}";
#else
Text = $"BizHawk Developer Build (RELEASE MODE) GIT {SubWCRev.GIT_BRANCH}#{SubWCRev.GIT_SHORTHASH}";
#endif
- if (DateTime.Now.Month == 12)
+ if (DateTime.Now.Month == 12)
+ {
if (DateTime.Now.Day > 17 && DateTime.Now.Day <= 25)
{
pictureBox1.Image = Properties.Resources.alt_about_image;
}
-
- if (DateTime.Now.Month == 2)
- {
- if (DateTime.Now.Day >= 7 && DateTime.Now.Day <= 14)
- {
- pictureBox1.Image = Properties.Resources.HawkInLove;
- pictureBox1.Location = new Point(pictureBox1.Location.X - 40, pictureBox1.Location.Y);
- pictureBox1.Width = pictureBox1.Width + 80;
- }
}
}
diff --git a/BizHawk.Client.EmuHawk/Communication.cs b/BizHawk.Client.EmuHawk/Communication.cs
index ca6bd4b421..a1a466dae5 100644
--- a/BizHawk.Client.EmuHawk/Communication.cs
+++ b/BizHawk.Client.EmuHawk/Communication.cs
@@ -165,7 +165,7 @@ namespace BizHawk.Client.EmuHawk
}
}
- Decoder decoder = Encoding.UTF8.GetDecoder();
+ readonly Decoder decoder = Encoding.UTF8.GetDecoder();
Socket soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipAdd;
IPEndPoint remoteEP;
@@ -175,19 +175,14 @@ namespace BizHawk.Client.EmuHawk
public int Retries { get; set; } = 10;
public bool success = false; //indicates whether the last command was executed succesfully
- public void Initialize(IVideoProvider _currentVideoProvider)
+ public void Initialize()
{
- currentVideoProvider = _currentVideoProvider;
- SetIp(ip, port);
+ if (currentVideoProvider == null) currentVideoProvider = Global.Emulator.AsVideoProviderOrDefault();
initialized = true;
}
public void Connect()
{
- if (!initialized)
- {
- Initialize(currentVideoProvider);
- }
remoteEP = new IPEndPoint(ipAdd, port);
soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
soc.Connect(remoteEP);
@@ -200,7 +195,7 @@ namespace BizHawk.Client.EmuHawk
ip = ip_;
port = port_;
ipAdd = System.Net.IPAddress.Parse(ip);
- remoteEP = new IPEndPoint(ipAdd, port);
+ Connect();
}
public string GetInfo()
@@ -248,9 +243,9 @@ namespace BizHawk.Client.EmuHawk
public string SendScreenshot(int waitingTime)
{
- if (!connected)
+ if (!initialized)
{
- Connect();
+ Initialize();
}
ScreenShot screenShot = new ScreenShot();
using (BitmapBuffer bb = screenShot.MakeScreenShotImage())
diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs
index 6ec93e6d70..bbb6ac98f6 100644
--- a/BizHawk.Client.EmuHawk/MainForm.cs
+++ b/BizHawk.Client.EmuHawk/MainForm.cs
@@ -1911,7 +1911,13 @@ namespace BizHawk.Client.EmuHawk
private void SetPauseStatusbarIcon()
{
- if (IsTurboSeeking)
+ if (EmulatorPaused)
+ {
+ PauseStatusButton.Image = Properties.Resources.Pause;
+ PauseStatusButton.Visible = true;
+ PauseStatusButton.ToolTipText = "Emulator Paused";
+ }
+ else if (IsTurboSeeking)
{
PauseStatusButton.Image = Properties.Resources.Lightning;
PauseStatusButton.Visible = true;
@@ -1923,12 +1929,6 @@ namespace BizHawk.Client.EmuHawk
PauseStatusButton.Visible = true;
PauseStatusButton.ToolTipText = $"Emulator is playing to frame {PauseOnFrame.Value} click to stop seek";
}
- else if (EmulatorPaused)
- {
- PauseStatusButton.Image = Properties.Resources.Pause;
- PauseStatusButton.Visible = true;
- PauseStatusButton.ToolTipText = "Emulator Paused";
- }
else
{
PauseStatusButton.Image = Properties.Resources.Blank;
@@ -2023,7 +2023,7 @@ namespace BizHawk.Client.EmuHawk
}
}
- private BitmapBuffer MakeScreenshotImage()
+ public BitmapBuffer MakeScreenshotImage()
{
return GlobalWin.DisplayManager.RenderVideoProvider(_currentVideoProvider);
}
diff --git a/BizHawk.Client.EmuHawk/Properties/Resources.Designer.cs b/BizHawk.Client.EmuHawk/Properties/Resources.Designer.cs
index 8cb04e3e15..d9e97b6eff 100644
--- a/BizHawk.Client.EmuHawk/Properties/Resources.Designer.cs
+++ b/BizHawk.Client.EmuHawk/Properties/Resources.Designer.cs
@@ -19,7 +19,7 @@ namespace BizHawk.Client.EmuHawk.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@@ -690,16 +690,6 @@ namespace BizHawk.Client.EmuHawk.Properties {
}
}
- ///
- /// Looks up a localized resource of type System.Drawing.Bitmap.
- ///
- internal static System.Drawing.Bitmap HawkInLove {
- get {
- object obj = ResourceManager.GetObject("HawkInLove", resourceCulture);
- return ((System.Drawing.Bitmap)(obj));
- }
- }
-
///
/// Looks up a localized resource of type System.Drawing.Bitmap.
///
diff --git a/BizHawk.Client.EmuHawk/Properties/Resources.resx b/BizHawk.Client.EmuHawk/Properties/Resources.resx
index 301536707a..1876bfb3b7 100644
--- a/BizHawk.Client.EmuHawk/Properties/Resources.resx
+++ b/BizHawk.Client.EmuHawk/Properties/Resources.resx
@@ -1455,9 +1455,6 @@
..\images\tastudio\ts_h_piano_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
- ..\images\HawkInLove.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
..\images\tastudio\ts_h_piano_00_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
diff --git a/BizHawk.Client.EmuHawk/Resources/MoveBottom.png b/BizHawk.Client.EmuHawk/Resources/MoveBottom.png
index 7befbdd795..b79e61272a 100644
Binary files a/BizHawk.Client.EmuHawk/Resources/MoveBottom.png and b/BizHawk.Client.EmuHawk/Resources/MoveBottom.png differ
diff --git a/BizHawk.Client.EmuHawk/Resources/MoveTop.png b/BizHawk.Client.EmuHawk/Resources/MoveTop.png
index 397032df28..fd7f8593d2 100644
Binary files a/BizHawk.Client.EmuHawk/Resources/MoveTop.png and b/BizHawk.Client.EmuHawk/Resources/MoveTop.png differ
diff --git a/BizHawk.Client.EmuHawk/Resources/courier16px_0.png b/BizHawk.Client.EmuHawk/Resources/courier16px_0.png
index c73de1e864..414e067c56 100644
Binary files a/BizHawk.Client.EmuHawk/Resources/courier16px_0.png and b/BizHawk.Client.EmuHawk/Resources/courier16px_0.png differ
diff --git a/BizHawk.Client.EmuHawk/config/ControllerImages/C64Joystick.png b/BizHawk.Client.EmuHawk/config/ControllerImages/C64Joystick.png
index d5ce8bde37..3069753d0c 100644
Binary files a/BizHawk.Client.EmuHawk/config/ControllerImages/C64Joystick.png and b/BizHawk.Client.EmuHawk/config/ControllerImages/C64Joystick.png differ
diff --git a/BizHawk.Client.EmuHawk/config/ControllerImages/GBA_Controller.png b/BizHawk.Client.EmuHawk/config/ControllerImages/GBA_Controller.png
index 9eee422dc5..1311133ffd 100644
Binary files a/BizHawk.Client.EmuHawk/config/ControllerImages/GBA_Controller.png and b/BizHawk.Client.EmuHawk/config/ControllerImages/GBA_Controller.png differ
diff --git a/BizHawk.Client.EmuHawk/config/ControllerImages/IntVController.png b/BizHawk.Client.EmuHawk/config/ControllerImages/IntVController.png
index 0a6fe8b09f..3f52174551 100644
Binary files a/BizHawk.Client.EmuHawk/config/ControllerImages/IntVController.png and b/BizHawk.Client.EmuHawk/config/ControllerImages/IntVController.png differ
diff --git a/BizHawk.Client.EmuHawk/config/ControllerImages/N64.png b/BizHawk.Client.EmuHawk/config/ControllerImages/N64.png
index d4403059a9..85255b7a73 100644
Binary files a/BizHawk.Client.EmuHawk/config/ControllerImages/N64.png and b/BizHawk.Client.EmuHawk/config/ControllerImages/N64.png differ
diff --git a/BizHawk.Client.EmuHawk/config/ControllerImages/NES_Controller.png b/BizHawk.Client.EmuHawk/config/ControllerImages/NES_Controller.png
index da59820a7d..242c232a0f 100644
Binary files a/BizHawk.Client.EmuHawk/config/ControllerImages/NES_Controller.png and b/BizHawk.Client.EmuHawk/config/ControllerImages/NES_Controller.png differ
diff --git a/BizHawk.Client.EmuHawk/config/ControllerImages/SMSController.png b/BizHawk.Client.EmuHawk/config/ControllerImages/SMSController.png
index 7ebf0fe021..5a735e54ef 100644
Binary files a/BizHawk.Client.EmuHawk/config/ControllerImages/SMSController.png and b/BizHawk.Client.EmuHawk/config/ControllerImages/SMSController.png differ
diff --git a/BizHawk.Client.EmuHawk/config/ControllerImages/WonderSwanColor.png b/BizHawk.Client.EmuHawk/config/ControllerImages/WonderSwanColor.png
index e6ef63cd48..996fb672ef 100644
Binary files a/BizHawk.Client.EmuHawk/config/ControllerImages/WonderSwanColor.png and b/BizHawk.Client.EmuHawk/config/ControllerImages/WonderSwanColor.png differ
diff --git a/BizHawk.Client.EmuHawk/config/ControllerImages/ZXSpectrumKeyboards.png b/BizHawk.Client.EmuHawk/config/ControllerImages/ZXSpectrumKeyboards.png
index 1af85ebea9..6dbf138700 100644
Binary files a/BizHawk.Client.EmuHawk/config/ControllerImages/ZXSpectrumKeyboards.png and b/BizHawk.Client.EmuHawk/config/ControllerImages/ZXSpectrumKeyboards.png differ
diff --git a/BizHawk.Client.EmuHawk/config/ControllerImages/psx_dualshock.png b/BizHawk.Client.EmuHawk/config/ControllerImages/psx_dualshock.png
index 3ca47a305a..2fe9d86ad4 100644
Binary files a/BizHawk.Client.EmuHawk/config/ControllerImages/psx_dualshock.png and b/BizHawk.Client.EmuHawk/config/ControllerImages/psx_dualshock.png differ
diff --git a/BizHawk.Client.EmuHawk/images/AVI.png b/BizHawk.Client.EmuHawk/images/AVI.png
index 47f3216425..e4f3742164 100644
Binary files a/BizHawk.Client.EmuHawk/images/AVI.png and b/BizHawk.Client.EmuHawk/images/AVI.png differ
diff --git a/BizHawk.Client.EmuHawk/images/AddEdit.png b/BizHawk.Client.EmuHawk/images/AddEdit.png
index 73c6ebf990..84a165703d 100644
Binary files a/BizHawk.Client.EmuHawk/images/AddEdit.png and b/BizHawk.Client.EmuHawk/images/AddEdit.png differ
diff --git a/BizHawk.Client.EmuHawk/images/AtariControllerIcon.png b/BizHawk.Client.EmuHawk/images/AtariControllerIcon.png
index 2d2444e123..1eec649c37 100644
Binary files a/BizHawk.Client.EmuHawk/images/AtariControllerIcon.png and b/BizHawk.Client.EmuHawk/images/AtariControllerIcon.png differ
diff --git a/BizHawk.Client.EmuHawk/images/AudioHS.png b/BizHawk.Client.EmuHawk/images/AudioHS.png
index 614cc0da98..4f1bc9fe33 100644
Binary files a/BizHawk.Client.EmuHawk/images/AudioHS.png and b/BizHawk.Client.EmuHawk/images/AudioHS.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Back.png b/BizHawk.Client.EmuHawk/images/Back.png
index 74c21f21c3..1b8ad526c8 100644
Binary files a/BizHawk.Client.EmuHawk/images/Back.png and b/BizHawk.Client.EmuHawk/images/Back.png differ
diff --git a/BizHawk.Client.EmuHawk/images/BackMore.png b/BizHawk.Client.EmuHawk/images/BackMore.png
index f399933f9b..563aba269c 100644
Binary files a/BizHawk.Client.EmuHawk/images/BackMore.png and b/BizHawk.Client.EmuHawk/images/BackMore.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Blank.png b/BizHawk.Client.EmuHawk/images/Blank.png
index ab2a9ccc02..c8d0a51cc0 100644
Binary files a/BizHawk.Client.EmuHawk/images/Blank.png and b/BizHawk.Client.EmuHawk/images/Blank.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Both.png b/BizHawk.Client.EmuHawk/images/Both.png
index a949badfe7..f4c909befb 100644
Binary files a/BizHawk.Client.EmuHawk/images/Both.png and b/BizHawk.Client.EmuHawk/images/Both.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Bug.png b/BizHawk.Client.EmuHawk/images/Bug.png
index 9b7265b3e9..cb2097b36c 100644
Binary files a/BizHawk.Client.EmuHawk/images/Bug.png and b/BizHawk.Client.EmuHawk/images/Bug.png differ
diff --git a/BizHawk.Client.EmuHawk/images/C64Symbol.png b/BizHawk.Client.EmuHawk/images/C64Symbol.png
index cf51f73786..ca6410a7bf 100644
Binary files a/BizHawk.Client.EmuHawk/images/C64Symbol.png and b/BizHawk.Client.EmuHawk/images/C64Symbol.png differ
diff --git a/BizHawk.Client.EmuHawk/images/ControllerImages/AppleIIKeyboard.png b/BizHawk.Client.EmuHawk/images/ControllerImages/AppleIIKeyboard.png
index 519910281d..0d048366d3 100644
Binary files a/BizHawk.Client.EmuHawk/images/ControllerImages/AppleIIKeyboard.png and b/BizHawk.Client.EmuHawk/images/ControllerImages/AppleIIKeyboard.png differ
diff --git a/BizHawk.Client.EmuHawk/images/ControllerImages/C64Joystick.png b/BizHawk.Client.EmuHawk/images/ControllerImages/C64Joystick.png
index d5ce8bde37..f3b4eec4cf 100644
Binary files a/BizHawk.Client.EmuHawk/images/ControllerImages/C64Joystick.png and b/BizHawk.Client.EmuHawk/images/ControllerImages/C64Joystick.png differ
diff --git a/BizHawk.Client.EmuHawk/images/ControllerImages/GBA_Controller.png b/BizHawk.Client.EmuHawk/images/ControllerImages/GBA_Controller.png
index 9eee422dc5..1311133ffd 100644
Binary files a/BizHawk.Client.EmuHawk/images/ControllerImages/GBA_Controller.png and b/BizHawk.Client.EmuHawk/images/ControllerImages/GBA_Controller.png differ
diff --git a/BizHawk.Client.EmuHawk/images/ControllerImages/IntVController.png b/BizHawk.Client.EmuHawk/images/ControllerImages/IntVController.png
index 0a6fe8b09f..941d7fc796 100644
Binary files a/BizHawk.Client.EmuHawk/images/ControllerImages/IntVController.png and b/BizHawk.Client.EmuHawk/images/ControllerImages/IntVController.png differ
diff --git a/BizHawk.Client.EmuHawk/images/ControllerImages/N64.png b/BizHawk.Client.EmuHawk/images/ControllerImages/N64.png
index d4403059a9..85255b7a73 100644
Binary files a/BizHawk.Client.EmuHawk/images/ControllerImages/N64.png and b/BizHawk.Client.EmuHawk/images/ControllerImages/N64.png differ
diff --git a/BizHawk.Client.EmuHawk/images/ControllerImages/NES_Controller.png b/BizHawk.Client.EmuHawk/images/ControllerImages/NES_Controller.png
index da59820a7d..242c232a0f 100644
Binary files a/BizHawk.Client.EmuHawk/images/ControllerImages/NES_Controller.png and b/BizHawk.Client.EmuHawk/images/ControllerImages/NES_Controller.png differ
diff --git a/BizHawk.Client.EmuHawk/images/ControllerImages/SMSController.png b/BizHawk.Client.EmuHawk/images/ControllerImages/SMSController.png
index 7ebf0fe021..c2743fde2d 100644
Binary files a/BizHawk.Client.EmuHawk/images/ControllerImages/SMSController.png and b/BizHawk.Client.EmuHawk/images/ControllerImages/SMSController.png differ
diff --git a/BizHawk.Client.EmuHawk/images/ControllerImages/VBoyController.png b/BizHawk.Client.EmuHawk/images/ControllerImages/VBoyController.png
index 59bef68ff7..ce679b95bb 100644
Binary files a/BizHawk.Client.EmuHawk/images/ControllerImages/VBoyController.png and b/BizHawk.Client.EmuHawk/images/ControllerImages/VBoyController.png differ
diff --git a/BizHawk.Client.EmuHawk/images/ControllerImages/WonderSwanColor.png b/BizHawk.Client.EmuHawk/images/ControllerImages/WonderSwanColor.png
index e6ef63cd48..5aeb1819c3 100644
Binary files a/BizHawk.Client.EmuHawk/images/ControllerImages/WonderSwanColor.png and b/BizHawk.Client.EmuHawk/images/ControllerImages/WonderSwanColor.png differ
diff --git a/BizHawk.Client.EmuHawk/images/ControllerImages/psx_dualshock.png b/BizHawk.Client.EmuHawk/images/ControllerImages/psx_dualshock.png
index 3ca47a305a..b394db13e7 100644
Binary files a/BizHawk.Client.EmuHawk/images/ControllerImages/psx_dualshock.png and b/BizHawk.Client.EmuHawk/images/ControllerImages/psx_dualshock.png differ
diff --git a/BizHawk.Client.EmuHawk/images/CorpHawkSmall.png b/BizHawk.Client.EmuHawk/images/CorpHawkSmall.png
index c17d8dc028..db344c01a2 100644
Binary files a/BizHawk.Client.EmuHawk/images/CorpHawkSmall.png and b/BizHawk.Client.EmuHawk/images/CorpHawkSmall.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Cross.png b/BizHawk.Client.EmuHawk/images/Cross.png
index 28a9c09f8d..723be03ccd 100644
Binary files a/BizHawk.Client.EmuHawk/images/Cross.png and b/BizHawk.Client.EmuHawk/images/Cross.png differ
diff --git a/BizHawk.Client.EmuHawk/images/CutHS.png b/BizHawk.Client.EmuHawk/images/CutHS.png
index 449f92f08c..dd40e93a2a 100644
Binary files a/BizHawk.Client.EmuHawk/images/CutHS.png and b/BizHawk.Client.EmuHawk/images/CutHS.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Delete.png b/BizHawk.Client.EmuHawk/images/Delete.png
index 16f24e0de8..98950c75ce 100644
Binary files a/BizHawk.Client.EmuHawk/images/Delete.png and b/BizHawk.Client.EmuHawk/images/Delete.png differ
diff --git a/BizHawk.Client.EmuHawk/images/ENE.png b/BizHawk.Client.EmuHawk/images/ENE.png
index 48ea5e0e5a..fc3b12cd0e 100644
Binary files a/BizHawk.Client.EmuHawk/images/ENE.png and b/BizHawk.Client.EmuHawk/images/ENE.png differ
diff --git a/BizHawk.Client.EmuHawk/images/ESE.png b/BizHawk.Client.EmuHawk/images/ESE.png
index 8bc8c0cc18..8c36e1b06b 100644
Binary files a/BizHawk.Client.EmuHawk/images/ESE.png and b/BizHawk.Client.EmuHawk/images/ESE.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Erase.png b/BizHawk.Client.EmuHawk/images/Erase.png
index 6b716c3dc0..7ccec56a31 100644
Binary files a/BizHawk.Client.EmuHawk/images/Erase.png and b/BizHawk.Client.EmuHawk/images/Erase.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Freeze.png b/BizHawk.Client.EmuHawk/images/Freeze.png
index 8707356101..1501801931 100644
Binary files a/BizHawk.Client.EmuHawk/images/Freeze.png and b/BizHawk.Client.EmuHawk/images/Freeze.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Fullscreen.png b/BizHawk.Client.EmuHawk/images/Fullscreen.png
index d57607a351..c2547efd2f 100644
Binary files a/BizHawk.Client.EmuHawk/images/Fullscreen.png and b/BizHawk.Client.EmuHawk/images/Fullscreen.png differ
diff --git a/BizHawk.Client.EmuHawk/images/GameController.png b/BizHawk.Client.EmuHawk/images/GameController.png
index 268da4cbe6..3d0131cd16 100644
Binary files a/BizHawk.Client.EmuHawk/images/GameController.png and b/BizHawk.Client.EmuHawk/images/GameController.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Hack.png b/BizHawk.Client.EmuHawk/images/Hack.png
index cc95ab4e30..04a83ddc6a 100644
Binary files a/BizHawk.Client.EmuHawk/images/Hack.png and b/BizHawk.Client.EmuHawk/images/Hack.png differ
diff --git a/BizHawk.Client.EmuHawk/images/HawkInLove.png b/BizHawk.Client.EmuHawk/images/HawkInLove.png
deleted file mode 100644
index e29af04f0e..0000000000
Binary files a/BizHawk.Client.EmuHawk/images/HawkInLove.png and /dev/null differ
diff --git a/BizHawk.Client.EmuHawk/images/HomeBrew.png b/BizHawk.Client.EmuHawk/images/HomeBrew.png
index f14d7d4cda..bf44aef86f 100644
Binary files a/BizHawk.Client.EmuHawk/images/HomeBrew.png and b/BizHawk.Client.EmuHawk/images/HomeBrew.png differ
diff --git a/BizHawk.Client.EmuHawk/images/HotKeys.png b/BizHawk.Client.EmuHawk/images/HotKeys.png
index 56967c36bf..962eb51ed7 100644
Binary files a/BizHawk.Client.EmuHawk/images/HotKeys.png and b/BizHawk.Client.EmuHawk/images/HotKeys.png differ
diff --git a/BizHawk.Client.EmuHawk/images/JumpTo.png b/BizHawk.Client.EmuHawk/images/JumpTo.png
index 733adba85c..333ac7cd45 100644
Binary files a/BizHawk.Client.EmuHawk/images/JumpTo.png and b/BizHawk.Client.EmuHawk/images/JumpTo.png differ
diff --git a/BizHawk.Client.EmuHawk/images/LightOff.png b/BizHawk.Client.EmuHawk/images/LightOff.png
index 82ef6b0df2..14c35ff3fe 100644
Binary files a/BizHawk.Client.EmuHawk/images/LightOff.png and b/BizHawk.Client.EmuHawk/images/LightOff.png differ
diff --git a/BizHawk.Client.EmuHawk/images/LightOn.png b/BizHawk.Client.EmuHawk/images/LightOn.png
index 3390074dea..5f0675db49 100644
Binary files a/BizHawk.Client.EmuHawk/images/LightOn.png and b/BizHawk.Client.EmuHawk/images/LightOn.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Lua.png b/BizHawk.Client.EmuHawk/images/Lua.png
index 34e6f4d65b..05dc80a0c0 100644
Binary files a/BizHawk.Client.EmuHawk/images/Lua.png and b/BizHawk.Client.EmuHawk/images/Lua.png differ
diff --git a/BizHawk.Client.EmuHawk/images/NE.png b/BizHawk.Client.EmuHawk/images/NE.png
index 982a3b242d..2e27de59ef 100644
Binary files a/BizHawk.Client.EmuHawk/images/NE.png and b/BizHawk.Client.EmuHawk/images/NE.png differ
diff --git a/BizHawk.Client.EmuHawk/images/NNE.png b/BizHawk.Client.EmuHawk/images/NNE.png
index ea2dc3655e..7f55925d39 100644
Binary files a/BizHawk.Client.EmuHawk/images/NNE.png and b/BizHawk.Client.EmuHawk/images/NNE.png differ
diff --git a/BizHawk.Client.EmuHawk/images/NNW.png b/BizHawk.Client.EmuHawk/images/NNW.png
index f8788da18e..839e95600d 100644
Binary files a/BizHawk.Client.EmuHawk/images/NNW.png and b/BizHawk.Client.EmuHawk/images/NNW.png differ
diff --git a/BizHawk.Client.EmuHawk/images/NW.png b/BizHawk.Client.EmuHawk/images/NW.png
index e732d7233f..2f376bb299 100644
Binary files a/BizHawk.Client.EmuHawk/images/NW.png and b/BizHawk.Client.EmuHawk/images/NW.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Pause.png b/BizHawk.Client.EmuHawk/images/Pause.png
index 302f04ba75..f6dfbfb1a5 100644
Binary files a/BizHawk.Client.EmuHawk/images/Pause.png and b/BizHawk.Client.EmuHawk/images/Pause.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Play.png b/BizHawk.Client.EmuHawk/images/Play.png
index 8773c25147..b13bd6912b 100644
Binary files a/BizHawk.Client.EmuHawk/images/Play.png and b/BizHawk.Client.EmuHawk/images/Play.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Previous.png b/BizHawk.Client.EmuHawk/images/Previous.png
index 1789227599..e20b73c2d8 100644
Binary files a/BizHawk.Client.EmuHawk/images/Previous.png and b/BizHawk.Client.EmuHawk/images/Previous.png differ
diff --git a/BizHawk.Client.EmuHawk/images/QuickNes.png b/BizHawk.Client.EmuHawk/images/QuickNes.png
index 5792558e8a..1d709201f6 100644
Binary files a/BizHawk.Client.EmuHawk/images/QuickNes.png and b/BizHawk.Client.EmuHawk/images/QuickNes.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Recent.png b/BizHawk.Client.EmuHawk/images/Recent.png
index bf4416d175..140eb751ba 100644
Binary files a/BizHawk.Client.EmuHawk/images/Recent.png and b/BizHawk.Client.EmuHawk/images/Recent.png differ
diff --git a/BizHawk.Client.EmuHawk/images/RecordHS.png b/BizHawk.Client.EmuHawk/images/RecordHS.png
index a75db7757e..a3755cc02c 100644
Binary files a/BizHawk.Client.EmuHawk/images/RecordHS.png and b/BizHawk.Client.EmuHawk/images/RecordHS.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Refresh.png b/BizHawk.Client.EmuHawk/images/Refresh.png
index 5d9a1a7766..b367d1b1e1 100644
Binary files a/BizHawk.Client.EmuHawk/images/Refresh.png and b/BizHawk.Client.EmuHawk/images/Refresh.png differ
diff --git a/BizHawk.Client.EmuHawk/images/RetroQuestion.png b/BizHawk.Client.EmuHawk/images/RetroQuestion.png
index 8eb1682b39..ea5d4a0120 100644
Binary files a/BizHawk.Client.EmuHawk/images/RetroQuestion.png and b/BizHawk.Client.EmuHawk/images/RetroQuestion.png differ
diff --git a/BizHawk.Client.EmuHawk/images/SE.png b/BizHawk.Client.EmuHawk/images/SE.png
index d0ac5e9075..47df429af2 100644
Binary files a/BizHawk.Client.EmuHawk/images/SE.png and b/BizHawk.Client.EmuHawk/images/SE.png differ
diff --git a/BizHawk.Client.EmuHawk/images/SSE.png b/BizHawk.Client.EmuHawk/images/SSE.png
index b31f29ddea..3dc165ccaf 100644
Binary files a/BizHawk.Client.EmuHawk/images/SSE.png and b/BizHawk.Client.EmuHawk/images/SSE.png differ
diff --git a/BizHawk.Client.EmuHawk/images/SSW.png b/BizHawk.Client.EmuHawk/images/SSW.png
index 4f7bd90358..5356f11e25 100644
Binary files a/BizHawk.Client.EmuHawk/images/SSW.png and b/BizHawk.Client.EmuHawk/images/SSW.png differ
diff --git a/BizHawk.Client.EmuHawk/images/SW.png b/BizHawk.Client.EmuHawk/images/SW.png
index e242a310be..0d00fdd174 100644
Binary files a/BizHawk.Client.EmuHawk/images/SW.png and b/BizHawk.Client.EmuHawk/images/SW.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Save.png b/BizHawk.Client.EmuHawk/images/Save.png
index b0ce1f9f55..89146b4c26 100644
Binary files a/BizHawk.Client.EmuHawk/images/Save.png and b/BizHawk.Client.EmuHawk/images/Save.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Scan.png b/BizHawk.Client.EmuHawk/images/Scan.png
index 7bb7d4092e..bab8c127f9 100644
Binary files a/BizHawk.Client.EmuHawk/images/Scan.png and b/BizHawk.Client.EmuHawk/images/Scan.png differ
diff --git a/BizHawk.Client.EmuHawk/images/ScrollTo.png b/BizHawk.Client.EmuHawk/images/ScrollTo.png
index 4429e339c5..904c3b5e32 100644
Binary files a/BizHawk.Client.EmuHawk/images/ScrollTo.png and b/BizHawk.Client.EmuHawk/images/ScrollTo.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Shark.png b/BizHawk.Client.EmuHawk/images/Shark.png
index e6ff5fb55b..97a96445a5 100644
Binary files a/BizHawk.Client.EmuHawk/images/Shark.png and b/BizHawk.Client.EmuHawk/images/Shark.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Stop.png b/BizHawk.Client.EmuHawk/images/Stop.png
index a62d26f71b..18cb7f82a0 100644
Binary files a/BizHawk.Client.EmuHawk/images/Stop.png and b/BizHawk.Client.EmuHawk/images/Stop.png differ
diff --git a/BizHawk.Client.EmuHawk/images/TAStudio.png b/BizHawk.Client.EmuHawk/images/TAStudio.png
index 65cd18bbe6..3adc639400 100644
Binary files a/BizHawk.Client.EmuHawk/images/TAStudio.png and b/BizHawk.Client.EmuHawk/images/TAStudio.png differ
diff --git a/BizHawk.Client.EmuHawk/images/ToolBox.png b/BizHawk.Client.EmuHawk/images/ToolBox.png
index aed1f9c643..583e30faee 100644
Binary files a/BizHawk.Client.EmuHawk/images/ToolBox.png and b/BizHawk.Client.EmuHawk/images/ToolBox.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Translation.png b/BizHawk.Client.EmuHawk/images/Translation.png
index 2ddedbb605..dcbdebb17f 100644
Binary files a/BizHawk.Client.EmuHawk/images/Translation.png and b/BizHawk.Client.EmuHawk/images/Translation.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Triangle.png b/BizHawk.Client.EmuHawk/images/Triangle.png
index 39562995ec..04ba91aad6 100644
Binary files a/BizHawk.Client.EmuHawk/images/Triangle.png and b/BizHawk.Client.EmuHawk/images/Triangle.png differ
diff --git a/BizHawk.Client.EmuHawk/images/TruncateFromFile.png b/BizHawk.Client.EmuHawk/images/TruncateFromFile.png
index af595112ad..ee3058b192 100644
Binary files a/BizHawk.Client.EmuHawk/images/TruncateFromFile.png and b/BizHawk.Client.EmuHawk/images/TruncateFromFile.png differ
diff --git a/BizHawk.Client.EmuHawk/images/TruncateFromRW.png b/BizHawk.Client.EmuHawk/images/TruncateFromRW.png
index 1a33ab58c1..5637de4bb1 100644
Binary files a/BizHawk.Client.EmuHawk/images/TruncateFromRW.png and b/BizHawk.Client.EmuHawk/images/TruncateFromRW.png differ
diff --git a/BizHawk.Client.EmuHawk/images/TurboFastForward.png b/BizHawk.Client.EmuHawk/images/TurboFastForward.png
index 01006b0bbf..016611d269 100644
Binary files a/BizHawk.Client.EmuHawk/images/TurboFastForward.png and b/BizHawk.Client.EmuHawk/images/TurboFastForward.png differ
diff --git a/BizHawk.Client.EmuHawk/images/Unfreeze.png b/BizHawk.Client.EmuHawk/images/Unfreeze.png
index ac0d6da1d3..38bb5caaad 100644
Binary files a/BizHawk.Client.EmuHawk/images/Unfreeze.png and b/BizHawk.Client.EmuHawk/images/Unfreeze.png differ
diff --git a/BizHawk.Client.EmuHawk/images/YellowLeft.png b/BizHawk.Client.EmuHawk/images/YellowLeft.png
index 517ab4c4e6..196eba2146 100644
Binary files a/BizHawk.Client.EmuHawk/images/YellowLeft.png and b/BizHawk.Client.EmuHawk/images/YellowLeft.png differ
diff --git a/BizHawk.Client.EmuHawk/images/camera.png b/BizHawk.Client.EmuHawk/images/camera.png
index 21b72b07fa..9a3711bc0d 100644
Binary files a/BizHawk.Client.EmuHawk/images/camera.png and b/BizHawk.Client.EmuHawk/images/camera.png differ
diff --git a/BizHawk.Client.EmuHawk/images/cheat.png b/BizHawk.Client.EmuHawk/images/cheat.png
index 83449e7c91..438fcef00d 100644
Binary files a/BizHawk.Client.EmuHawk/images/cheat.png and b/BizHawk.Client.EmuHawk/images/cheat.png differ
diff --git a/BizHawk.Client.EmuHawk/images/corphawk.jpg b/BizHawk.Client.EmuHawk/images/corphawk.jpg
index 5c65d2d271..31fdb8d27b 100644
Binary files a/BizHawk.Client.EmuHawk/images/corphawk.jpg and b/BizHawk.Client.EmuHawk/images/corphawk.jpg differ
diff --git a/BizHawk.Client.EmuHawk/images/dual.png b/BizHawk.Client.EmuHawk/images/dual.png
index 37fd7b0806..e70e7a9631 100644
Binary files a/BizHawk.Client.EmuHawk/images/dual.png and b/BizHawk.Client.EmuHawk/images/dual.png differ
diff --git a/BizHawk.Client.EmuHawk/images/gambatte.png b/BizHawk.Client.EmuHawk/images/gambatte.png
index 7a3de1551d..f4e93be9f0 100644
Binary files a/BizHawk.Client.EmuHawk/images/gambatte.png and b/BizHawk.Client.EmuHawk/images/gambatte.png differ
diff --git a/BizHawk.Client.EmuHawk/images/gba-icon.png b/BizHawk.Client.EmuHawk/images/gba-icon.png
index 635c3488ee..e907e1810f 100644
Binary files a/BizHawk.Client.EmuHawk/images/gba-icon.png and b/BizHawk.Client.EmuHawk/images/gba-icon.png differ
diff --git a/BizHawk.Client.EmuHawk/images/kitchensink.png b/BizHawk.Client.EmuHawk/images/kitchensink.png
index b5453eb3f2..2e8d5ed6fe 100644
Binary files a/BizHawk.Client.EmuHawk/images/kitchensink.png and b/BizHawk.Client.EmuHawk/images/kitchensink.png differ
diff --git a/BizHawk.Client.EmuHawk/images/monitor.png b/BizHawk.Client.EmuHawk/images/monitor.png
index 93bf3ec5e1..99719269ad 100644
Binary files a/BizHawk.Client.EmuHawk/images/monitor.png and b/BizHawk.Client.EmuHawk/images/monitor.png differ
diff --git a/BizHawk.Client.EmuHawk/images/pcb.png b/BizHawk.Client.EmuHawk/images/pcb.png
index f24421c2a4..19dc0eaa8a 100644
Binary files a/BizHawk.Client.EmuHawk/images/pcb.png and b/BizHawk.Client.EmuHawk/images/pcb.png differ
diff --git a/BizHawk.Client.EmuHawk/images/reboot.png b/BizHawk.Client.EmuHawk/images/reboot.png
index f7ef40ae9b..ac0a762ca3 100644
Binary files a/BizHawk.Client.EmuHawk/images/reboot.png and b/BizHawk.Client.EmuHawk/images/reboot.png differ
diff --git a/BizHawk.Client.EmuHawk/images/redo.png b/BizHawk.Client.EmuHawk/images/redo.png
index 90dd179418..da711c9f77 100644
Binary files a/BizHawk.Client.EmuHawk/images/redo.png and b/BizHawk.Client.EmuHawk/images/redo.png differ
diff --git a/BizHawk.Client.EmuHawk/images/search.png b/BizHawk.Client.EmuHawk/images/search.png
index 4c3145b541..93def76456 100644
Binary files a/BizHawk.Client.EmuHawk/images/search.png and b/BizHawk.Client.EmuHawk/images/search.png differ
diff --git a/BizHawk.Client.EmuHawk/images/sms-icon.png b/BizHawk.Client.EmuHawk/images/sms-icon.png
index cd629ac554..c35da300e3 100644
Binary files a/BizHawk.Client.EmuHawk/images/sms-icon.png and b/BizHawk.Client.EmuHawk/images/sms-icon.png differ
diff --git a/BizHawk.Client.EmuHawk/images/snes9x.png b/BizHawk.Client.EmuHawk/images/snes9x.png
index 61683a0761..6e9127c3b7 100644
Binary files a/BizHawk.Client.EmuHawk/images/snes9x.png and b/BizHawk.Client.EmuHawk/images/snes9x.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/icon_anchor.png b/BizHawk.Client.EmuHawk/images/tastudio/icon_anchor.png
index e0151ac14d..58ca2645e0 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/icon_anchor.png and b/BizHawk.Client.EmuHawk/images/tastudio/icon_anchor.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/icon_anchor_lag.png b/BizHawk.Client.EmuHawk/images/tastudio/icon_anchor_lag.png
index a1f32b6139..473cdd8b5a 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/icon_anchor_lag.png and b/BizHawk.Client.EmuHawk/images/tastudio/icon_anchor_lag.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/icon_marker.png b/BizHawk.Client.EmuHawk/images/tastudio/icon_marker.png
index 8ddcb829ab..c621a6e58c 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/icon_marker.png and b/BizHawk.Client.EmuHawk/images/tastudio/icon_marker.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_arrow_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_arrow_blue.png
index 589f92884a..93b7efc5ff 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_arrow_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_arrow_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_arrow_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_arrow_green.png
index c747468ed9..1b1a2fe43d 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_arrow_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_arrow_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_arrow_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_arrow_green_blue.png
index 0c0c46ae91..84b6b6b37f 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_arrow_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_arrow_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_00.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_00.png
index 955582c9de..d2af2cf074 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_00.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_00.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_00_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_00_blue.png
index e85c941c84..d236c3e659 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_00_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_00_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_00_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_00_green.png
index 89aae3e5e6..b1bad964df 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_00_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_00_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_00_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_00_green_blue.png
index 84e413b9d7..383b843694 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_00_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_00_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_01.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_01.png
index fb4b0e1119..04f68c883b 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_01.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_01.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_01_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_01_blue.png
index 2145f7af09..a93eab372a 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_01_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_01_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_01_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_01_green.png
index cf802a03cd..2c2033bff4 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_01_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_01_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_01_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_01_green_blue.png
index c434f4ae7c..5a96530176 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_01_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_01_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_02_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_02_blue.png
index 8fdcafbab9..90ac8e9f9b 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_02_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_02_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_02_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_02_green.png
index 68fd227ff1..144c9d0ac4 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_02_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_02_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_02_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_02_green_blue.png
index 884b7093ab..190f98a6da 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_02_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_02_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_03.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_03.png
index 78b6f479f6..f350127353 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_03.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_03.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_03_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_03_blue.png
index 11b14ec654..9c75abf03a 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_03_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_03_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_03_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_03_green.png
index fce606eb7c..62cb4a56e1 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_03_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_03_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_03_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_03_green_blue.png
index 0853d47f2e..75f2ec2aa2 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_03_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_03_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_04.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_04.png
index 6ff4fd87ac..bd374bfa19 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_04.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_04.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_04_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_04_blue.png
index eb53fdf764..902b101647 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_04_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_04_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_04_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_04_green.png
index d5f0bcfa42..96cdf6e80d 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_04_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_04_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_04_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_04_green_blue.png
index 96cfc7424e..b00511b112 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_04_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_04_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_05.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_05.png
index 3c629b1cc3..cc9e1f3d57 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_05.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_05.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_05_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_05_blue.png
index 93c0829e8c..a34cbc67ea 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_05_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_05_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_05_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_05_green.png
index 8b88bb7499..ab458b3597 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_05_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_05_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_05_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_05_green_blue.png
index 3f166c65e3..640c6b193e 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_05_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_05_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_06.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_06.png
index cf24acacb8..d22dd800db 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_06.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_06.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_06_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_06_blue.png
index 19d4b10924..1d875273ab 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_06_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_06_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_07.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_07.png
index a4152a6964..dc320f3983 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_07.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_07.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_07_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_07_blue.png
index de5107eb59..704d13df85 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_07_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_07_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_07_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_07_green.png
index 553ebba2de..dd127c5131 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_07_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_07_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_07_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_07_green_blue.png
index 77249f8fc8..98b7f0ddd8 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_07_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_07_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_08.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_08.png
index 98d790ad3a..c586bbef45 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_08.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_08.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_08_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_08_blue.png
index a7ee4658e3..cdfda18798 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_08_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_08_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_08_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_08_green_blue.png
index fc7a5e854b..c3cebe5df4 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_08_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_08_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_09.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_09.png
index be54ece2d3..701228cd44 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_09.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_09.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_09_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_09_blue.png
index d6e8a68f5c..77ae02c825 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_09_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_09_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_09_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_09_green_blue.png
index b89bdba916..591a01615f 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_09_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_09_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_10.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_10.png
index 708b07e0c7..5eed44d710 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_10.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_10.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_10_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_10_blue.png
index bf717ba16e..2d0eead8ff 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_10_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_10_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_10_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_10_green.png
index cc8adf1632..65c449f56b 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_10_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_10_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_10_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_10_green_blue.png
index a2d31643f6..aa7c4247cb 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_10_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_10_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_11.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_11.png
index bc2639c51f..077456b640 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_11.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_11.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_11_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_11_blue.png
index 4359a6d2d7..b4289a1c75 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_11_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_11_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_11_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_11_green.png
index 6a10ced43a..15bc04a92c 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_11_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_11_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_11_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_11_green_blue.png
index a14ae500a3..75806751d7 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_11_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_11_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_12.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_12.png
index 3252ece944..0a75571850 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_12.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_12.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_12_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_12_blue.png
index 475de85df8..d9eb9df449 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_12_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_12_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_13.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_13.png
index 490aeef557..723aed96d8 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_13.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_13.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_13_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_13_blue.png
index fa43a9b3c8..bab5870e54 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_13_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_13_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_14.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_14.png
index 53621e56f1..178932ce73 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_14.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_14.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_14_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_14_blue.png
index 047303d1a7..fc66a2eb9a 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_14_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_14_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_15.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_15.png
index 5525b5527b..3c9504307a 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_15.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_15.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_15_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_15_blue.png
index ec64b938a3..48aa95e245 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_15_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_15_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_16.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_16.png
index 88e85232d6..b4953219c1 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_16.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_16.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_16_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_16_blue.png
index 5f33a16a97..b79ff1ecb0 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_16_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_16_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_16_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_16_green.png
index e32c587ee3..be4847cf8c 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_16_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_16_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_17.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_17.png
index c1f81606fd..fe242b32ca 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_17.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_17.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_17_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_17_blue.png
index a6b1546b2c..eaeb89289d 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_17_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_17_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_18.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_18.png
index efc1b510d8..fa4989476d 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_18.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_18.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_18_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_18_blue.png
index a422f4dabc..29f2393d68 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_18_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_18_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_18_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_18_green.png
index b480d86417..9882f64d1d 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_18_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_18_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_19.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_19.png
index 57efe196f0..3968809aaa 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_19.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_19.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_19_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_19_blue.png
index d1f33ae98e..f998b91f16 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_19_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_19_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_19_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_19_green.png
index 69ae57d3ba..647e76915c 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_19_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_h_piano_19_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_arrow_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_arrow_blue.png
index 9f67151ad7..33849f3ab9 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_arrow_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_arrow_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_arrow_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_arrow_green.png
index e79cee8272..04345ee33c 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_arrow_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_arrow_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_arrow_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_arrow_green_blue.png
index 995c7f34cc..bcabaf0fc1 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_arrow_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_arrow_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_00.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_00.png
index f482e29c53..0f77b87da8 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_00.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_00.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_00_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_00_blue.png
index d097b961c0..fdc73d34cd 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_00_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_00_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_00_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_00_green.png
index 3bea8a7152..3e23b59815 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_00_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_00_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_00_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_00_green_blue.png
index d8c6772442..0ab33c7a8d 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_00_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_00_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_01.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_01.png
index e432d151a7..ed6c045731 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_01.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_01.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_01_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_01_blue.png
index 68e699d2cc..d296a97ce3 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_01_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_01_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_01_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_01_green.png
index fda832b129..5e4ad8631c 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_01_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_01_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_01_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_01_green_blue.png
index 055b5e34ae..e80f5e8c60 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_01_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_01_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_02_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_02_blue.png
index d4c5ae0b78..3a4931530c 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_02_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_02_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_02_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_02_green.png
index 4669b60ea6..64d0a2121a 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_02_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_02_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_02_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_02_green_blue.png
index 3eab16a930..b6d3201bbe 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_02_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_02_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_03.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_03.png
index cb0d3c7d28..90c5caa462 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_03.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_03.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_03_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_03_blue.png
index cf6c18d8f3..e63b858b78 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_03_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_03_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_03_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_03_green.png
index 857f100a8a..cccc2d6b8e 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_03_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_03_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_03_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_03_green_blue.png
index 6b66fec26e..7b510ada1a 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_03_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_03_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_04.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_04.png
index 54dd1fe623..fbc94c764b 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_04.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_04.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_04_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_04_blue.png
index aa9cb05d93..d982e6db78 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_04_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_04_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_04_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_04_green.png
index d63b74ed6a..47e7d3feef 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_04_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_04_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_04_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_04_green_blue.png
index bf32affa9f..f4d6fdb73c 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_04_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_04_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_05.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_05.png
index 82210096a8..2f99722b69 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_05.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_05.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_05_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_05_blue.png
index 34e2f0ca60..5e16817fc1 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_05_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_05_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_05_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_05_green.png
index 50e1d6a5a4..f982c0c603 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_05_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_05_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_05_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_05_green_blue.png
index 6105439cdd..e8a4dac76f 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_05_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_05_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_06.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_06.png
index a9eb98e28a..dd12dd7d66 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_06.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_06.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_06_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_06_blue.png
index b2c4d2d636..bcf476982f 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_06_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_06_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_06_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_06_green.png
index 69f767c496..2c3ea639ab 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_06_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_06_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_06_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_06_green_blue.png
index 9409c4eb32..fc2fd79f0c 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_06_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_06_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_07_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_07_blue.png
index 36cbb17fd8..c95539cd79 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_07_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_07_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_07_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_07_green.png
index 3676cc07ab..4ad5685416 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_07_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_07_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_07_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_07_green_blue.png
index c138d609b2..5a6382f7c6 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_07_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_07_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_08.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_08.png
index 6beb021447..c269f1b3aa 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_08.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_08.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_08_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_08_blue.png
index 731344cb9e..bbd205b88a 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_08_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_08_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_08_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_08_green.png
index 77653b1b0c..0443dbc035 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_08_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_08_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_08_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_08_green_blue.png
index e23bb30670..0b0612619e 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_08_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_08_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_09.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_09.png
index dd1ee94e33..57201a2606 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_09.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_09.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_09_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_09_blue.png
index 48d3d10a33..0a4656ce49 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_09_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_09_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_09_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_09_green.png
index 9951af20be..3fa00948d5 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_09_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_09_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_09_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_09_green_blue.png
index b232aefd36..13b1e08c45 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_09_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_09_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_10.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_10.png
index d963edf154..ab817fb0e0 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_10.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_10.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_10_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_10_blue.png
index 2672096255..87b3f4570b 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_10_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_10_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_10_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_10_green.png
index 1ad36f7523..dc7a634361 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_10_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_10_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_10_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_10_green_blue.png
index ae1a149968..45b4debb10 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_10_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_10_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_11.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_11.png
index b8561b14b4..4547c5ba2d 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_11.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_11.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_11_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_11_blue.png
index 775fbb53e7..5c7d828af3 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_11_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_11_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_11_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_11_green.png
index 2317ef4866..70636584e4 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_11_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_11_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_11_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_11_green_blue.png
index 285e3d08c9..60290be9bc 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_11_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_11_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_12_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_12_blue.png
index e9e033aa71..71fbf7c3e3 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_12_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_12_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_12_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_12_green.png
index b46277ceb4..166901d5d3 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_12_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_12_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_12_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_12_green_blue.png
index f165c1ba36..e21d7e9dba 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_12_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_12_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_13.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_13.png
index 99a7ef48ac..92a328483b 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_13.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_13.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_13_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_13_blue.png
index 103941a3b6..570b2be4a1 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_13_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_13_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_13_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_13_green.png
index 990ae51102..e85bfa92c2 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_13_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_13_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_13_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_13_green_blue.png
index 6a3d1731b2..5f7ecc1878 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_13_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_13_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_14.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_14.png
index d0ff5c07c0..8a694d36fb 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_14.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_14.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_14_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_14_blue.png
index 7e7998a1ea..58e2973cde 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_14_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_14_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_14_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_14_green.png
index 22257c3838..01f9af62d6 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_14_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_14_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_14_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_14_green_blue.png
index 4f47fbdc30..f88b1c9513 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_14_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_14_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_15.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_15.png
index b2b020f0a9..18eadebe92 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_15.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_15.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_15_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_15_blue.png
index 7584278120..d8b61e92db 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_15_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_15_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_15_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_15_green.png
index 3a758eabac..2daee18b9c 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_15_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_15_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_15_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_15_green_blue.png
index 5639415d18..d220c2ba2a 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_15_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_15_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_16.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_16.png
index 3388cbb364..e5e0cd00c6 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_16.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_16.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_16_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_16_blue.png
index f4feefad6e..65816d5f5b 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_16_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_16_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_16_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_16_green.png
index aa5f82770f..4a6a5c0460 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_16_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_16_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_16_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_16_green_blue.png
index 0fcd7276ab..aaea662669 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_16_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_16_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_17.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_17.png
index ceb01571a5..cfa900283e 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_17.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_17.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_17_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_17_blue.png
index d9c446a8de..91557fb136 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_17_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_17_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_17_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_17_green.png
index 9e52809109..757abd1b10 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_17_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_17_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_17_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_17_green_blue.png
index 8d6681c4f6..3b62e96c12 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_17_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_17_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_18.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_18.png
index 0c0505f543..8e139c3c4b 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_18.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_18.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_18_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_18_blue.png
index 651bfdf1dc..86f36fc558 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_18_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_18_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_18_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_18_green.png
index e95eed2e50..b3ce321bb9 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_18_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_18_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_18_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_18_green_blue.png
index 0e2d5a0eec..d87af20309 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_18_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_18_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_19.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_19.png
index 3e8314449a..3e5b55cf10 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_19.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_19.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_19_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_19_blue.png
index 5ed0b077e2..1c680b312a 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_19_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_19_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_19_green.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_19_green.png
index bacc7ac208..425d1cf644 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_19_green.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_19_green.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_19_green_blue.png b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_19_green_blue.png
index 9dcdbf2519..e821b699af 100644
Binary files a/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_19_green_blue.png and b/BizHawk.Client.EmuHawk/images/tastudio/ts_v_piano_19_green_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/textdoc.png b/BizHawk.Client.EmuHawk/images/textdoc.png
index 5a31e768c6..d3972d12d0 100644
Binary files a/BizHawk.Client.EmuHawk/images/textdoc.png and b/BizHawk.Client.EmuHawk/images/textdoc.png differ
diff --git a/BizHawk.Client.EmuHawk/images/thumbsdown.png b/BizHawk.Client.EmuHawk/images/thumbsdown.png
index 2fe368c3d4..f640b54d15 100644
Binary files a/BizHawk.Client.EmuHawk/images/thumbsdown.png and b/BizHawk.Client.EmuHawk/images/thumbsdown.png differ
diff --git a/BizHawk.Client.EmuHawk/images/tvIcon.png b/BizHawk.Client.EmuHawk/images/tvIcon.png
index 4dd7a8732d..ee8dd3adec 100644
Binary files a/BizHawk.Client.EmuHawk/images/tvIcon.png and b/BizHawk.Client.EmuHawk/images/tvIcon.png differ
diff --git a/BizHawk.Client.EmuHawk/images/undo.png b/BizHawk.Client.EmuHawk/images/undo.png
index 085e769122..b009b22da8 100644
Binary files a/BizHawk.Client.EmuHawk/images/undo.png and b/BizHawk.Client.EmuHawk/images/undo.png differ
diff --git a/BizHawk.Client.EmuHawk/images/user_blue.png b/BizHawk.Client.EmuHawk/images/user_blue.png
index 0c76dd066e..8e2fc36fec 100644
Binary files a/BizHawk.Client.EmuHawk/images/user_blue.png and b/BizHawk.Client.EmuHawk/images/user_blue.png differ
diff --git a/BizHawk.Client.EmuHawk/images/whiteTriDown.png b/BizHawk.Client.EmuHawk/images/whiteTriDown.png
index de77507e87..23c23d2b00 100644
Binary files a/BizHawk.Client.EmuHawk/images/whiteTriDown.png and b/BizHawk.Client.EmuHawk/images/whiteTriDown.png differ
diff --git a/BizHawk.Client.EmuHawk/images/whiteTriLeft.png b/BizHawk.Client.EmuHawk/images/whiteTriLeft.png
index 0334f5a1d1..93b87c92ab 100644
Binary files a/BizHawk.Client.EmuHawk/images/whiteTriLeft.png and b/BizHawk.Client.EmuHawk/images/whiteTriLeft.png differ
diff --git a/BizHawk.Client.EmuHawk/images/whiteTriRight.png b/BizHawk.Client.EmuHawk/images/whiteTriRight.png
index 7d24215e62..cd9dffd74a 100644
Binary files a/BizHawk.Client.EmuHawk/images/whiteTriRight.png and b/BizHawk.Client.EmuHawk/images/whiteTriRight.png differ
diff --git a/BizHawk.Client.EmuHawk/images/whiteTriUp.png b/BizHawk.Client.EmuHawk/images/whiteTriUp.png
index c813f49628..ef3ca6af84 100644
Binary files a/BizHawk.Client.EmuHawk/images/whiteTriUp.png and b/BizHawk.Client.EmuHawk/images/whiteTriUp.png differ
diff --git a/BizHawk.Client.EmuHawk/tools/Debugger/Breakpoint.cs b/BizHawk.Client.EmuHawk/tools/Debugger/Breakpoint.cs
index 3f4aca4106..b296f0d821 100644
--- a/BizHawk.Client.EmuHawk/tools/Debugger/Breakpoint.cs
+++ b/BizHawk.Client.EmuHawk/tools/Debugger/Breakpoint.cs
@@ -7,7 +7,7 @@ namespace BizHawk.Client.EmuHawk
{
public class BreakpointList : List
{
- public Action Callback { get; set; }
+ public MemoryCallbackDelegate Callback { get; set; }
public void Add(IDebuggable core, string scope, uint address, uint mask, MemoryCallbackType type)
{
@@ -69,7 +69,7 @@ namespace BizHawk.Client.EmuHawk
private bool _active;
private readonly IDebuggable _core;
- public Breakpoint(bool readOnly, IDebuggable core, string scope, Action callBack, uint address, uint mask, MemoryCallbackType type, bool enabled = true)
+ public Breakpoint(bool readOnly, IDebuggable core, string scope, MemoryCallbackDelegate callBack, uint address, uint mask, MemoryCallbackType type, bool enabled = true)
{
Scope = scope;
_core = core;
@@ -83,7 +83,7 @@ namespace BizHawk.Client.EmuHawk
ReadOnly = readOnly;
}
- public Breakpoint(IDebuggable core, string scope, Action callBack, uint address, uint mask, MemoryCallbackType type, bool enabled = true)
+ public Breakpoint(IDebuggable core, string scope, MemoryCallbackDelegate callBack, uint address, uint mask, MemoryCallbackType type, bool enabled = true)
{
Scope = scope;
_core = core;
@@ -96,7 +96,7 @@ namespace BizHawk.Client.EmuHawk
Active = enabled;
}
- public Breakpoint(string name, bool readOnly, IDebuggable core, string scope, Action callBack, uint address, uint mask, MemoryCallbackType type, bool enabled = true)
+ public Breakpoint(string name, bool readOnly, IDebuggable core, string scope, MemoryCallbackDelegate callBack, uint address, uint mask, MemoryCallbackType type, bool enabled = true)
{
Scope = scope;
_core = core;
@@ -111,7 +111,7 @@ namespace BizHawk.Client.EmuHawk
}
public string Scope { get; }
- public Action Callback { get; }
+ public MemoryCallbackDelegate Callback { get; }
public uint? Address { get; set; }
public uint? AddressMask { get; set; }
public MemoryCallbackType Type { get; set; }
diff --git a/BizHawk.Client.EmuHawk/tools/Debugger/BreakpointControl.cs b/BizHawk.Client.EmuHawk/tools/Debugger/BreakpointControl.cs
index 17428ebc77..5d8dfc5bc9 100644
--- a/BizHawk.Client.EmuHawk/tools/Debugger/BreakpointControl.cs
+++ b/BizHawk.Client.EmuHawk/tools/Debugger/BreakpointControl.cs
@@ -60,16 +60,16 @@ namespace BizHawk.Client.EmuHawk
: Color.White;
}
- private void BreakpointCallback()
+ private void BreakpointCallback(uint addr, uint value, uint flags)
{
GlobalWin.MainForm.PauseEmulator();
UpdateValues();
GlobalWin.OSD.AddMessage("Breakpoint hit");
}
- private void SeekCallback()
+ private void SeekCallback(uint addr, uint value, uint flags)
{
- BreakpointCallback();
+ BreakpointCallback(addr, value, flags);
var seekBreakpoint = _breakpoints.FirstOrDefault(x => x.Name.StartsWith(SeekName));
diff --git a/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.Communication.cs b/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.Communication.cs
index 4776698360..156b3078f9 100644
--- a/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.Communication.cs
+++ b/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.Communication.cs
@@ -36,6 +36,9 @@ namespace BizHawk.Client.EmuHawk
return list.ToString();
}
+ [LuaMethod("socketServerIsConnected", "socketServerIsConnected")]
+ public bool SocketServerIsConnected() => GlobalWin.socketServer.connected;
+
[LuaMethod("socketServerScreenShot", "sends a screenshot to the Socket server")]
public string SocketServerScreenShot()
{
diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs
index a163f97c2e..ac2116bb94 100644
--- a/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs
+++ b/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs
@@ -182,8 +182,8 @@ namespace BizHawk.Client.EmuHawk
Frame = Tastudio.Emulator.Frame,
CoreData = (byte[])(Tastudio.StatableEmulator.SaveStateBinary().Clone()),
InputLog = Movie.InputLog.Clone(),
+ CoreFrameBuffer = GlobalWin.MainForm.MakeScreenshotImage(),
OSDFrameBuffer = GlobalWin.MainForm.CaptureOSD(),
- LagLog = Movie.TasLagLog.Clone(),
ChangeLog = new TasMovieChangeLog(Movie),
TimeStamp = DateTime.Now,
Markers = Movie.Markers.DeepClone(),
@@ -203,7 +203,7 @@ namespace BizHawk.Client.EmuHawk
var stateInfo = new KeyValuePair(branch.Frame, branch.CoreData);
Tastudio.LoadState(stateInfo);
Movie.TasStateManager.Capture(true);
- QuickBmpFile.Copy(new BitmapBufferVideoProvider(branch.OSDFrameBuffer), Tastudio.VideoProvider);
+ QuickBmpFile.Copy(new BitmapBufferVideoProvider(branch.CoreFrameBuffer), Tastudio.VideoProvider);
if (Tastudio.Settings.OldControlSchemeForBranches && Tastudio.TasPlaybackBox.RecordingMode)
Movie.Truncate(branch.Frame);
diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/ScreenshotForm.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/ScreenshotForm.cs
index 65e407eb5f..3c765cb845 100644
--- a/BizHawk.Client.EmuHawk/tools/TAStudio/ScreenshotForm.cs
+++ b/BizHawk.Client.EmuHawk/tools/TAStudio/ScreenshotForm.cs
@@ -1,120 +1,120 @@
-using System.Drawing;
-using System.Windows.Forms;
-
+using System.Drawing;
+using System.Windows.Forms;
+
using BizHawk.Client.Common;
// We pretend it's a tooltip kind of thing, so show only the actual contents
// and avoid stealing forcus, while still being topmost
// http://stackoverflow.com/a/25219399/2792852
// This is not an actual tooltip, because they can't reliably fade in and out with trasparency
-namespace BizHawk.Client.EmuHawk
-{
- public partial class ScreenshotForm : Form
+namespace BizHawk.Client.EmuHawk
+{
+ public partial class ScreenshotForm : Form
{
private const int WS_EX_TOPMOST = 0x00000008;
- private const int Interval = 40;
+ private const int Interval = 40;
private const double AlphaStep = 0.125;
- private readonly Timer _showTimer = new Timer();
- private readonly Timer _hideTimer = new Timer();
-
- private TasBranch _branch;
- private int _drawingHeight;
-
- new public Font Font;
- new public int Padding;
- new public string Text;
-
- public ScreenshotForm()
- {
- InitializeComponent();
-
- var fontSize = 10;
- var fontStyle = FontStyle.Regular;
- Font = new Font(FontFamily.GenericMonospace, fontSize, fontStyle);
- _drawingHeight = 0;
- Padding = 0;
- Opacity = 0;
-
- _showTimer.Interval = Interval;
- _showTimer.Tick += (sender, e) =>
- {
- if ((Opacity += AlphaStep) >= 1)
- {
- _showTimer.Stop();
- }
- };
-
- _hideTimer.Interval = Interval;
- _hideTimer.Tick += (sender, e) =>
- {
- if ((Opacity -= AlphaStep) <= 0)
- {
- _hideTimer.Stop();
- Hide();
- }
- };
- }
-
- public void UpdateValues(TasBranch branch, Point location , int width, int height, int padding)
- {
- _branch = branch;
- Width = width;
- Padding = padding;
- _drawingHeight = height;
- Text = _branch.UserText;
- Location = location;
-
- if (Padding > 0)
- {
- Padding += 2;
- }
-
- Height = _drawingHeight + Padding;
- Refresh();
- }
-
- protected override void OnPaint(PaintEventArgs e)
- {
- _branch.OSDFrameBuffer.DiscardAlpha();
- var bitmap = _branch.OSDFrameBuffer.ToSysdrawingBitmap();
- e.Graphics.DrawImage(bitmap, new Rectangle(0, 0, Width, _drawingHeight));
- if (Padding > 0)
- {
- e.Graphics.DrawRectangle(new Pen(Brushes.Black), new Rectangle(new Point(0, _drawingHeight), new Size(Width - 1, Padding - 1)));
- e.Graphics.DrawString(Text, Font, Brushes.Black, new Rectangle(2, _drawingHeight, Width - 2, Height));
- }
-
- base.OnPaint(e);
- }
-
- public void FadeIn()
- {
- _showTimer.Stop();
- _hideTimer.Stop();
- _showTimer.Start();
- Show();
- }
-
- public void FadeOut()
- {
- _showTimer.Stop();
- _hideTimer.Stop();
- _hideTimer.Start();
- }
-
- // avoid stealing focus
- protected override bool ShowWithoutActivation => true;
-
- protected override CreateParams CreateParams
- {
- get
- {
- CreateParams createParams = base.CreateParams;
- createParams.ExStyle |= WS_EX_TOPMOST;
- return createParams;
- }
- }
- }
-}
+ private readonly Timer _showTimer = new Timer();
+ private readonly Timer _hideTimer = new Timer();
+
+ private TasBranch _branch;
+ private int _drawingHeight;
+
+ new public Font Font;
+ new public int Padding;
+ new public string Text;
+
+ public ScreenshotForm()
+ {
+ InitializeComponent();
+
+ var fontSize = 10;
+ var fontStyle = FontStyle.Regular;
+ Font = new Font(FontFamily.GenericMonospace, fontSize, fontStyle);
+ _drawingHeight = 0;
+ Padding = 0;
+ Opacity = 0;
+
+ _showTimer.Interval = Interval;
+ _showTimer.Tick += (sender, e) =>
+ {
+ if ((Opacity += AlphaStep) >= 1)
+ {
+ _showTimer.Stop();
+ }
+ };
+
+ _hideTimer.Interval = Interval;
+ _hideTimer.Tick += (sender, e) =>
+ {
+ if ((Opacity -= AlphaStep) <= 0)
+ {
+ _hideTimer.Stop();
+ Hide();
+ }
+ };
+ }
+
+ public void UpdateValues(TasBranch branch, Point location , int width, int height, int padding)
+ {
+ _branch = branch;
+ Width = width;
+ Padding = padding;
+ _drawingHeight = height;
+ Text = _branch.UserText;
+ Location = location;
+
+ if (Padding > 0)
+ {
+ Padding += 2;
+ }
+
+ Height = _drawingHeight + Padding;
+ Refresh();
+ }
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ _branch.OSDFrameBuffer.DiscardAlpha();
+ var bitmap = _branch.OSDFrameBuffer.ToSysdrawingBitmap();
+ e.Graphics.DrawImage(bitmap, new Rectangle(0, 0, Width, _drawingHeight));
+ if (Padding > 0)
+ {
+ e.Graphics.DrawRectangle(new Pen(Brushes.Black), new Rectangle(new Point(0, _drawingHeight), new Size(Width - 1, Padding - 1)));
+ e.Graphics.DrawString(Text, Font, Brushes.Black, new Rectangle(2, _drawingHeight, Width - 2, Height));
+ }
+
+ base.OnPaint(e);
+ }
+
+ public void FadeIn()
+ {
+ _showTimer.Stop();
+ _hideTimer.Stop();
+ _showTimer.Start();
+ Show();
+ }
+
+ public void FadeOut()
+ {
+ _showTimer.Stop();
+ _hideTimer.Stop();
+ _hideTimer.Start();
+ }
+
+ // avoid stealing focus
+ protected override bool ShowWithoutActivation => true;
+
+ protected override CreateParams CreateParams
+ {
+ get
+ {
+ CreateParams createParams = base.CreateParams;
+ createParams.ExStyle |= WS_EX_TOPMOST;
+ return createParams;
+ }
+ }
+ }
+}
diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs
index de35d5b4bc..c9cb910243 100644
--- a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs
+++ b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs
@@ -66,9 +66,9 @@ namespace BizHawk.Client.EmuHawk
public void JumpToGreenzone()
{
- if (Emulator.Frame > CurrentTasMovie.LastValidFrame)
+ if (Emulator.Frame > CurrentTasMovie.LastEditedFrame)
{
- GoToLastEmulatedFrameIfNecessary(CurrentTasMovie.LastValidFrame);
+ GoToLastEmulatedFrameIfNecessary(CurrentTasMovie.LastEditedFrame);
}
else
{
@@ -76,19 +76,22 @@ namespace BizHawk.Client.EmuHawk
}
}
- private void StartSeeking(int? frame)
+ private void StartSeeking(int? frame, bool fromMiddleClick = false)
{
if (!frame.HasValue)
{
return;
}
- if (Mainform.PauseOnFrame != null)
+ if (!fromMiddleClick)
{
- StopSeeking(true); // don't restore rec mode just yet, as with heavy editing checkbox updating causes lag
+ if (Mainform.PauseOnFrame != null)
+ {
+ StopSeeking(true); // don't restore rec mode just yet, as with heavy editing checkbox updating causes lag
+ }
+ _seekStartFrame = Emulator.Frame;
}
- _seekStartFrame = Emulator.Frame;
Mainform.PauseOnFrame = frame.Value;
int? diff = Mainform.PauseOnFrame - _seekStartFrame;
@@ -510,7 +513,7 @@ namespace BizHawk.Client.EmuHawk
TasMovieRecord record = CurrentTasMovie[LastPositionFrame];
if (!record.Lagged.HasValue && LastPositionFrame > Emulator.Frame)
{
- StartSeeking(LastPositionFrame);
+ StartSeeking(LastPositionFrame, true);
}
else
{
@@ -1129,7 +1132,7 @@ namespace BizHawk.Client.EmuHawk
if (!Settings.AutoRestoreOnMouseUpOnly)
{
- _triggerAutoRestore = true;
+ _triggerAutoRestore = startVal < Emulator.Frame && endVal < Emulator.Frame;
DoTriggeredAutoRestoreIfNeeded();
}
}
diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs
index 672ec1656f..3695e8d996 100644
--- a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs
+++ b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs
@@ -807,7 +807,7 @@ namespace BizHawk.Client.EmuHawk
GoToFrame(0);
int lastState = 0;
- int goToFrame = CurrentTasMovie.TasStateManager.LastStatedFrame;
+ int goToFrame = CurrentTasMovie.LastStatedFrame;
do
{
Mainform.FrameAdvance();
diff --git a/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadAnalogStick.cs b/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadAnalogStick.cs
index fa62c0fc08..5a6661a3c7 100644
--- a/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadAnalogStick.cs
+++ b/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadAnalogStick.cs
@@ -39,6 +39,8 @@ namespace BizHawk.Client.EmuHawk
public float[] RangeX = new float[] { -128f, 0.0f, 127f };
public float[] RangeY = new float[] { -128f, 0.0f, 127f };
+ private bool ReverseX;
+ private bool ReverseY;
public string SecondaryName { get; set; }
@@ -50,7 +52,17 @@ namespace BizHawk.Client.EmuHawk
AnalogStick.YName = !string.IsNullOrEmpty(SecondaryName)
? SecondaryName
: Name.Replace("X", "Y"); // Fallback
+ if (RangeX[0] > RangeX[2])
+ {
+ RangeX = new[] { RangeX[2], RangeX[1], RangeX[0] };
+ ReverseX = true;
+ }
AnalogStick.SetRangeX(RangeX);
+ if (RangeY[0] > RangeY[2])
+ {
+ RangeY = new[] { RangeY[2], RangeY[1], RangeY[0] };
+ ReverseY = true;
+ }
AnalogStick.SetRangeY(RangeY);
ManualX.Minimum = (decimal)RangeX[0];
@@ -264,7 +276,7 @@ namespace BizHawk.Client.EmuHawk
private void SetAnalogMaxFromNumerics()
{
if (!_programmaticallyUpdatingNumerics)
- AnalogStick.SetUserRange((sbyte)MaxXNumeric.Value, (sbyte)MaxYNumeric.Value);
+ AnalogStick.SetUserRange(ReverseX ? -MaxXNumeric.Value : MaxXNumeric.Value, ReverseY ? -MaxYNumeric.Value : MaxYNumeric.Value);
}
}
}
diff --git a/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/components/AnalogStickPanel.cs b/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/components/AnalogStickPanel.cs
index 928cbb1fed..e85d267ea9 100644
--- a/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/components/AnalogStickPanel.cs
+++ b/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/components/AnalogStickPanel.cs
@@ -51,10 +51,10 @@ namespace BizHawk.Client.EmuHawk
private sbyte UserRangePercentageX = 100;
private sbyte UserRangePercentageY = 100;
- public void SetUserRange(sbyte rx, sbyte ry)
+ public void SetUserRange(decimal rx, decimal ry)
{
- UserRangePercentageX = rx;
- UserRangePercentageY = ry;
+ UserRangePercentageX = (sbyte) rx;
+ UserRangePercentageY = (sbyte) ry;
Rerange();
Refresh();
}
diff --git a/BizHawk.Client.MultiHawk/Resources/courier16px_0.png b/BizHawk.Client.MultiHawk/Resources/courier16px_0.png
index bad54fe855..36d5051db4 100644
Binary files a/BizHawk.Client.MultiHawk/Resources/courier16px_0.png and b/BizHawk.Client.MultiHawk/Resources/courier16px_0.png differ
diff --git a/BizHawk.Client.MultiHawk/images/Blank.png b/BizHawk.Client.MultiHawk/images/Blank.png
index ab2a9ccc02..c8d0a51cc0 100644
Binary files a/BizHawk.Client.MultiHawk/images/Blank.png and b/BizHawk.Client.MultiHawk/images/Blank.png differ
diff --git a/BizHawk.Client.MultiHawk/images/CutHS.png b/BizHawk.Client.MultiHawk/images/CutHS.png
index 449f92f08c..dd40e93a2a 100644
Binary files a/BizHawk.Client.MultiHawk/images/CutHS.png and b/BizHawk.Client.MultiHawk/images/CutHS.png differ
diff --git a/BizHawk.Client.MultiHawk/images/GameController.png b/BizHawk.Client.MultiHawk/images/GameController.png
index 268da4cbe6..3d0131cd16 100644
Binary files a/BizHawk.Client.MultiHawk/images/GameController.png and b/BizHawk.Client.MultiHawk/images/GameController.png differ
diff --git a/BizHawk.Client.MultiHawk/images/HotKeys.png b/BizHawk.Client.MultiHawk/images/HotKeys.png
index 56967c36bf..962eb51ed7 100644
Binary files a/BizHawk.Client.MultiHawk/images/HotKeys.png and b/BizHawk.Client.MultiHawk/images/HotKeys.png differ
diff --git a/BizHawk.Client.MultiHawk/images/Pause.png b/BizHawk.Client.MultiHawk/images/Pause.png
index 302f04ba75..206c71c233 100644
Binary files a/BizHawk.Client.MultiHawk/images/Pause.png and b/BizHawk.Client.MultiHawk/images/Pause.png differ
diff --git a/BizHawk.Client.MultiHawk/images/Play.png b/BizHawk.Client.MultiHawk/images/Play.png
index 8773c25147..b8f7541b05 100644
Binary files a/BizHawk.Client.MultiHawk/images/Play.png and b/BizHawk.Client.MultiHawk/images/Play.png differ
diff --git a/BizHawk.Client.MultiHawk/images/Recent.png b/BizHawk.Client.MultiHawk/images/Recent.png
index bf4416d175..42c559ad27 100644
Binary files a/BizHawk.Client.MultiHawk/images/Recent.png and b/BizHawk.Client.MultiHawk/images/Recent.png differ
diff --git a/BizHawk.Client.MultiHawk/images/RecordHS.png b/BizHawk.Client.MultiHawk/images/RecordHS.png
index a75db7757e..581741d36c 100644
Binary files a/BizHawk.Client.MultiHawk/images/RecordHS.png and b/BizHawk.Client.MultiHawk/images/RecordHS.png differ
diff --git a/BizHawk.Client.MultiHawk/images/Save.png b/BizHawk.Client.MultiHawk/images/Save.png
index b0ce1f9f55..5ec0a2d762 100644
Binary files a/BizHawk.Client.MultiHawk/images/Save.png and b/BizHawk.Client.MultiHawk/images/Save.png differ
diff --git a/BizHawk.Client.MultiHawk/images/Scan.png b/BizHawk.Client.MultiHawk/images/Scan.png
index 7bb7d4092e..ea5e620d8f 100644
Binary files a/BizHawk.Client.MultiHawk/images/Scan.png and b/BizHawk.Client.MultiHawk/images/Scan.png differ
diff --git a/BizHawk.Client.MultiHawk/images/Stop.png b/BizHawk.Client.MultiHawk/images/Stop.png
index a62d26f71b..ef00c0f811 100644
Binary files a/BizHawk.Client.MultiHawk/images/Stop.png and b/BizHawk.Client.MultiHawk/images/Stop.png differ
diff --git a/BizHawk.Client.MultiHawk/images/reboot.png b/BizHawk.Client.MultiHawk/images/reboot.png
index f7ef40ae9b..2d355ac56c 100644
Binary files a/BizHawk.Client.MultiHawk/images/reboot.png and b/BizHawk.Client.MultiHawk/images/reboot.png differ
diff --git a/BizHawk.Emulation.Common/Base Implementations/CallbackBasedTraceBuffer.cs b/BizHawk.Emulation.Common/Base Implementations/CallbackBasedTraceBuffer.cs
index 29ae44e902..97cb1f1e7d 100644
--- a/BizHawk.Emulation.Common/Base Implementations/CallbackBasedTraceBuffer.cs
+++ b/BizHawk.Emulation.Common/Base Implementations/CallbackBasedTraceBuffer.cs
@@ -46,7 +46,7 @@ namespace BizHawk.Emulation.Common
protected readonly List Buffer = new List();
- protected abstract void TraceFromCallback();
+ protected abstract void TraceFromCallback(uint addr, uint value, uint flags);
private ITraceSink _sink;
@@ -80,7 +80,7 @@ namespace BizHawk.Emulation.Common
public class TracingMemoryCallback : IMemoryCallback
{
- public TracingMemoryCallback(Action callback)
+ public TracingMemoryCallback(MemoryCallbackDelegate callback)
{
Callback = callback;
}
@@ -89,7 +89,7 @@ namespace BizHawk.Emulation.Common
public string Name => "Trace Logging";
- public Action Callback { get; }
+ public MemoryCallbackDelegate Callback { get; }
public uint? Address => null;
diff --git a/BizHawk.Emulation.Common/Base Implementations/MemoryCallbackSystem.cs b/BizHawk.Emulation.Common/Base Implementations/MemoryCallbackSystem.cs
index 0df3232a4a..3b984eedde 100644
--- a/BizHawk.Emulation.Common/Base Implementations/MemoryCallbackSystem.cs
+++ b/BizHawk.Emulation.Common/Base Implementations/MemoryCallbackSystem.cs
@@ -36,6 +36,7 @@ namespace BizHawk.Emulation.Common
private bool _hasReads;
private bool _hasWrites;
private bool _hasExecutes;
+ private bool _hasAny;
public bool ExecuteCallbacksAvailable { get; }
@@ -67,38 +68,61 @@ namespace BizHawk.Emulation.Common
}
}
- private static void Call(ObservableCollection cbs, uint addr, string scope)
+ private static void Call(ObservableCollection cbs, uint addr, uint value, uint flags, string scope)
{
for (int i = 0; i < cbs.Count; i++)
{
if (!cbs[i].Address.HasValue || (cbs[i].Scope == scope && cbs[i].Address == (addr & cbs[i].AddressMask)))
{
- cbs[i].Callback();
+ cbs[i].Callback(addr, value, flags);
}
}
}
- public void CallReads(uint addr, string scope)
+ public void CallMemoryCallbacks(uint addr, uint value, uint flags, string scope)
+ {
+ if (!_hasAny) return;
+
+ if (_hasReads)
+ {
+ if((flags & (uint)MemoryCallbackFlags.AccessRead)!=0)
+ Call(_reads, addr, value, flags, scope);
+ }
+
+ if (_hasWrites)
+ {
+ if((flags & (uint)MemoryCallbackFlags.AccessWrite)!=0)
+ Call(_writes, addr, value, flags, scope);
+ }
+
+ if (_hasExecutes)
+ {
+ if((flags & (uint)MemoryCallbackFlags.AccessExecute)!=0)
+ Call(_execs, addr, value, flags, scope);
+ }
+ }
+
+ public void CallReads(uint addr, uint value, uint flags, string scope)
{
if (_hasReads)
{
- Call(_reads, addr, scope);
+ Call(_reads, addr, value, flags, scope);
}
}
- public void CallWrites(uint addr, string scope)
+ public void CallWrites(uint addr, uint value, uint flags, string scope)
{
if (_hasWrites)
{
- Call(_writes, addr, scope);
+ Call(_writes, addr, value, flags, scope);
}
}
- public void CallExecutes(uint addr, string scope)
+ public void CallExecutes(uint addr, uint value, uint flags, string scope)
{
if (_hasExecutes)
{
- Call(_execs, addr, scope);
+ Call(_execs, addr, value, flags, scope);
}
}
@@ -132,11 +156,12 @@ namespace BizHawk.Emulation.Common
_hasReads = _reads.Count > 0;
_hasWrites = _writes.Count > 0;
_hasExecutes = _execs.Count > 0;
+ _hasAny = _hasReads || _hasWrites || _hasExecutes;
return (_hasReads != hadReads || _hasWrites != hadWrites || _hasExecutes != hadExecutes);
}
- private int RemoveInternal(Action action)
+ private int RemoveInternal(MemoryCallbackDelegate action)
{
var readsToRemove = _reads.Where(imc => imc.Callback == action).ToList();
var writesToRemove = _writes.Where(imc => imc.Callback == action).ToList();
@@ -160,7 +185,7 @@ namespace BizHawk.Emulation.Common
return readsToRemove.Count + writesToRemove.Count + execsToRemove.Count;
}
- public void Remove(Action action)
+ public void Remove(MemoryCallbackDelegate action)
{
if (RemoveInternal(action) > 0)
{
@@ -171,7 +196,7 @@ namespace BizHawk.Emulation.Common
}
}
- public void RemoveAll(IEnumerable actions)
+ public void RemoveAll(IEnumerable actions)
{
bool changed = false;
foreach (var action in actions)
@@ -286,7 +311,7 @@ namespace BizHawk.Emulation.Common
public class MemoryCallback : IMemoryCallback
{
- public MemoryCallback(string scope, MemoryCallbackType type, string name, Action callback, uint? address, uint? mask)
+ public MemoryCallback(string scope, MemoryCallbackType type, string name, MemoryCallbackDelegate callback, uint? address, uint? mask)
{
if (type == MemoryCallbackType.Execute && !address.HasValue)
{
@@ -303,7 +328,7 @@ namespace BizHawk.Emulation.Common
public MemoryCallbackType Type { get; }
public string Name { get; }
- public Action Callback { get; }
+ public MemoryCallbackDelegate Callback { get; }
public uint? Address { get; }
public uint? AddressMask { get; }
public string Scope { get; }
diff --git a/BizHawk.Emulation.Common/Interfaces/IMemoryCallbackSystem.cs b/BizHawk.Emulation.Common/Interfaces/IMemoryCallbackSystem.cs
index 23d8808347..dc891c4ae0 100644
--- a/BizHawk.Emulation.Common/Interfaces/IMemoryCallbackSystem.cs
+++ b/BizHawk.Emulation.Common/Interfaces/IMemoryCallbackSystem.cs
@@ -3,6 +3,9 @@ using System.Collections.Generic;
namespace BizHawk.Emulation.Common
{
+
+ public delegate void MemoryCallbackDelegate(uint address, uint value, uint flags);
+
///
/// This is a property of , and defines the means by which a client
/// gets and sets memory callbacks in the core. A memory callback should fire any time memory is
@@ -61,35 +64,23 @@ namespace BizHawk.Emulation.Common
void Add(IMemoryCallback callback);
///
- /// Executes all Read callbacks for the given address and domain
+ /// Executes all matching callbacks for the given address and domain
///
/// The address to check for callbacks
+ /// The value contained (or written to) addr
+ /// The callback flags relevant to this access
/// The scope that the address pertains to. Must be a value in
- void CallReads(uint addr, string scope);
-
- ///
- /// Executes all Write callbacks for the given address and domain
- ///
- /// The address to check for callbacks
- /// The scope that the address pertains to. Must be a value in
- void CallWrites(uint addr, string scope);
-
- ///
- /// Executes all Execute callbacks for the given address and domain
- ///
- /// The address to check for callbacks
- /// The scope that the address pertains to. Must be a value in
- void CallExecutes(uint addr, string scope);
+ void CallMemoryCallbacks(uint addr, uint value, uint flags, string scope);
///
/// Removes the given callback from the list
///
- void Remove(Action action);
+ void Remove(MemoryCallbackDelegate action);
///
/// Removes the given callbacks from the list
///
- void RemoveAll(IEnumerable actions);
+ void RemoveAll(IEnumerable actions);
///
/// Removes all read,write, and execute callbacks
@@ -111,7 +102,7 @@ namespace BizHawk.Emulation.Common
{
MemoryCallbackType Type { get; }
string Name { get; }
- Action Callback { get; }
+ MemoryCallbackDelegate Callback { get; }
uint? Address { get; }
uint? AddressMask { get; }
string Scope { get; }
@@ -121,4 +112,20 @@ namespace BizHawk.Emulation.Common
{
Read, Write, Execute
}
+
+ [Flags]
+ public enum MemoryCallbackFlags : uint
+ {
+ SizeUnknown = 0x00 << 16,
+ SizeByte = 0x01 << 16,
+ SizeWord = 0x02 << 16,
+ SizeLong = 0x03 << 16,
+ AccessUnknown = 0x00 << 12,
+ AccessRead = 0x01 << 12,
+ AccessWrite = 0x02 << 12,
+ AccessExecute = 0x04 << 12,
+ CPUUnknown = 0x00 << 8,
+ CPUZero = 0x01 << 8,
+ DomainUnknown = 0x00,
+ }
}
diff --git a/BizHawk.Emulation.Cores/CPUs/CP1610/CP1610.Execute.cs b/BizHawk.Emulation.Cores/CPUs/CP1610/CP1610.Execute.cs
index c30c140bff..dcaa1b7cc7 100644
--- a/BizHawk.Emulation.Cores/CPUs/CP1610/CP1610.Execute.cs
+++ b/BizHawk.Emulation.Cores/CPUs/CP1610/CP1610.Execute.cs
@@ -192,7 +192,8 @@ namespace BizHawk.Emulation.Cores.Components.CP1610
if (MemoryCallbacks != null)
{
- MemoryCallbacks.CallExecutes(RegisterPC, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessExecute);
+ MemoryCallbacks.CallMemoryCallbacks(RegisterPC, 0, flags, "System Bus");
}
switch (opcode)
diff --git a/BizHawk.Emulation.Cores/CPUs/CP1610/CP1610.cs b/BizHawk.Emulation.Cores/CPUs/CP1610/CP1610.cs
index f1b795f1b8..fd4ccf623d 100644
--- a/BizHawk.Emulation.Cores/CPUs/CP1610/CP1610.cs
+++ b/BizHawk.Emulation.Cores/CPUs/CP1610/CP1610.cs
@@ -31,7 +31,8 @@ namespace BizHawk.Emulation.Cores.Components.CP1610
{
if (MemoryCallbacks != null && !peek)
{
- MemoryCallbacks.CallReads(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessRead);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
}
return ReadMemory(addr, peek);
@@ -41,7 +42,8 @@ namespace BizHawk.Emulation.Cores.Components.CP1610
{
if (MemoryCallbacks != null && !poke)
{
- MemoryCallbacks.CallWrites(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessWrite);
+ MemoryCallbacks.CallMemoryCallbacks(addr, value, flags, "System Bus");
}
WriteMemory(addr, value, poke);
diff --git a/BizHawk.Emulation.Cores/CPUs/HuC6280/Execute.cs b/BizHawk.Emulation.Cores/CPUs/HuC6280/Execute.cs
index e86edcc297..cfc1db3d95 100644
--- a/BizHawk.Emulation.Cores/CPUs/HuC6280/Execute.cs
+++ b/BizHawk.Emulation.Cores/CPUs/HuC6280/Execute.cs
@@ -60,7 +60,7 @@ namespace BizHawk.Emulation.Cores.Components.H6280
LagIFlag = FlagI;
if (Debug) Logger(State());
- MemoryCallbacks.CallExecutes(PC, "System Bus");
+ MemoryCallbacks.CallMemoryCallbacks(PC, 0, (uint)MemoryCallbackFlags.AccessExecute, "System Bus");
if (CDL != null && CDL.Active) CDLOpcode();
diff --git a/BizHawk.Emulation.Cores/CPUs/HuC6280/HuC6280.cs b/BizHawk.Emulation.Cores/CPUs/HuC6280/HuC6280.cs
index 27a93c5d2d..406e3730d7 100644
--- a/BizHawk.Emulation.Cores/CPUs/HuC6280/HuC6280.cs
+++ b/BizHawk.Emulation.Cores/CPUs/HuC6280/HuC6280.cs
@@ -230,7 +230,8 @@ namespace BizHawk.Emulation.Cores.Components.H6280
{
byte page = MPR[address >> 13];
var result = ReadMemory21((page << 13) | (address & 0x1FFF));
- MemoryCallbacks.CallReads(address, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessRead);
+ MemoryCallbacks.CallMemoryCallbacks(address, result, flags, "System Bus");
return result;
}
@@ -238,7 +239,8 @@ namespace BizHawk.Emulation.Cores.Components.H6280
{
byte page = MPR[address >> 13];
WriteMemory21((page << 13) | (address & 0x1FFF), value);
- MemoryCallbacks.CallWrites(address, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessWrite);
+ MemoryCallbacks.CallMemoryCallbacks(address, value, flags, "System Bus");
}
private ushort ReadWord(ushort address)
diff --git a/BizHawk.Emulation.Cores/CPUs/MC6809/Execute.cs b/BizHawk.Emulation.Cores/CPUs/MC6809/Execute.cs
index 836508c574..df96726c14 100644
--- a/BizHawk.Emulation.Cores/CPUs/MC6809/Execute.cs
+++ b/BizHawk.Emulation.Cores/CPUs/MC6809/Execute.cs
@@ -157,7 +157,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
case 0x83: IMD_OP_D(SUB16, D); break; // SUBD (Immediate)
case 0x84: REG_OP_IMD(AND8, A); break; // ANDA (Immediate)
case 0x85: REG_OP_IMD(BIT, A); break; // BITA (Immediate)
- case 0x86: REG_OP_IMD(TR, A); break; // LDA (Immediate)
+ case 0x86: REG_OP_IMD(LD_8, A); break; // LDA (Immediate)
case 0x87: ILLEGAL(); break; // ILLEGAL
case 0x88: REG_OP_IMD(XOR8, A); break; // EORA (Immediate)
case 0x89: REG_OP_IMD(ADC8, A); break; // ADCA (Immediate)
@@ -173,7 +173,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
case 0x93: DIR_OP_D(SUB16, D); break; // SUBD (Direct)
case 0x94: DIRECT_MEM_4(AND8, A); break; // ANDA (Direct)
case 0x95: DIRECT_MEM_4(BIT, A); break; // BITA (Direct)
- case 0x96: DIRECT_MEM_4(TR, A); break; // LDA (Direct)
+ case 0x96: DIRECT_MEM_4(LD_8, A); break; // LDA (Direct)
case 0x97: DIRECT_ST_4(A); break; // STA (Direct)
case 0x98: DIRECT_MEM_4(XOR8, A); break; // EORA (Direct)
case 0x99: DIRECT_MEM_4(ADC8, A); break; // ADCA (Direct)
@@ -205,7 +205,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
case 0xB3: EXT_OP_D(SUB16, D); break; // SUBD (Extended)
case 0xB4: EXT_REG(AND8, A); break; // ANDA (Extended)
case 0xB5: EXT_REG(BIT, A); break; // BITA (Extended)
- case 0xB6: EXT_REG(TR, A); break; // LDA (Extended)
+ case 0xB6: EXT_REG(LD_8, A); break; // LDA (Extended)
case 0xB7: EXT_ST(A); break; // STA (Extended)
case 0xB8: EXT_REG(XOR8, A); break; // EORA (Extended)
case 0xB9: EXT_REG(ADC8, A); break; // ADCA (Extended)
@@ -221,7 +221,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
case 0xC3: IMD_OP_D(ADD16, D); break; // ADDD (Immediate)
case 0xC4: REG_OP_IMD(AND8, B); break; // ANDB (Immediate)
case 0xC5: REG_OP_IMD(BIT, B); break; // BITB (Immediate)
- case 0xC6: REG_OP_IMD(TR, B); break; // LDB (Immediate)
+ case 0xC6: REG_OP_IMD(LD_8, B); break; // LDB (Immediate)
case 0xC7: ILLEGAL(); break; // ILLEGAL
case 0xC8: REG_OP_IMD(XOR8, B); break; // EORB (Immediate)
case 0xC9: REG_OP_IMD(ADC8, B); break; // ADCB (Immediate)
@@ -237,7 +237,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
case 0xD3: DIR_OP_D(ADD16, D); break; // ADDD (Direct)
case 0xD4: DIRECT_MEM_4(AND8, B); break; // ANDB (Direct)
case 0xD5: DIRECT_MEM_4(BIT, B); break; // BITB (Direct)
- case 0xD6: DIRECT_MEM_4(TR, B); break; // LDB (Direct)
+ case 0xD6: DIRECT_MEM_4(LD_8, B); break; // LDB (Direct)
case 0xD7: DIRECT_ST_4(B); break; // STB (Direct)
case 0xD8: DIRECT_MEM_4(XOR8, B); break; // EORB (Direct)
case 0xD9: DIRECT_MEM_4(ADC8, B); break; // ADCB (Direct)
@@ -269,7 +269,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
case 0xF3: EXT_OP_D(ADD16, D); break; // ADDD (Extended)
case 0xF4: EXT_REG(AND8, B); break; // ANDB (Extended)
case 0xF5: EXT_REG(BIT, B); break; // BITB (Extended)
- case 0xF6: EXT_REG(TR, B); break; // LDB (Extended)
+ case 0xF6: EXT_REG(LD_8, B); break; // LDB (Extended)
case 0xF7: EXT_ST(B); break; // STB (Extended)
case 0xF8: EXT_REG(XOR8, B); break; // EORB (Extended)
case 0xF9: EXT_REG(ADC8, B); break; // ADCB (Extended)
diff --git a/BizHawk.Emulation.Cores/CPUs/MC6809/Indexed_Modes.cs b/BizHawk.Emulation.Cores/CPUs/MC6809/Indexed_Modes.cs
index e330edb35a..89e4e87c8f 100644
--- a/BizHawk.Emulation.Cores/CPUs/MC6809/Indexed_Modes.cs
+++ b/BizHawk.Emulation.Cores/CPUs/MC6809/Indexed_Modes.cs
@@ -86,7 +86,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
private void INDEX_OP_LEA(ushort dest)
{
- PopulateCURINSTR(TR, dest, IDX_EA,
+ PopulateCURINSTR(LEA, dest, IDX_EA,
IDLE);
IRQS = 2;
@@ -96,7 +96,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
{
PopulateCURINSTR(IDLE,
RD_INC, ALU, IDX_EA,
- RD_INC_OP, ALU2, IDX_EA, SET_ADDR, indexed_op_reg, ALU, ALU2);
+ RD_INC_OP, ALU2, IDX_EA, LD_16, indexed_op_reg, ALU, ALU2);
IRQS = 3;
}
@@ -114,7 +114,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
{
PopulateCURINSTR(IDLE,
RD_INC, A, IDX_EA,
- RD_INC, B, IDX_EA);
+ RD_INC_OP, B, IDX_EA, LD_16, ADDR, A, B);
IRQS = 3;
}
@@ -430,7 +430,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
case I_SBC: INDEX_OP_EX4(SBC8); break; // SBC A,B
case I_AND: INDEX_OP_EX4(AND8); break; // AND A,B
case I_BIT: INDEX_OP_EX4(BIT); break; // BIT A,B
- case I_LD: INDEX_OP_EX4(TR); break; // LD A,B
+ case I_LD: INDEX_OP_EX4(LD_8); break; // LD A,B
case I_ST: INDEX_OP_EX4_ST(); break; // ST A,B
case I_XOR: INDEX_OP_EX4(XOR8); break; // XOR A,B
case I_ADC: INDEX_OP_EX4(ADC8); break; // ADC A,B
diff --git a/BizHawk.Emulation.Cores/CPUs/MC6809/MC6809.cs b/BizHawk.Emulation.Cores/CPUs/MC6809/MC6809.cs
index 286b7a6af2..db47fef582 100644
--- a/BizHawk.Emulation.Cores/CPUs/MC6809/MC6809.cs
+++ b/BizHawk.Emulation.Cores/CPUs/MC6809/MC6809.cs
@@ -74,6 +74,9 @@ namespace BizHawk.Emulation.Common.Components.MC6809
public const ushort CMP16 = 63;
public const ushort CMP16D = 64;
public const ushort WR_HI_INC = 65;
+ public const ushort LD_8 = 66;
+ public const ushort LD_16 = 67;
+ public const ushort LEA = 68;
public MC6809()
{
@@ -149,6 +152,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
public void ExecuteOne()
{
//Console.Write(opcode_see + " ");
+ //Console.WriteLine(Regs[PC] + " ");
switch (cur_instr[instr_pntr++])
{
case IDLE:
@@ -246,6 +250,16 @@ namespace BizHawk.Emulation.Common.Components.MC6809
Regs[cur_instr[instr_pntr++]] = (ushort)((Regs[ALU2] << 8) + Regs[ADDR]);
PUL_n_BLD(cur_instr[instr_pntr++]);
break;
+ case LD_8:
+ LD_8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case LD_16:
+ LD_16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case LEA:
+ LEA_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+
}
break;
case WR:
@@ -284,6 +298,15 @@ namespace BizHawk.Emulation.Common.Components.MC6809
case TR:
TR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
+ case LD_8:
+ LD_8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case LD_16:
+ LD_16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case LEA:
+ LEA_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
case EXG:
EXG_Func(cur_instr[instr_pntr++]);
break;
diff --git a/BizHawk.Emulation.Cores/CPUs/MC6809/OP_Tables.cs b/BizHawk.Emulation.Cores/CPUs/MC6809/OP_Tables.cs
index bc9e27f4ec..2a867db8df 100644
--- a/BizHawk.Emulation.Cores/CPUs/MC6809/OP_Tables.cs
+++ b/BizHawk.Emulation.Cores/CPUs/MC6809/OP_Tables.cs
@@ -150,7 +150,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
private void REG_OP_LD_16D()
{
PopulateCURINSTR(RD_INC, A, PC,
- RD_INC, B, PC);
+ RD_INC_OP, B, PC, LD_16, ADDR, A, B);
IRQS = 2;
}
@@ -160,7 +160,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
PopulateCURINSTR(RD_INC_OP, ALU, PC, SET_ADDR, ADDR, DP, ALU,
IDLE,
RD_INC, A, ADDR,
- RD_INC, B, ADDR);
+ RD_INC_OP, B, ADDR, LD_16, ADDR, A, B);
IRQS = 4;
}
@@ -198,7 +198,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
private void REG_OP_LD_16(ushort dest)
{
PopulateCURINSTR(RD_INC, ALU, PC,
- RD_INC_OP, ALU2, PC, SET_ADDR, dest, ALU, ALU2);
+ RD_INC_OP, ALU2, PC, LD_16, dest, ALU, ALU2);
IRQS = 2;
}
@@ -208,7 +208,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
PopulateCURINSTR(RD_INC_OP, ALU, PC, SET_ADDR, ADDR, DP, ALU,
IDLE,
RD_INC, ALU, ADDR,
- RD_INC_OP, ALU2, ADDR, SET_ADDR, dest, ALU, ALU2);
+ RD_INC_OP, ALU2, ADDR, LD_16, dest, ALU, ALU2);
IRQS = 4;
}
@@ -229,7 +229,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
RD_INC_OP, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2,
IDLE,
RD_INC, ALU, ADDR,
- RD_INC_OP, ALU2, ADDR, SET_ADDR, dest, ALU, ALU2);
+ RD_INC_OP, ALU2, ADDR, LD_16, dest, ALU, ALU2);
IRQS = 5;
}
@@ -251,7 +251,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
RD_INC_OP, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2,
IDLE,
RD_INC, A, ADDR,
- RD_INC, B, ADDR);
+ RD_INC_OP, B, ADDR, LD_16, ADDR, A, B);
IRQS = 5;
}
@@ -601,14 +601,14 @@ namespace BizHawk.Emulation.Common.Components.MC6809
}
else if (Regs[ALU].Bit(4))
{
- PopulateCURINSTR(RD_INC_OP, ALU2, src,
+ PopulateCURINSTR(RD_INC, ALU2, src,
RD_INC_OP, ADDR, src, SET_ADDR_PUL, X, src);
Regs[ALU] &= 0xE0;
}
else if (Regs[ALU].Bit(5))
{
- PopulateCURINSTR(RD_INC_OP, ALU2, src,
+ PopulateCURINSTR(RD_INC, ALU2, src,
RD_INC_OP, ADDR, src, SET_ADDR_PUL, Y, src);
Regs[ALU] &= 0xC0;
@@ -617,12 +617,12 @@ namespace BizHawk.Emulation.Common.Components.MC6809
{
if (src == US)
{
- PopulateCURINSTR(RD_INC_OP, ALU2, src,
+ PopulateCURINSTR(RD_INC, ALU2, src,
RD_INC_OP, ADDR, src, SET_ADDR_PUL, SP, src);
}
else
{
- PopulateCURINSTR(RD_INC_OP, ALU2, src,
+ PopulateCURINSTR(RD_INC, ALU2, src,
RD_INC_OP, ADDR, src, SET_ADDR_PUL, US, src);
}
@@ -630,7 +630,7 @@ namespace BizHawk.Emulation.Common.Components.MC6809
}
else if (Regs[ALU].Bit(7))
{
- PopulateCURINSTR(RD_INC_OP, ALU2, src,
+ PopulateCURINSTR(RD_INC, ALU2, src,
RD_INC_OP, ADDR, src, SET_ADDR_PUL, PC, src);
Regs[ALU] = 0;
diff --git a/BizHawk.Emulation.Cores/CPUs/MC6809/Operations.cs b/BizHawk.Emulation.Cores/CPUs/MC6809/Operations.cs
index 5c06f9296e..6ce7fb9836 100644
--- a/BizHawk.Emulation.Cores/CPUs/MC6809/Operations.cs
+++ b/BizHawk.Emulation.Cores/CPUs/MC6809/Operations.cs
@@ -85,6 +85,35 @@ namespace BizHawk.Emulation.Common.Components.MC6809
Regs[dest] = Regs[src];
}
+ public void LD_8_Func(ushort dest, ushort src)
+ {
+ Regs[dest] = Regs[src];
+
+ FlagZ = (Regs[dest] & 0xFF) == 0;
+ FlagV = false;
+ FlagN = (Regs[dest] & 0xFF) > 127;
+ }
+
+ public void LD_16_Func(ushort dest, ushort src_h, ushort src_l)
+ {
+ Regs[dest] = (ushort)(Regs[src_h] << 8 | Regs[src_l]);
+
+ FlagZ = Regs[dest] == 0;
+ FlagV = false;
+ FlagN = Regs[dest] > 0x7FFF;
+ }
+
+ // for LEAX/Y, zero flag can be effected, but not for U/S
+ public void LEA_Func(ushort dest, ushort src)
+ {
+ Regs[dest] = Regs[src];
+
+ if ((dest == X) || (dest == Y))
+ {
+ FlagZ = Regs[dest] == 0;
+ }
+ }
+
public void TST_Func(ushort src)
{
FlagZ = Regs[src] == 0;
diff --git a/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.cs b/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.cs
index 330d669ef8..938e521207 100644
--- a/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.cs
+++ b/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.cs
@@ -183,9 +183,21 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII
private void SetCallbacks()
{
- _machine.Memory.ReadCallback = (addr) => MemoryCallbacks.CallReads(addr, "System Bus");
- _machine.Memory.WriteCallback = (addr) => MemoryCallbacks.CallWrites(addr, "System Bus");
- _machine.Memory.ExecuteCallback = (addr) => MemoryCallbacks.CallExecutes(addr, "System Bus");
+ _machine.Memory.ReadCallback = (addr) =>
+ {
+ uint flags = (uint)(MemoryCallbackFlags.AccessRead);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
+ };
+ _machine.Memory.WriteCallback = (addr) =>
+ {
+ uint flags = (uint)(MemoryCallbackFlags.AccessWrite);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
+ };
+ _machine.Memory.ExecuteCallback = (addr) =>
+ {
+ uint flags = (uint)(MemoryCallbackFlags.AccessExecute);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
+ };
_machine.Memory.InputCallback = InputCallbacks.Call;
}
}
diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.Core.cs b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.Core.cs
index 4d9bb84286..bef82b1590 100644
--- a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.Core.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.Core.cs
@@ -160,7 +160,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_mapper.Bit13 = addr.Bit(13);
var temp = _mapper.ReadMemory((ushort)(addr & 0x1FFF));
_tia.BusState = temp;
- MemoryCallbacks.CallReads(addr, "System Bus");
+ var flags = (uint)(MemoryCallbackFlags.AccessRead);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
return temp;
}
@@ -180,8 +181,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
_mapper.WriteMemory((ushort)(addr & 0x1FFF), value);
-
- MemoryCallbacks.CallWrites(addr, "System Bus");
+ var flags = (uint)(MemoryCallbackFlags.AccessWrite);
+ MemoryCallbacks.CallMemoryCallbacks(addr, value, flags, "System Bus");
}
internal void PokeMemory(ushort addr, byte value)
@@ -191,7 +192,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
private void ExecFetch(ushort addr)
{
- MemoryCallbacks.CallExecutes(addr, "System Bus");
+ var flags = (uint)(MemoryCallbackFlags.AccessExecute);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
}
private void RebootCore()
diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs
index 93f6a3b1ad..d7b2901d1e 100644
--- a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs
@@ -126,10 +126,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
private HMoveData _hmove;
private BallData _ball;
- private readonly Audio[] AUD = { new Audio(), new Audio() };
+ private readonly Audio AUD =new Audio();
// current audio register state used to sample correct positions in the scanline (clrclk 0 and 114)
- ////public byte[] current_audio_register = new byte[6];
public readonly short[] LocalAudioCycles = new short[2000];
private static int ReverseBits(int value, int bits)
@@ -809,8 +808,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
if (AudioClocks < 2000)
{
- LocalAudioCycles[AudioClocks] += (short)(AUD[0].Cycle() / 2);
- LocalAudioCycles[AudioClocks] += (short)(AUD[1].Cycle() / 2);
+ LocalAudioCycles[AudioClocks] += (short)(AUD.Cycle_L() / 2);
+ LocalAudioCycles[AudioClocks] += (short)(AUD.Cycle_R() / 2);
AudioClocks++;
}
}
@@ -1258,27 +1257,27 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
else if (maskedAddr == 0x15) // AUDC0
{
- AUD[0].AUDC = (byte)(value & 15);
+ AUD.AUDC_L = (byte)(value & 15);
}
else if (maskedAddr == 0x16) // AUDC1
{
- AUD[1].AUDC = (byte)(value & 15);
+ AUD.AUDC_R = (byte)(value & 15);
}
else if (maskedAddr == 0x17) // AUDF0
{
- AUD[0].AUDF = (byte)((value & 31) + 1);
+ AUD.AUDF_L = (byte)((value & 31) + 1);
}
else if (maskedAddr == 0x18) // AUDF1
{
- AUD[1].AUDF = (byte)((value & 31) + 1);
+ AUD.AUDF_R = (byte)((value & 31) + 1);
}
else if (maskedAddr == 0x19) // AUDV0
{
- AUD[0].AUDV = (byte)(value & 15);
+ AUD.AUDV_L = (byte)(value & 15);
}
else if (maskedAddr == 0x1A) // AUDV1
{
- AUD[1].AUDV = (byte)(value & 15);
+ AUD.AUDV_R = (byte)(value & 15);
}
else if (maskedAddr == 0x1B) // GRP0
{
diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.Audio.cs b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.Audio.cs
index 3c84e12bff..fa95102db1 100644
--- a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.Audio.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.Audio.cs
@@ -8,88 +8,98 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
public class Audio
{
// noise/division control
- public byte AUDC = 0;
+ public byte AUDC_L = 0;
+ public byte AUDC_R = 0;
// frequency divider
- public byte AUDF = 1;
+ public byte AUDF_L = 1;
+ public byte AUDF_R = 1;
// volume
- public byte AUDV = 0;
+ public byte AUDV_L = 0;
+ public byte AUDV_R = 0;
// 2 state counter
- private bool sr1 = true;
+ private bool sr1_L = true;
+ private bool sr1_R = true;
// 4 bit shift register
- private int sr4 = 0x0f;
+ private int sr4_L = 0x0f;
+ private int sr4_R = 0x0f;
// 5 bit shift register
- private int sr5 = 0x1f;
+ private int sr5_L = 0x1f;
+ private int sr5_R = 0x1f;
// 9 bit shift register
- private int sr9 = 0x1ff;
+ private int sr9_L = 0x1ff;
+ private int sr9_R = 0x1ff;
// 3 state counter
- private int sr3 = 2;
+ private int sr3_L = 2;
+ private int sr3_R = 2;
// counter based off AUDF
- private byte freqcnt;
+ private byte freqcnt_L;
+ private byte freqcnt_R;
// latched audio value
- private bool on = true;
+ private bool on_L = true;
+ private bool on_R = true;
- private bool Run3()
+ private bool Run3_L()
{
- sr3++;
- if (sr3 == 3)
+ sr3_L++;
+ if (sr3_L == 3)
{
- sr3 = 0;
+ sr3_L = 0;
return true;
}
return false;
}
- private bool Run4()
+ private bool Run4_L()
{
- bool ret = (sr4 & 1) != 0;
- bool c = ((sr4 & 1) != 0) ^ ((sr4 & 2) != 0);
- sr4 = (sr4 >> 1) | (c ? 8 : 0);
+ bool ret = (sr4_L & 1) != 0;
+ bool c = ((sr4_L & 1) != 0) ^ ((sr4_L & 2) != 0);
+ sr4_L = (sr4_L >> 1) | (c ? 8 : 0);
return ret;
}
- private bool Run5()
+ private bool Run5_L()
{
- bool ret = (sr5 & 1) != 0;
- bool c = ((sr5 & 1) != 0) ^ ((sr5 & 4) != 0);
- sr5 = (sr5 >> 1) | (c ? 16 : 0);
+ bool ret = (sr5_L & 1) != 0;
+ bool c = ((sr5_L & 1) != 0) ^ ((sr5_L & 4) != 0);
+ sr5_L = (sr5_L >> 1) | (c ? 16 : 0);
return ret;
}
- private bool One4()
+ private bool One4_L()
{
- bool ret = (sr4 & 1) != 0;
- sr4 = (sr4 >> 1) | 8;
+ bool ret = (sr4_L & 1) != 0;
+ sr4_L = (sr4_L >> 1) | 8;
return ret;
}
- private bool One5()
+ private bool One5_L()
{
- bool ret = (sr5 & 1) != 0;
- sr5 = (sr5 >> 1) | 16;
+ bool ret = (sr5_L & 1) != 0;
+ sr5_L = (sr5_L >> 1) | 16;
return ret;
}
- private bool Run1()
+ private bool Run1_L()
{
- sr1 = !sr1;
- return !sr1;
+ sr1_L = !sr1_L;
+ return !sr1_L;
}
- private bool Run9()
+ private bool Run9_L()
{
- bool ret = (sr9 & 1) != 0;
- bool c = ((sr9 & 1) != 0) ^ ((sr9 & 16) != 0);
- sr9 = (sr9 >> 1) | (c ? 256 : 0);
+ bool ret = (sr9_L & 1) != 0;
+ bool c = ((sr9_L & 1) != 0) ^ ((sr9_L & 16) != 0);
+ sr9_L = (sr9_L >> 1) | (c ? 256 : 0);
return ret;
}
@@ -97,92 +107,92 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
/// call me approx 31k times a second
///
/// 16 bit audio sample
- public short Cycle()
+ public short Cycle_L()
{
- if (++freqcnt >= AUDF)
+ if (++freqcnt_L >= AUDF_L)
{
- freqcnt = 0;
- switch (AUDC)
+ freqcnt_L = 0;
+ switch (AUDC_L)
{
case 0x00:
case 0x0b:
// Both have a 1 s
- One5();
- on = One4();
+ One5_L();
+ on_L = One4_L();
break;
case 0x01:
// Both run, but the 5 bit is ignored
- on = Run4();
+ on_L = Run4_L();
//Run5();
break;
case 0x02:
- if ((sr5 & 0x0f) == 0 || (sr5 & 0x0f) == 0x0f)
+ if ((sr5_L & 0x0f) == 0 || (sr5_L & 0x0f) == 0x0f)
{
- on = Run4();
+ on_L = Run4_L();
}
- Run5();
+ Run5_L();
break;
case 0x03:
- if (Run5())
+ if (Run5_L())
{
- on = Run4();
+ on_L = Run4_L();
}
break;
case 0x04:
- Run5();
- One4();
- on = Run1();
+ Run5_L();
+ One4_L();
+ on_L = Run1_L();
break;
case 0x05:
- One5();
- Run4();
- on = Run1();
+ One5_L();
+ Run4_L();
+ on_L = Run1_L();
break;
case 0x06:
case 0x0a:
- Run5();
- if ((sr5 & 0x0f) == 0)
+ Run5_L();
+ if ((sr5_L & 0x0f) == 0)
{
- on = false;
+ on_L = false;
}
- else if ((sr5 & 0x0f) == 0x0f)
+ else if ((sr5_L & 0x0f) == 0x0f)
{
- on = true;
+ on_L = true;
}
break;
case 0x07:
case 0x09:
- on = Run5();
+ on_L = Run5_L();
break;
case 0x08:
- on = Run9();
+ on_L = Run9_L();
break;
case 0x0c:
case 0x0d:
- if (Run3())
+ if (Run3_L())
{
- on = Run1();
+ on_L = Run1_L();
}
break;
case 0x0e:
- if (Run3())
+ if (Run3_L())
{
goto case 0x06;
}
break;
case 0x0f:
- if (Run3())
+ if (Run3_L())
{
goto case 0x07;
}
@@ -191,21 +201,189 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
- return (short)(on ? AUDV * 1092 : 0);
+ return (short)(on_L ? AUDV_L * 1092 : 0);
+ }
+
+ private bool Run3_R()
+ {
+ sr3_R++;
+ if (sr3_R == 3)
+ {
+ sr3_R = 0;
+ return true;
+ }
+
+ return false;
+ }
+
+ private bool Run4_R()
+ {
+ bool ret = (sr4_R & 1) != 0;
+ bool c = ((sr4_R & 1) != 0) ^ ((sr4_R & 2) != 0);
+ sr4_R = (sr4_R >> 1) | (c ? 8 : 0);
+ return ret;
+ }
+
+ private bool Run5_R()
+ {
+ bool ret = (sr5_R & 1) != 0;
+ bool c = ((sr5_R & 1) != 0) ^ ((sr5_R & 4) != 0);
+ sr5_R = (sr5_R >> 1) | (c ? 16 : 0);
+ return ret;
+ }
+
+ private bool One4_R()
+ {
+ bool ret = (sr4_R & 1) != 0;
+ sr4_R = (sr4_R >> 1) | 8;
+ return ret;
+ }
+
+ private bool One5_R()
+ {
+ bool ret = (sr5_R & 1) != 0;
+ sr5_R = (sr5_R >> 1) | 16;
+ return ret;
+ }
+
+ private bool Run1_R()
+ {
+ sr1_R = !sr1_R;
+ return !sr1_R;
+ }
+
+ private bool Run9_R()
+ {
+ bool ret = (sr9_R & 1) != 0;
+ bool c = ((sr9_R & 1) != 0) ^ ((sr9_R & 16) != 0);
+ sr9_R = (sr9_R >> 1) | (c ? 256 : 0);
+ return ret;
+ }
+
+ ///
+ /// call me approx 31k times a second
+ ///
+ /// 16 bit audio sample
+ public short Cycle_R()
+ {
+ if (++freqcnt_R >= AUDF_R)
+ {
+ freqcnt_R = 0;
+ switch (AUDC_R)
+ {
+ case 0x00:
+ case 0x0b:
+ // Both have a 1 s
+ One5_R();
+ on_R = One4_R();
+ break;
+
+ case 0x01:
+ // Both run, but the 5 bit is ignored
+ on_R = Run4_R();
+ //Run5();
+ break;
+ case 0x02:
+ if ((sr5_R & 0x0f) == 0 || (sr5_R & 0x0f) == 0x0f)
+ {
+ on_R = Run4_R();
+ }
+
+ Run5_R();
+ break;
+ case 0x03:
+ if (Run5_R())
+ {
+ on_R = Run4_R();
+ }
+
+ break;
+
+ case 0x04:
+ Run5_R();
+ One4_R();
+ on_R = Run1_R();
+ break;
+
+ case 0x05:
+ One5_R();
+ Run4_R();
+ on_R = Run1_R();
+ break;
+
+ case 0x06:
+ case 0x0a:
+ Run5_R();
+ if ((sr5_R & 0x0f) == 0)
+ {
+ on_R = false;
+ }
+ else if ((sr5_R & 0x0f) == 0x0f)
+ {
+ on_R = true;
+ }
+
+ break;
+
+ case 0x07:
+ case 0x09:
+ on_R = Run5_R();
+ break;
+
+ case 0x08:
+ on_R = Run9_R();
+ break;
+ case 0x0c:
+ case 0x0d:
+ if (Run3_R())
+ {
+ on_R = Run1_R();
+ }
+
+ break;
+ case 0x0e:
+ if (Run3_R())
+ {
+ goto case 0x06;
+ }
+
+ break;
+ case 0x0f:
+ if (Run3_R())
+ {
+ goto case 0x07;
+ }
+
+ break;
+ }
+ }
+
+ return (short)(on_R ? AUDV_R * 1092 : 0);
}
public void SyncState(Serializer ser)
{
- ser.Sync(nameof(AUDC), ref AUDC);
- ser.Sync(nameof(AUDF), ref AUDF);
- ser.Sync(nameof(AUDV), ref AUDV);
- ser.Sync(nameof(sr1), ref sr1);
- ser.Sync(nameof(sr3), ref sr3);
- ser.Sync(nameof(sr4), ref sr4);
- ser.Sync(nameof(sr5), ref sr5);
- ser.Sync(nameof(sr9), ref sr9);
- ser.Sync(nameof(freqcnt), ref freqcnt);
- ser.Sync(nameof(on), ref on);
+ ser.Sync(nameof(AUDC_L), ref AUDC_L);
+ ser.Sync(nameof(AUDF_L), ref AUDF_L);
+ ser.Sync(nameof(AUDV_L), ref AUDV_L);
+ ser.Sync(nameof(sr1_L), ref sr1_L);
+ ser.Sync(nameof(sr3_L), ref sr3_L);
+ ser.Sync(nameof(sr4_L), ref sr4_L);
+ ser.Sync(nameof(sr5_L), ref sr5_L);
+ ser.Sync(nameof(sr9_L), ref sr9_L);
+ ser.Sync(nameof(freqcnt_L), ref freqcnt_L);
+ ser.Sync(nameof(on_L), ref on_L);
+
+ ser.Sync(nameof(AUDC_R), ref AUDC_R);
+ ser.Sync(nameof(AUDF_R), ref AUDF_R);
+ ser.Sync(nameof(AUDV_R), ref AUDV_R);
+ ser.Sync(nameof(sr1_R), ref sr1_R);
+ ser.Sync(nameof(sr3_R), ref sr3_R);
+ ser.Sync(nameof(sr4_R), ref sr4_R);
+ ser.Sync(nameof(sr5_R), ref sr5_R);
+ ser.Sync(nameof(sr9_R), ref sr9_R);
+ ser.Sync(nameof(freqcnt_R), ref freqcnt_R);
+ ser.Sync(nameof(on_R), ref on_R);
}
}
}
diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.SyncState.cs b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.SyncState.cs
index 43ad77adb1..252f74e644 100644
--- a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.SyncState.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.SyncState.cs
@@ -72,6 +72,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
ser.Sync(nameof(AudioClocks), ref AudioClocks);
ser.Sync(nameof(New_Frame), ref New_Frame);
+ ser.BeginSection("Audio");
+ AUD.SyncState(ser);
+ ser.EndSection();
+
ser.BeginSection("Player0");
_player0.SyncState(ser);
ser.EndSection();
diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs
index 2651c1f893..bf70777b4a 100644
--- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs
@@ -291,7 +291,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
private void ExecFetch(ushort addr)
{
- MemoryCallbacks.CallExecutes(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessExecute);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
}
private void Reset_Mapper(string m)
diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/MemoryMap.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/MemoryMap.cs
index 6f3e76aba5..7f871dc7a4 100644
--- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/MemoryMap.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/MemoryMap.cs
@@ -20,7 +20,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
{
public byte ReadMemory(ushort addr)
{
- MemoryCallbacks.CallReads(addr, "System Bus");
+ uint flags = (uint)(Common.MemoryCallbackFlags.AccessRead);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
if ((addr & 0xFCE0) == 0)
{
@@ -98,7 +99,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
public void WriteMemory(ushort addr, byte value)
{
- MemoryCallbacks.CallWrites(addr, "System Bus");
+ uint flags = (uint)(Common.MemoryCallbackFlags.AccessWrite);
+ MemoryCallbacks.CallMemoryCallbacks(addr, value, flags, "System Bus");
if ((addr & 0xFCE0) == 0)
{
diff --git a/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/HW_Registers.cs b/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/HW_Registers.cs
index bbc833d62b..49b52c5906 100644
--- a/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/HW_Registers.cs
+++ b/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/HW_Registers.cs
@@ -17,6 +17,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
public partial class VectrexHawk
{
public byte dir_dac, dir_ctrl;
+ public byte reg_A, reg_B;
public byte portB_ret, portA_ret;
@@ -111,20 +112,26 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
case 0x0:
wrt_val = (byte)(value & dir_ctrl);
+ portB_ret = (byte)(wrt_val | (reg_B & ~(dir_ctrl)));
+
int_fl &= 0xE7;
update_int_fl();
break;
case 0x1:
wrt_val = (byte)(value & dir_dac);
+ portA_ret = (byte)(wrt_val | (reg_A & ~(dir_dac)));
+
int_fl &= 0xFC;
update_int_fl();
break;
case 0x2:
dir_ctrl = value;
+ Console.WriteLine("dir_ctrl: " + value);
break;
case 0x3:
dir_dac = value;
+ Console.WriteLine("dir_dac: " + value);
break;
case 0x4:
t1_low = value;
diff --git a/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/MemoryMap.cs b/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/MemoryMap.cs
index dc94847b60..3d28d0d5e6 100644
--- a/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/MemoryMap.cs
+++ b/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/MemoryMap.cs
@@ -20,7 +20,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
{
public byte ReadMemory(ushort addr)
{
- MemoryCallbacks.CallReads(addr, "System Bus");
+ uint flags = (uint)MemoryCallbackFlags.AccessRead;
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
if (addr < 0x8000)
{
@@ -54,7 +55,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
public void WriteMemory(ushort addr, byte value)
{
- MemoryCallbacks.CallWrites(addr, "System Bus");
+ uint flags = (uint)MemoryCallbackFlags.AccessWrite;
+ MemoryCallbacks.CallMemoryCallbacks(addr, value, flags, "System Bus");
if (addr < 0x8000)
{
diff --git a/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.cs b/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.cs
index bbf36349b5..6e297f9b6a 100644
--- a/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.cs
+++ b/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.cs
@@ -68,6 +68,21 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
Console.WriteLine("SHA1:" + rom.HashSHA1(0, rom.Length));
_rom = rom;
+
+ // mirror games that are too small
+ if (_rom.Length < 0x8000)
+ {
+ _rom = new byte[0x8000];
+
+ for (int i = 0; i < 0x8000 / rom.Length; i++)
+ {
+ for (int j = 0; j < rom.Length; j++)
+ {
+ _rom[j + i * rom.Length] = rom[j];
+ }
+ }
+ }
+
Setup_Mapper();
_frameHz = 60;
@@ -108,12 +123,14 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
private void ExecFetch(ushort addr)
{
- MemoryCallbacks.CallExecutes(addr, "System Bus");
+ uint flags = (uint)MemoryCallbackFlags.AccessExecute;
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
}
private void Setup_Mapper()
{
mapper = new MapperDefault();
+ mapper.Core = this;
}
}
}
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs
index 06c9737275..245b7f7841 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs
@@ -3,7 +3,7 @@ using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.GBA
{
- [Core("mGBA", "endrift", true, true, "0.6.3 (c4dfb265c35ecba4050d646bd65a02d8b3704948)", "https://mgba.io/", false)]
+ [Core("mGBA", "endrift", true, true, "0.7.2", "https://mgba.io/", false)]
[ServiceNotApplicable(typeof(IDriveLight), typeof(IRegionable))]
public partial class MGBAHawk : IEmulator, IVideoProvider, ISoundProvider, IGBAGPUViewable,
ISaveRam, IStatable, IInputPollable, ISettable,
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs
index 72cb7af7ca..843377bcc7 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs
@@ -168,9 +168,20 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
void InitCallbacks()
{
padcb = new LibVBANext.StandardCallback(() => InputCallbacks.Call());
- fetchcb = new LibVBANext.AddressCallback((addr) => MemoryCallbacks.CallExecutes(addr, "System Bus"));
- readcb = new LibVBANext.AddressCallback((addr) => MemoryCallbacks.CallReads(addr, "System Bus"));
- writecb = new LibVBANext.AddressCallback((addr) => MemoryCallbacks.CallWrites(addr, "System Bus"));
+ fetchcb = new LibVBANext.AddressCallback((addr) => {
+ uint flags = (uint)(MemoryCallbackFlags.AccessExecute);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
+ });
+ readcb = new LibVBANext.AddressCallback((addr) =>
+ {
+ uint flags = (uint)(MemoryCallbackFlags.AccessRead);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
+ });
+ writecb = new LibVBANext.AddressCallback((addr) =>
+ {
+ uint flags = (uint)(MemoryCallbackFlags.AccessWrite);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
+ });
tracecb = new LibVBANext.TraceCallback((addr, opcode) => Tracer.Put(Trace(addr, opcode)));
_inputCallbacks.ActiveChanged += SyncPadCallback;
_memorycallbacks.ActiveChanged += SyncMemoryCallbacks;
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs
index cf3a5123f2..5a7d688cd9 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs
@@ -294,7 +294,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
private void ExecFetch(ushort addr)
{
- MemoryCallbacks.CallExecutes(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessRead);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
}
private void Setup_Mapper()
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/MemoryMap.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/MemoryMap.cs
index fdeafdc9e3..a3a4d1b2db 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/MemoryMap.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/MemoryMap.cs
@@ -29,7 +29,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
{
public byte ReadMemory(ushort addr)
{
- MemoryCallbacks.CallReads(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessRead);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
addr_access = addr;
if (ppu.DMA_start)
@@ -157,7 +158,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
public void WriteMemory(ushort addr, byte value)
{
- MemoryCallbacks.CallWrites(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessWrite);
+ MemoryCallbacks.CallMemoryCallbacks(addr, value, flags, "System Bus");
addr_access = addr;
if (ppu.DMA_start)
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.cs
index 4900fca9b9..4192c9bece 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.cs
@@ -93,8 +93,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink
}
private void ExecFetch(ushort addr)
- {
- MemoryCallbacks.CallExecutes(addr, "System Bus");
+ {
+ uint flags = (uint)(MemoryCallbackFlags.AccessExecute);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
}
}
}
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IDebuggable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IDebuggable.cs
index 075ee71d27..17e1041253 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IDebuggable.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IDebuggable.cs
@@ -59,19 +59,22 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
private void ReadCallback(uint address, ulong cycleOffset)
{
callbackCycleCount = _cycleCount + cycleOffset;
- MemoryCallbacks.CallReads(address, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessRead);
+ MemoryCallbacks.CallMemoryCallbacks(address, 0, flags, "System Bus");
}
private void WriteCallback(uint address, ulong cycleOffset)
{
callbackCycleCount = _cycleCount + cycleOffset;
- MemoryCallbacks.CallWrites(address, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessWrite);
+ MemoryCallbacks.CallMemoryCallbacks(address, 0, flags,"System Bus");
}
private void ExecCallback(uint address, ulong cycleOffset)
{
callbackCycleCount = _cycleCount + cycleOffset;
- MemoryCallbacks.CallExecutes(address, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessExecute);
+ MemoryCallbacks.CallMemoryCallbacks(address, 0, flags, "System Bus");
}
///
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISaveRam.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISaveRam.cs
index 3776eb00f7..218d2bf3ec 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISaveRam.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISaveRam.cs
@@ -41,31 +41,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
break;
default:
throw new ArgumentException("Size of saveram data does not match expected!");
- case 44:
- data = FixRTC(data, 44);
- break;
- case 40:
- data = FixRTC(data, 40);
- break;
}
LibGambatte.gambatte_loadsavedata(GambatteState, data);
}
-
- private byte[] FixRTC(byte[] data, int offset)
- {
- // length - offset is the start of the VBA-only data; so
- // length - offset - 4 is the start of the RTC block
- int idx = data.Length - offset - 4;
-
- byte[] ret = new byte[idx + 4];
- Buffer.BlockCopy(data, 0, ret, 0, idx);
- data[idx] = (byte)zerotime;
- data[idx + 1] = (byte)(zerotime >> 8);
- data[idx + 2] = (byte)(zerotime >> 16);
- data[idx + 3] = (byte)(zerotime >> 24);
-
- return ret;
- }
}
}
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs
index 297b029f11..70a2aef2fe 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs
@@ -116,17 +116,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
[DefaultValue(false)]
public bool RealTimeRTC { get; set; }
- [DisplayName("RTC Initial Time")]
- [Description("Set the initial RTC time in terms of elapsed seconds. Only used when RealTimeRTC is false.")]
+ [DisplayName("RTC Divisor Offset")]
+ [Description("CPU clock frequency relative to real time clock. Base value is 2^22 Hz. Used in cycle-based RTC to sync on real hardware to account for RTC imperfections.")]
[DefaultValue(0)]
- public int RTCInitialTime
- {
- get { return _RTCInitialTime; }
- set { _RTCInitialTime = Math.Max(0, Math.Min(1024 * 24 * 60 * 60, value)); }
- }
-
- [JsonIgnore]
- private int _RTCInitialTime;
+ public int RTCDivisorOffset { get; set; }
[DisplayName("Equal Length Frames")]
[Description("When false, emulation frames sync to vblank. Only useful for high level TASing.")]
@@ -141,11 +134,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
[DeepEqualsIgnore]
private bool _equalLengthFrames;
- [DisplayName("Initial DIV offset")]
- [Description("Internal. Probably doesn't work. Leave this set to 0. Accepts values from 0 to 65532 in steps of 4")]
- [DefaultValue(0)]
- public int InitialDiv { get; set; }
-
public GambatteSyncSettings()
{
SettingsUtil.SetDefaultValues(this);
@@ -160,11 +148,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
{
return !DeepEquality.DeepEquals(x, y);
}
-
- public uint GetInitialDivInternal()
- {
- return (uint)(InitialDiv & 0xfffc);
- }
}
}
}
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs
index ad53a9b698..0de16d0723 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs
@@ -58,13 +58,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
{
_syncSettings = (GambatteSyncSettings)syncSettings ?? new GambatteSyncSettings();
- // copy over non-loadflag syncsettings now; they won't take effect if changed later
- zerotime = (uint)_syncSettings.RTCInitialTime;
-
- real_rtc_time = !DeterministicEmulation && _syncSettings.RealTimeRTC;
-
- DivInternal = _syncSettings.GetInitialDivInternal();
-
LibGambatte.LoadFlags flags = 0;
switch (_syncSettings.ConsoleMode)
@@ -90,33 +83,26 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
flags |= LibGambatte.LoadFlags.MULTICART_COMPAT;
}
- if (LibGambatte.gambatte_load(GambatteState, file, (uint)file.Length, GetCurrentTime(), flags, DivInternal) != 0)
+ if (LibGambatte.gambatte_load(GambatteState, file, (uint)file.Length, flags) != 0)
{
throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_load)}() returned non-zero (is this not a gb or gbc rom?)");
}
+ byte[] Bios;
if ((flags & LibGambatte.LoadFlags.FORCE_DMG) == LibGambatte.LoadFlags.FORCE_DMG)
{
- byte[] Bios = comm.CoreFileProvider.GetFirmware("GB", "World", true, "BIOS Not Found, Cannot Load");
-
+ Bios = comm.CoreFileProvider.GetFirmware("GB", "World", true, "BIOS Not Found, Cannot Load");
IsCgb = false;
-
- if (LibGambatte.gambatte_loaddmgbios(GambatteState, Bios) != 0)
- {
- throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_loaddmgbios)}() returned non-zero (bios error)");
- }
}
else
{
- byte[] Bios = comm.CoreFileProvider.GetFirmware("GBC", "World", true, "BIOS Not Found, Cannot Load");
-
+ Bios = comm.CoreFileProvider.GetFirmware("GBC", "World", true, "BIOS Not Found, Cannot Load");
IsCgb = true;
-
- if (LibGambatte.gambatte_loadgbcbios(GambatteState, Bios) != 0)
- {
- throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_loadgbcbios)}() returned non-zero (bios error)");
- }
}
+ if (LibGambatte.gambatte_loadbios(GambatteState, Bios, (uint)Bios.Length) != 0)
+ {
+ throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_loadbios)}() returned non-zero (bios error)");
+ }
// set real default colors (before anyone mucks with them at all)
PutSettings((GambatteSettings)settings ?? new GambatteSettings());
@@ -140,8 +126,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
string romname = System.Text.Encoding.ASCII.GetString(buff);
Console.WriteLine("Core reported rom name: {0}", romname);
- TimeCallback = new LibGambatte.RTCCallback(GetCurrentTime);
- LibGambatte.gambatte_setrtccallback(GambatteState, TimeCallback);
+ if (!DeterministicEmulation && _syncSettings.RealTimeRTC)
+ {
+ LibGambatte.gambatte_settimemode(GambatteState, false);
+ }
+ LibGambatte.gambatte_setrtcdivisoroffset(GambatteState, _syncSettings.RTCDivisorOffset);
_cdCallback = new LibGambatte.CDCallback(CDCallbackProc);
@@ -174,59 +163,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
///
private LibGambatte.Buttons CurrentButtons = 0;
- private uint DivInternal = 0;
-
- #region RTC
-
- ///
- /// RTC time when emulation begins.
- ///
- private readonly uint zerotime = 0;
-
- ///
- /// if true, RTC will run off of real elapsed time
- ///
- private bool real_rtc_time = false;
-
- private LibGambatte.RTCCallback TimeCallback;
-
- private static long GetUnixNow()
- {
- // because internally the RTC works off of relative time, we don't need to base
- // this off of any particular canonical epoch.
- return DateTime.UtcNow.Ticks / 10000000L - 60000000000L;
- }
-
- private uint GetCurrentTime()
- {
- if (real_rtc_time)
- {
- return (uint)GetUnixNow();
- }
-
- ulong fn = (ulong)Frame;
-
- // as we're exactly tracking cpu cycles, this can be pretty accurate
- fn *= 4389;
- fn /= 262144;
- fn += zerotime;
- return (uint)fn;
- }
-
- private uint GetInitialTime()
- {
- if (real_rtc_time)
- {
- return (uint)GetUnixNow();
- }
-
- // setting the initial boot time to 0 will cause our zerotime
- // to function as an initial offset, which is what we want
- return 0;
- }
-
- #endregion
-
#region ALL SAVESTATEABLE STATE GOES HERE
///
@@ -327,7 +263,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
if (controller.IsPressed("Power"))
{
- LibGambatte.gambatte_reset(GambatteState, GetCurrentTime(), DivInternal);
+ LibGambatte.gambatte_reset(GambatteState);
}
if (Tracer.Enabled)
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs
index 1fb710656d..ede91383bf 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs
@@ -47,29 +47,20 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
/// opaque state pointer
/// the rom data, can be disposed of once this function returns
/// length of romdata in bytes
- /// RTC time when the rom is loaded
/// ORed combination of LoadFlags.
/// 0 on success, negative value on failure.
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
- public static extern int gambatte_load(IntPtr core, byte[] romdata, uint length, long now, LoadFlags flags, uint div);
+ public static extern int gambatte_load(IntPtr core, byte[] romdata, uint length, LoadFlags flags);
///
- /// Load GB BIOS image.
+ /// Load GB(C) BIOS image.
///
/// opaque state pointer
/// the bios data, can be disposed of once this function returns
+ /// length of romdata in bytes
/// 0 on success, negative value on failure.
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
- public static extern int gambatte_loaddmgbios(IntPtr core, byte[] biosdata);
-
- ///
- /// Load GBC BIOS image.
- ///
- /// opaque state pointer
- /// the bios data, can be disposed of once this function returns
- /// 0 on success, negative value on failure.
- [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
- public static extern int gambatte_loadgbcbios(IntPtr core, byte[] biosdata);
+ public static extern int gambatte_loadbios(IntPtr core, byte[] biosdata, uint length);
///
/// Emulates until at least 'samples' stereo sound samples are produced in the supplied buffer,
@@ -114,9 +105,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
/// Equivalent to reloading a ROM image, or turning a Game Boy Color off and on again.
///
/// opaque state pointer
- /// RTC time when the reset occurs
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
- public static extern void gambatte_reset(IntPtr core, long now, uint div);
+ public static extern void gambatte_reset(IntPtr core);
///
/// palette type for gambatte_setdmgpalettecolor
@@ -254,21 +244,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
/// 0-153 inclusive
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gambatte_setscanlinecallback(IntPtr core, ScanlineCallback callback, int sl);
-
- ///
- /// type of the RTC callback
- ///
- /// what time is it, unixy
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate uint RTCCallback();
-
- ///
- /// sets RTC callback. probably mandatory.
- ///
- /// opaque state pointer
- /// the callback
- [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
- public static extern void gambatte_setrtccallback(IntPtr core, RTCCallback callback);
///
/// type of the link data sent callback
@@ -284,6 +259,24 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gambatte_setlinkcallback(IntPtr core, LinkCallback callback);
+ ///
+ /// Changes between cycle-based and real-time RTC. Defaults to cycle-based.
+ ///
+ /// opaque state pointer
+ /// use cycle-based RTC
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void gambatte_settimemode(IntPtr core, bool useCycles);
+
+ ///
+ /// Adjusts the CPU clock frequency relative to real time. Base value is 2^22 Hz.
+ /// This is used to account for drift in the RTC when syncing cycle-based RTC to real hardware.
+ /// RTCs in carts are not perfectly accurate, and the value will differ from cart to cart.
+ ///
+ /// opaque state pointer
+ /// CPU frequency adjustment
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void gambatte_setrtcdivisoroffset(IntPtr core, int rtcDivisorOffset);
+
///
/// Returns true if the currently loaded ROM image is treated as having CGB support.
///
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusCoreApi.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusCoreApi.cs
index f2670ffe46..1b1107122a 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusCoreApi.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusCoreApi.cs
@@ -737,19 +737,22 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
break;
if (event_breakpoint)
{
+ MemoryCallbackFlags flags = 0;
switch (_breakparams._type)
{
case BreakType.Read:
- _breakparams._mcs.CallReads(_breakparams._addr, "System Bus");
+ flags |= MemoryCallbackFlags.AccessRead;
break;
case BreakType.Write:
- _breakparams._mcs.CallWrites(_breakparams._addr, "System Bus");
+ flags |= MemoryCallbackFlags.AccessWrite;
break;
case BreakType.Execute:
- _breakparams._mcs.CallExecutes(_breakparams._addr, "System Bus");
+ flags |= MemoryCallbackFlags.AccessExecute;
break;
}
+ _breakparams._mcs.CallMemoryCallbacks(_breakparams._addr, 0, (uint)flags, "System Bus");
+
event_breakpoint = false;
Resume();
continue;
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs
index 03e977c730..8d23b742c6 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs
@@ -897,7 +897,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
public void ExecFetch(ushort addr)
{
- MemoryCallbacks.CallExecutes(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.CPUZero | MemoryCallbackFlags.AccessExecute);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
}
public byte ReadMemory(ushort addr)
@@ -947,7 +948,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
}
}
- MemoryCallbacks.CallReads(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.CPUZero | MemoryCallbackFlags.AccessRead);
+ MemoryCallbacks.CallMemoryCallbacks(addr, ret, flags, "System Bus");
DB = ret;
return ret;
@@ -994,7 +996,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
Board.WritePRG(addr - 0x8000, value);
}
- MemoryCallbacks.CallWrites(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.CPUZero | MemoryCallbackFlags.AccessWrite | MemoryCallbackFlags.SizeByte);
+ MemoryCallbacks.CallMemoryCallbacks(addr, value, flags, "System Bus");
}
// the palette for each VS game needs to be chosen explicitly since there are 6 different ones.
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs
index e86ee2c289..b76b42954c 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs
@@ -364,7 +364,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
private void ReadHook(uint addr)
{
- MemoryCallbacks.CallReads(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessRead);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
// we RefreshMemoryCallbacks() after the trigger in case the trigger turns itself off at that point
// EDIT: for now, theres some IPC re-entrancy problem
// RefreshMemoryCallbacks();
@@ -372,7 +373,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
private void ExecHook(uint addr)
{
- MemoryCallbacks.CallExecutes(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessExecute);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
// we RefreshMemoryCallbacks() after the trigger in case the trigger turns itself off at that point
// EDIT: for now, theres some IPC re-entrancy problem
// RefreshMemoryCallbacks();
@@ -380,7 +382,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
private void WriteHook(uint addr, byte val)
{
- MemoryCallbacks.CallWrites(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessWrite);
+ MemoryCallbacks.CallMemoryCallbacks(addr, val, flags, "System Bus");
// we RefreshMemoryCallbacks() after the trigger in case the trigger turns itself off at that point
// EDIT: for now, theres some IPC re-entrancy problem
// RefreshMemoryCallbacks();
@@ -388,17 +391,20 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
private void ReadHook_SMP(uint addr)
{
- MemoryCallbacks.CallReads(addr, "SMP");
+ uint flags = (uint)(MemoryCallbackFlags.AccessRead);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "SMP");
}
private void ExecHook_SMP(uint addr)
{
- MemoryCallbacks.CallExecutes(addr, "SMP");
+ uint flags = (uint)(MemoryCallbackFlags.AccessExecute);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "SMP");
}
private void WriteHook_SMP(uint addr, byte val)
{
- MemoryCallbacks.CallWrites(addr, "SMP");
+ uint flags = (uint)(MemoryCallbackFlags.AccessWrite);
+ MemoryCallbacks.CallMemoryCallbacks(addr, val, flags, "SMP");
}
private enum LoadParamType
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.cs
index 6abdd61162..a6de84103b 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.cs
@@ -72,8 +72,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
private readonly ITraceable _tracer;
private void ExecFetch(ushort addr)
- {
- MemoryCallbacks.CallExecutes(addr, "System Bus");
+ {
+ uint flags = (uint)(MemoryCallbackFlags.AccessExecute);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
}
#region ISettable
diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.cs b/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.cs
index 1401820939..9f58497577 100644
--- a/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.cs
@@ -90,7 +90,8 @@ namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
private void ExecFetch(ushort addr)
{
- MemoryCallbacks.CallExecutes(addr, "System Bus");
+ uint flags = (uint)MemoryCallbackFlags.AccessExecute;
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
}
}
}
diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs
index 68d48916a4..941851b72d 100644
--- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs
@@ -298,7 +298,8 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
public byte ReadMemory(ushort addr)
{
- MemoryCallbacks.CallReads(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessRead);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
return ReadMemoryMapper(addr);
}
@@ -307,7 +308,8 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
{
WriteMemoryMapper(addr, value);
- MemoryCallbacks.CallWrites(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessWrite);
+ MemoryCallbacks.CallMemoryCallbacks(addr, value, flags, "System Bus");
}
public byte FetchMemory(ushort addr)
@@ -317,7 +319,8 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
private void OnExecMemory(ushort addr)
{
- MemoryCallbacks.CallExecutes(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessExecute);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
}
///
diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IDebuggable.cs b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IDebuggable.cs
index 9b5e7363d9..ea17bf2374 100644
--- a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IDebuggable.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IDebuggable.cs
@@ -61,9 +61,21 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
private void InitMemCallbacks()
{
- ExecCallback = new LibGPGX.mem_cb(a => MemoryCallbacks.CallExecutes(a, "M68K BUS"));
- ReadCallback = new LibGPGX.mem_cb(a => MemoryCallbacks.CallReads(a, "M68K BUS"));
- WriteCallback = new LibGPGX.mem_cb(a => MemoryCallbacks.CallWrites(a, "M68K BUS"));
+ ExecCallback = new LibGPGX.mem_cb(a =>
+ {
+ uint flags = (uint)(MemoryCallbackFlags.AccessExecute);
+ MemoryCallbacks.CallMemoryCallbacks(a, 0, flags, "M68K BUS");
+ });
+ ReadCallback = new LibGPGX.mem_cb(a =>
+ {
+ uint flags = (uint)(MemoryCallbackFlags.AccessRead);
+ MemoryCallbacks.CallMemoryCallbacks(a, 0, flags, "M68K BUS");
+ });
+ WriteCallback = new LibGPGX.mem_cb(a =>
+ {
+ uint flags = (uint)(MemoryCallbackFlags.AccessWrite);
+ MemoryCallbacks.CallMemoryCallbacks(a, 0, flags, "M68K BUS");
+ });
_memoryCallbacks.ActiveChanged += RefreshMemCallbacks;
}
diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ITraceable.cs b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ITraceable.cs
index c8d8dab662..29bdbab675 100644
--- a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ITraceable.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ITraceable.cs
@@ -19,7 +19,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
Header = "M68K: PC, machine code, mnemonic, operands, registers (D0-D7, A0-A7, SR, USP), flags (XNZVC)";
}
- protected override void TraceFromCallback()
+ protected override void TraceFromCallback(uint addr, uint value, uint flags)
{
var regs = DebuggableCore.GetCpuFlagsAndRegisters();
uint pc = (uint)regs["M68K PC"].Value;
diff --git a/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs b/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs
index 0b2931de02..30f3bd3cac 100644
--- a/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs
@@ -880,18 +880,20 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
void ShockMemCallback(uint address, OctoshockDll.eShockMemCb type, uint size, uint value)
{
+ MemoryCallbackFlags flags = 0;
switch (type)
{
- case OctoshockDll.eShockMemCb.Read:
- MemoryCallbacks.CallReads(address, "System Bus");
+ case OctoshockDll.eShockMemCb.Read:
+ flags |= MemoryCallbackFlags.AccessRead;
break;
case OctoshockDll.eShockMemCb.Write:
- MemoryCallbacks.CallWrites(address, "System Bus");
+ flags |= MemoryCallbackFlags.AccessWrite;
break;
case OctoshockDll.eShockMemCb.Execute:
- MemoryCallbacks.CallExecutes(address, "System Bus");
+ flags |= MemoryCallbackFlags.AccessExecute;
break;
}
+ MemoryCallbacks.CallMemoryCallbacks(address, value, (uint)flags, "System Bus");
}
void InitMemCallbacks()
diff --git a/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.cs b/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.cs
index 4068514676..8ef12ba934 100644
--- a/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.cs
+++ b/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.cs
@@ -142,15 +142,18 @@ namespace BizHawk.Emulation.Cores.WonderSwan
void ReadCallback(uint addr)
{
- MemoryCallbacks.CallReads(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessRead);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
}
void WriteCallback(uint addr)
{
- MemoryCallbacks.CallWrites(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessWrite);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
}
void ExecCallback(uint addr)
{
- MemoryCallbacks.CallExecutes(addr, "System Bus");
+ uint flags = (uint)(MemoryCallbackFlags.AccessExecute);
+ MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
}
void ButtonCallback()
{
diff --git a/Bizware/BizHawk.Bizware.Test/TestImages/courier16px_0.png b/Bizware/BizHawk.Bizware.Test/TestImages/courier16px_0.png
index e9e267cf8e..36d5051db4 100644
Binary files a/Bizware/BizHawk.Bizware.Test/TestImages/courier16px_0.png and b/Bizware/BizHawk.Bizware.Test/TestImages/courier16px_0.png differ
diff --git a/Bizware/BizHawk.Bizware.Test/TestImages/flame1.jpg b/Bizware/BizHawk.Bizware.Test/TestImages/flame1.jpg
index 0645716f53..f92a9b5e93 100644
Binary files a/Bizware/BizHawk.Bizware.Test/TestImages/flame1.jpg and b/Bizware/BizHawk.Bizware.Test/TestImages/flame1.jpg differ
diff --git a/Bizware/BizHawk.Bizware.Test/TestImages/flame2.jpg b/Bizware/BizHawk.Bizware.Test/TestImages/flame2.jpg
index 8fa880ce44..2807d7bb0f 100644
Binary files a/Bizware/BizHawk.Bizware.Test/TestImages/flame2.jpg and b/Bizware/BizHawk.Bizware.Test/TestImages/flame2.jpg differ
diff --git a/Bizware/BizHawk.Bizware.Test/TestImages/flame3.jpg b/Bizware/BizHawk.Bizware.Test/TestImages/flame3.jpg
index d50f2f426e..b7bc29faa8 100644
Binary files a/Bizware/BizHawk.Bizware.Test/TestImages/flame3.jpg and b/Bizware/BizHawk.Bizware.Test/TestImages/flame3.jpg differ
diff --git a/Bizware/BizHawk.Bizware.Test/TestImages/flame4.jpg b/Bizware/BizHawk.Bizware.Test/TestImages/flame4.jpg
index a4f1722056..e1eb76106f 100644
Binary files a/Bizware/BizHawk.Bizware.Test/TestImages/flame4.jpg and b/Bizware/BizHawk.Bizware.Test/TestImages/flame4.jpg differ
diff --git a/Bizware/BizHawk.Bizware.Test/TestImages/flame5.jpg b/Bizware/BizHawk.Bizware.Test/TestImages/flame5.jpg
index 2a8d7e6d95..9b8654889b 100644
Binary files a/Bizware/BizHawk.Bizware.Test/TestImages/flame5.jpg and b/Bizware/BizHawk.Bizware.Test/TestImages/flame5.jpg differ
diff --git a/README.md b/README.md
index 2594b56d72..645d5aa29f 100644
--- a/README.md
+++ b/README.md
@@ -96,7 +96,7 @@ Released binaries can be found right here on GitHub:
Click `BizHawk-.zip` to download it. Also note the changelog, the full version of which is [here at TASVideos](http://tasvideos.org/Bizhawk/ReleaseHistory.html). **Don't mix different versions** of BizHawk, keep each version in its own folder.
-Before you start (by running `EmuHawk.exe`), you'll need the following Windows-only prerequisites installed. You can get them all at once with [this program](https://github.com/TASVideos/BizHawk-Prereqs/releases/latest).
+**Note**: Before you start (by running `EmuHawk.exe`), you'll need the Windows-only prerequisites installed. You can get them all at once with [this program](https://github.com/TASVideos/BizHawk-Prereqs/releases/latest) (you don't need to do this every time BizHawk updates, check the date on its release page, but it can't hurt installing it again to be sure). The specific libraries it installs are:
* .NET Framework 4.6.1
* Visual C++ Redists
* 2010 SP1
@@ -106,7 +106,7 @@ Before you start (by running `EmuHawk.exe`), you'll need the following Windows-o
BizHawk functions like a "portable" program, you may move or rename the folder containing `EmuHawk.exe`, even to another drive — as long as you keep all the files together, and the prerequisites are installed when you go to run it.
-Following [Microsoft's support lifecycle](https://support.microsoft.com/en-us/help/13853/windows-lifecycle-fact-sheet), Win10 is supported from 1803 "Redstone 4", Win8 is supported from 8.1, and Win7 is supported from SP1 (ends Jan 2020, upgrade to Win10 or try [ReactOS](https://reactos.org/joining/faqs)).
+Following [Microsoft's support lifecycle](https://support.microsoft.com/en-us/help/13853/windows-lifecycle-fact-sheet), Win10 is supported from 1803 "Redstone 4", Win8 is supported from 8.1 (*not* 8.0), and Win7 is supported from SP1 (ends Jan 2020, upgrade to Win10 or try [ReactOS](https://reactos.org/joining/faqs)).
A "backport" release, [1.13.2](https://github.com/TASVideos/BizHawk/releases/tag/1.13.2), is available for users of Windows XP and/or 32-bit Windows. Being in the 1.x series, many bugs remain and features are missing.
@@ -120,11 +120,9 @@ A "backport" release, [1.13.2](https://github.com/TASVideos/BizHawk/releases/tag
You'll need to either build BizHawk yourself (see [*Building*](#gnulinux-1) below), or download a dev build (see [*Testing*](#testing) below).
-The runtime dependencies are Mono (complete) + Mono VB.NET, WINE (just `libwine` if available), `libdl.so` (glibc), NVIDIA's `cgc` utility, and `libblip_buf.so` from the repo's `Assets` folder (copy it to `/usr/lib/libblip_buf.so.1.1.0` or equivalent). LSB release info is optional for automatically setting the library location.
+The runtime dependencies are: Mono "complete", Mono VB.NET, WINE (just `libwine` if available), glibc, NVIDIA's `cgc` utility, and your distro's LSB implementation. Run `EmuHawkMono.sh` to start Mono with the right library and executable paths — you can run it from anywhere, so putting it in a .desktop file is fine. If running the script doesn't start EmuHawk, it might be because the library path for your distro isn't known (if you use a terminal, it will say so in the output).
-Run `EmuHawkMono.sh` to give Mono the library and executable paths — you can run it from anywhere, so putting it in a .desktop file is fine. If running the script doesn't start EmuHawk, you may need to edit it (if you use a terminal, it will say so in the output).
-
-The systems that currently work are: GB + GBC (GBHawk), NES (NesHawk), SMS, Atari 7800, and some classic home computers. See [#1430](https://github.com/TASVideos/BizHawk/issues/1430) for progress.
+The systems that currently work are: GB + GBC (GBHawk), NES (NesHawk), SMS, Atari 7800, and some classic home computers. Nothing other than EmuHawk has been ported. See [#1430](https://github.com/TASVideos/BizHawk/issues/1430) for progress.
[to top](#bizhawk)
@@ -141,30 +139,22 @@ git clone https://github.com/TASVideos/BizHawk.git BizHawk_master
Once it's downloaded and extracted, go into the repo's `Dist` folder and run `BuildAndPackage_Release.bat`. BizHawk will be built as a .zip just like any other release.
-For anything more complicated than building, you'll need an IDE like [VS Community 2017](https://visualstudio.microsoft.com/vs/community), currently the best free C# IDE. Open `BizHawk.sln` with VS to start and use the toolbar to choose EmuHawk and build. See [Compiling at TASVideos](http://tasvideos.org/Bizhawk/Compiling.html) (somewhat outdated) for more detailed instructions.
+For anything more complicated than just building, you'll need an IDE like [VS Community 2019](https://visualstudio.microsoft.com/vs/community), currently the best free C# IDE (if you can get JetBrains tools, use Rider). Open `BizHawk.sln` with VS to start and use the toolbar to choose `BizHawk.Client.EmuHawk | Release` and build. See [Compiling at TASVideos](http://tasvideos.org/Bizhawk/Compiling.html) (somewhat outdated) for more detailed instructions.
[to top](#bizhawk)
### GNU+Linux
-*Compiling* requires MSBuild and *running* requires Mono and WINE, but **BizHawk does not run under WINE** — only the bundled libraries are required.
+Note: Currently, *running* (not building) requires WINE, but only the bundled libraries. **BizHawk should not run on WINE**.
-If you use GNU+Linux, there might be a `bizhawk-git` package or similar in the same repo as the main package. If it's available, installing it will automate the build process.
-
-Building is as easy as:
+If there is a package named `bizhawk-git` or similar in the same repo as the normal package, install that to build master. Otherwise, building is as easy as:
```sh
-git clone https://github.com/TASVideos/BizHawk.git BizHawk_master && cd BizHawk_master
-# or ssh: git clone git@github.com:TASVideos/BizHawk.git BizHawk_master && cd BizHawk_master
-msbuild /p:Configuration=Release BizHawk.sln
+git clone https://github.com/TASVideos/BizHawk.git BizHawk_master && BizHawk_master/Dist/BuildRelease.sh
+# or ssh: git clone git@github.com:TASVideos/BizHawk.git BizHawk_master && BizHawk_master/Dist/BuildRelease.sh
+# devs may use `Dist/BuildDebug.sh` instead to get `#if DEBUG` code compiled into the binaries
```
-Remove the `/p:...` flag from MSBuild if you want debugging symbols.
-
-If your distro isn't listed under *Installing* above, `libblip_buf` probably isn't in your package repos. You can easily [build it yourself](https://gitlab.com/TASVideos/libblip_buf/blob/unified/README.md).
-
-Once built, see [*Installing*](#gnulinux) above, substituting the repo's `output` folder for the download.
-
-Again, if your distro isn't listed there, you might get an "Unknown distro" warning in the terminal, and BizHawk may not open or may show the missing dependencies dialog. You may need to add your distro to the case statement in the script, setting `libpath` to the location of `d3dx9_43.dll.so` (please do share if you get it working).
+Once built, see [*Installing*](#gnulinux) above, the built output is `BizHawk_master/output`. Again, if your distro isn't in the list, you might get an "Unknown distro" warning in the terminal, and EmuHawk may not open or may show the missing dependencies dialog. You may need to add your distro to the case statement in the script, setting `libpath` to the location of `d3dx9_43.dll.so` (please do share if you get it working).
[to top](#bizhawk)
diff --git a/libgambatte/Makefile b/libgambatte/Makefile
index 33e7712716..56452b0f38 100644
--- a/libgambatte/Makefile
+++ b/libgambatte/Makefile
@@ -25,12 +25,12 @@ SRCS = \
src/cpu.cpp \
src/gambatte.cpp \
src/initstate.cpp \
- src/interrupter.cpp \
src/interruptrequester.cpp \
src/memory.cpp \
src/mem/cartridge.cpp \
src/mem/memptrs.cpp \
src/mem/rtc.cpp \
+ src/mem/time.cpp \
src/newstate.cpp \
src/sound.cpp \
src/sound/channel1.cpp \
@@ -61,6 +61,6 @@ $(TARGET) : $(OBJS)
clean:
$(RM) $(OBJS)
$(RM) $(TARGET)
-
+
install:
$(CP) $(TARGET) $(DEST_$(ARCH))
diff --git a/libgambatte/include/gambatte.h b/libgambatte/include/gambatte.h
index 94bab7befb..368b2a4727 100644
--- a/libgambatte/include/gambatte.h
+++ b/libgambatte/include/gambatte.h
@@ -1,31 +1,32 @@
-/***************************************************************************
- * Copyright (C) 2007 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2007 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#ifndef GAMBATTE_H
#define GAMBATTE_H
#include "gbint.h"
+#include "loadres.h"
+#include
#include
-#include
-#include
#include "newstate.h"
namespace gambatte {
+
enum { BG_PALETTE = 0, SP1_PALETTE = 1, SP2_PALETTE = 2 };
typedef void (*MemoryCallback)(int32_t address, int64_t cycleOffset);
@@ -48,99 +49,116 @@ class GB {
public:
GB();
~GB();
-
+
enum LoadFlag {
FORCE_DMG = 1, /**< Treat the ROM as not having CGB support regardless of what its header advertises. */
GBA_CGB = 2, /**< Use GBA intial CPU register values when in CGB mode. */
MULTICART_COMPAT = 4, /**< Use heuristics to detect and support some multicart MBCs disguised as MBC1. */
};
-
- /** Load ROM image.
+
+ /**
+ * Load ROM image.
*
- * @param romfile Path to rom image file. Typically a .gbc, .gb, or .zip-file (if zip-support is compiled in).
+ * @param romfile Path to rom image file. Typically a .gbc, .gb, or .zip-file (if
+ * zip-support is compiled in).
* @param flags ORed combination of LoadFlags.
* @return 0 on success, negative value on failure.
*/
- int load(const char *romfiledata, unsigned romfilelength, std::uint32_t now, unsigned flags, unsigned div);
-
- int loadGBCBios(const char* biosfiledata);
- int loadDMGBios(const char* biosfiledata);
+ LoadRes load(char const *romfiledata, unsigned romfilelength, unsigned flags);
- /** Emulates until at least 'samples' stereo sound samples are produced in the supplied buffer,
- * or until a video frame has been drawn.
+ int loadBios(char const *biosfiledata, std::size_t size);
+
+ /**
+ * Emulates until at least 'samples' audio samples are produced in the
+ * supplied audio buffer, or until a video frame has been drawn.
*
- * There are 35112 stereo sound samples in a video frame.
- * May run for up to 2064 stereo samples too long.
- * A stereo sample consists of two native endian 2s complement 16-bit PCM samples,
- * with the left sample preceding the right one. Usually casting soundBuf to/from
- * short* is OK and recommended. The reason for not using a short* in the interface
- * is to avoid implementation-defined behaviour without compromising performance.
+ * There are 35112 audio (stereo) samples in a video frame.
+ * May run for up to 2064 audio samples too long.
+ *
+ * An audio sample consists of two native endian 2s complement 16-bit PCM samples,
+ * with the left sample preceding the right one. Usually casting audioBuf to
+ * int16_t* is OK. The reason for using an uint_least32_t* in the interface is to
+ * avoid implementation-defined behavior without compromising performance.
+ * libgambatte is strictly c++98, so fixed-width types are not an option (and even
+ * c99/c++11 cannot guarantee their availability).
*
* Returns early when a new video frame has finished drawing in the video buffer,
* such that the caller may update the video output before the frame is overwritten.
* The return value indicates whether a new video frame has been drawn, and the
- * exact time (in number of samples) at which it was drawn.
+ * exact time (in number of samples) at which it was completed.
*
- * @param soundBuf buffer with space >= samples + 2064
- * @param samples in: number of stereo samples to produce, out: actual number of samples produced
- * @return sample number at which the video frame was produced. -1 means no frame was produced.
+ * @param videoBuf 160x144 RGB32 (native endian) video frame buffer or 0
+ * @param pitch distance in number of pixels (not bytes) from the start of one line
+ * to the next in videoBuf.
+ * @param audioBuf buffer with space >= samples + 2064
+ * @param samples in: number of stereo samples to produce,
+ * out: actual number of samples produced
+ * @return sample offset in audioBuf at which the video frame was completed, or -1
+ * if no new video frame was completed.
*/
- long runFor(gambatte::uint_least32_t *soundBuf, unsigned &samples);
+ std::ptrdiff_t runFor(gambatte::uint_least32_t *soundBuf, std::size_t &samples);
- void blitTo(gambatte::uint_least32_t *videoBuf, int pitch);
+ void blitTo(gambatte::uint_least32_t *videoBuf, std::ptrdiff_t pitch);
void setLayers(unsigned mask);
- /** Reset to initial state.
+ /**
+ * Reset to initial state.
* Equivalent to reloading a ROM image, or turning a Game Boy Color off and on again.
*/
- void reset(std::uint32_t now, unsigned div);
-
- /** @param palNum 0 <= palNum < 3. One of BG_PALETTE, SP1_PALETTE and SP2_PALETTE.
+ void reset();
+
+ /**
+ * @param palNum 0 <= palNum < 3. One of BG_PALETTE, SP1_PALETTE and SP2_PALETTE.
* @param colorNum 0 <= colorNum < 4
*/
- void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32);
-
+ void setDmgPaletteColor(int palNum, int colorNum, unsigned long rgb32);
+
void setCgbPalette(unsigned *lut);
/** Sets the callback used for getting input state. */
void setInputGetter(unsigned (*getInput)());
-
+
void setReadCallback(MemoryCallback);
void setWriteCallback(MemoryCallback);
void setExecCallback(MemoryCallback);
void setCDCallback(CDCallback);
void setTraceCallback(void (*callback)(void *));
void setScanlineCallback(void (*callback)(), int sl);
- void setRTCCallback(std::uint32_t (*callback)());
void setLinkCallback(void(*callback)());
+ /** Use cycle-based RTC instead of real-time. */
+ void setTimeMode(bool useCycles);
+
+ /** adjust the assumed clock speed of the CPU compared to the RTC */
+ void setRtcDivisorOffset(long const rtcDivisorOffset);
+
/** Returns true if the currently loaded ROM image is treated as having CGB support. */
bool isCgb() const;
-
+
/** Returns true if a ROM image is loaded. */
bool isLoaded() const;
/** Writes persistent cartridge data to disk. NOT Done implicitly on ROM close. */
- void loadSavedata(const char *data);
+ void loadSavedata(char const *data);
int saveSavedataLength();
void saveSavedata(char *dest);
-
+
// 0 = vram, 1 = rom, 2 = wram, 3 = cartram, 4 = oam, 5 = hram
bool getMemoryArea(int which, unsigned char **data, int *length);
-
+
/** ROM header title of currently loaded ROM image. */
- const std::string romTitle() const;
+ std::string const romTitle() const;
- unsigned char ExternalRead(unsigned short addr);
- void ExternalWrite(unsigned short addr, unsigned char val);
+ unsigned char externalRead(unsigned short addr);
+ void externalWrite(unsigned short addr, unsigned char val);
- int LinkStatus(int which);
+ int linkStatus(int which);
- void GetRegs(int *dest);
+ void getRegs(int *dest);
- void SetInterruptAddresses(int *addrs, int numAddrs);
- int GetHitInterruptAddress();
+ void setInterruptAddresses(int *addrs, int numAddrs);
+ int getHitInterruptAddress();
templatevoid SyncState(NewState *ns);
@@ -148,8 +166,8 @@ private:
struct Priv;
Priv *const p_;
- GB(const GB &);
- GB & operator=(const GB &);
+ GB(GB const &);
+ GB & operator=(GB const &);
};
}
diff --git a/libgambatte/include/gbint.h b/libgambatte/include/gbint.h
index 8feb2aac25..272a9e8318 100644
--- a/libgambatte/include/gbint.h
+++ b/libgambatte/include/gbint.h
@@ -1,21 +1,21 @@
-/***************************************************************************
- * Copyright (C) 2007 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2007 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#ifndef GAMBATTE_INT_H
#define GAMBATTE_INT_H
diff --git a/libgambatte/include/loadres.h b/libgambatte/include/loadres.h
new file mode 100644
index 0000000000..6ee5e370b5
--- /dev/null
+++ b/libgambatte/include/loadres.h
@@ -0,0 +1,23 @@
+#ifndef GAMBATTE_LOADRES_H
+#define GAMBATTE_LOADRES_H
+
+#include
+
+namespace gambatte {
+
+enum LoadRes {
+ LOADRES_BAD_FILE_OR_UNKNOWN_MBC = -0x7FFF,
+ LOADRES_IO_ERROR,
+ LOADRES_UNSUPPORTED_MBC_HUC3 = -0x1FE,
+ LOADRES_UNSUPPORTED_MBC_TAMA5,
+ LOADRES_UNSUPPORTED_MBC_POCKET_CAMERA,
+ LOADRES_UNSUPPORTED_MBC_MBC7 = -0x122,
+ LOADRES_UNSUPPORTED_MBC_MBC6 = -0x120,
+ LOADRES_UNSUPPORTED_MBC_MBC4 = -0x117,
+ LOADRES_UNSUPPORTED_MBC_MMM01 = -0x10D,
+ LOADRES_OK = 0
+};
+
+}
+
+#endif
diff --git a/libgambatte/libgambatte.vcxproj b/libgambatte/libgambatte.vcxproj
index 3d744a9a8c..37d3a96a03 100644
--- a/libgambatte/libgambatte.vcxproj
+++ b/libgambatte/libgambatte.vcxproj
@@ -22,7 +22,7 @@
{5D630682-7BDA-474D-B387-0EB420DDC199}
Win32Proj
libgambatte
- 10.0.17763.0
+ 8.1
@@ -156,20 +156,18 @@
+
-
-
-
-
+
@@ -188,6 +186,7 @@
+
@@ -197,12 +196,12 @@
-
+
diff --git a/libgambatte/libgambatte.vcxproj.filters b/libgambatte/libgambatte.vcxproj.filters
index 614dad17ef..b34a8d79f1 100644
--- a/libgambatte/libgambatte.vcxproj.filters
+++ b/libgambatte/libgambatte.vcxproj.filters
@@ -15,46 +15,58 @@
-
- Header Files
-
Header Files
-
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
Header Files
Header Files
-
- Header Files
-
-
- Header Files
-
Header Files
Header Files
-
+
Header Files
-
+
+ Header Files
+
+
+ Header Files
+
+
Header Files
Header Files
-
- Header Files
-
-
- Header Files
-
-
+
Header Files
@@ -69,39 +81,12 @@
Header Files
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
Header Files
Header Files
-
- Header Files
-
Header Files
@@ -111,60 +96,69 @@
Header Files
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
Header Files
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
Source Files
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
Source Files
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
+
Source Files
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
Source Files
-
+
Source Files
-
+
+ Source Files
+
+
Source Files
@@ -185,25 +179,28 @@
Source Files
-
- Source Files
-
Source Files
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
Source Files
-
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
Source Files
diff --git a/libgambatte/src/cinterface.cpp b/libgambatte/src/cinterface.cpp
index ad8247f17c..f9b4ced4fb 100644
--- a/libgambatte/src/cinterface.cpp
+++ b/libgambatte/src/cinterface.cpp
@@ -1,225 +1,205 @@
+//
+// Copyright (C) 2007 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#include "cinterface.h"
#include "gambatte.h"
#include
#include
#include "newstate.h"
-using namespace gambatte;
-
// new is actually called in a few different places, so replace all of them for determinism guarantees
-void *operator new(std::size_t n)
-{
+void *operator new(std::size_t n) {
void *p = std::malloc(n);
std::memset(p, 0, n);
return p;
}
-void operator delete(void *p)
-{
+void operator delete(void *p) {
std::free(p);
}
-GBEXPORT GB *gambatte_create()
-{
+namespace {
+
+using namespace gambatte;
+
+ GBEXPORT GB * gambatte_create() {
return new GB();
}
-GBEXPORT void gambatte_destroy(GB *g)
-{
+GBEXPORT void gambatte_destroy(GB *g) {
delete g;
}
-GBEXPORT int gambatte_load(GB *g, const char *romfiledata, unsigned romfilelength, long long now, unsigned flags, unsigned div)
-{
- int ret = g->load(romfiledata, romfilelength, now, flags, div);
- return ret;
+GBEXPORT int gambatte_load(GB *g, char const *romfiledata, unsigned romfilelength, unsigned flags) {
+ return g->load(romfiledata, romfilelength, flags);
}
-GBEXPORT int gambatte_loadgbcbios(GB* g, const char* biosfiledata)
-{
- int ret = g->loadGBCBios(biosfiledata);
- return ret;
+GBEXPORT int gambatte_loadbios(GB *g, char const *biosfiledata, unsigned size) {
+ return g->loadBios(biosfiledata, size);
}
-GBEXPORT int gambatte_loaddmgbios(GB* g, const char* biosfiledata)
-{
- int ret = g->loadDMGBios(biosfiledata);
- return ret;
-}
-
-GBEXPORT int gambatte_runfor(GB *g, short *soundbuf, unsigned *samples)
-{
- unsigned sampv = *samples;
+GBEXPORT int gambatte_runfor(GB *g, short *soundbuf, unsigned *samples) {
+ std::size_t sampv = *samples;
int ret = g->runFor((unsigned int *) soundbuf, sampv);
*samples = sampv;
return ret;
}
-GBEXPORT void gambatte_blitto(GB *g, unsigned int *videobuf, int pitch)
-{
+GBEXPORT void gambatte_blitto(GB *g, unsigned int *videobuf, int pitch) {
g->blitTo((unsigned int *)videobuf, pitch);
}
-GBEXPORT void gambatte_setlayers(GB *g, unsigned mask)
-{
+GBEXPORT void gambatte_setlayers(GB *g, unsigned mask) {
g->setLayers(mask);
}
-GBEXPORT void gambatte_reset(GB *g, long long now, unsigned div)
-{
- g->reset(now, div);
+GBEXPORT void gambatte_settimemode(GB *g, bool useCycles) {
+ g->setTimeMode(useCycles);
}
-GBEXPORT void gambatte_setdmgpalettecolor(GB *g, unsigned palnum, unsigned colornum, unsigned rgb32)
-{
+GBEXPORT void gambatte_setrtcdivisoroffset(GB *g, int rtcDivisorOffset) {
+ g->setRtcDivisorOffset(rtcDivisorOffset);
+}
+
+GBEXPORT void gambatte_reset(GB *g) {
+ g->reset();
+}
+
+GBEXPORT void gambatte_setdmgpalettecolor(GB *g, unsigned palnum, unsigned colornum, unsigned rgb32) {
g->setDmgPaletteColor(palnum, colornum, rgb32);
}
-GBEXPORT void gambatte_setcgbpalette(GB *g, unsigned *lut)
-{
+GBEXPORT void gambatte_setcgbpalette(GB *g, unsigned *lut) {
g->setCgbPalette(lut);
}
-GBEXPORT void gambatte_setinputgetter(GB *g, unsigned (*getinput)(void))
-{
+GBEXPORT void gambatte_setinputgetter(GB *g, unsigned (*getinput)(void)) {
g->setInputGetter(getinput);
}
-GBEXPORT void gambatte_setreadcallback(GB *g, MemoryCallback callback)
-{
+GBEXPORT void gambatte_setreadcallback(GB *g, MemoryCallback callback) {
g->setReadCallback(callback);
}
-GBEXPORT void gambatte_setwritecallback(GB *g, MemoryCallback callback)
-{
+GBEXPORT void gambatte_setwritecallback(GB *g, MemoryCallback callback) {
g->setWriteCallback(callback);
}
-GBEXPORT void gambatte_setexeccallback(GB *g, MemoryCallback callback)
-{
+GBEXPORT void gambatte_setexeccallback(GB *g, MemoryCallback callback) {
g->setExecCallback(callback);
}
-GBEXPORT void gambatte_setcdcallback(GB *g, CDCallback cdc)
-{
+GBEXPORT void gambatte_setcdcallback(GB *g, CDCallback cdc) {
g->setCDCallback(cdc);
}
-GBEXPORT void gambatte_settracecallback(GB *g, void (*callback)(void *))
-{
+GBEXPORT void gambatte_settracecallback(GB *g, void (*callback)(void *)) {
g->setTraceCallback(callback);
}
-GBEXPORT void gambatte_setscanlinecallback(GB *g, void (*callback)(), int sl)
-{
+GBEXPORT void gambatte_setscanlinecallback(GB *g, void (*callback)(), int sl) {
g->setScanlineCallback(callback, sl);
}
-GBEXPORT void gambatte_setrtccallback(GB *g, unsigned int (*callback)())
-{
- g->setRTCCallback(callback);
-}
-
-GBEXPORT void gambatte_setlinkcallback(GB *g, void(*callback)())
-{
+GBEXPORT void gambatte_setlinkcallback(GB *g, void(*callback)()) {
g->setLinkCallback(callback);
}
-GBEXPORT int gambatte_iscgb(GB *g)
-{
+GBEXPORT int gambatte_iscgb(GB *g) {
return g->isCgb();
}
-GBEXPORT int gambatte_isloaded(GB *g)
-{
+GBEXPORT int gambatte_isloaded(GB *g) {
return g->isLoaded();
}
-GBEXPORT void gambatte_savesavedata(GB *g, char *dest)
-{
+GBEXPORT void gambatte_savesavedata(GB *g, char *dest) {
g->saveSavedata(dest);
}
-GBEXPORT void gambatte_loadsavedata(GB *g, const char *data)
-{
+GBEXPORT void gambatte_loadsavedata(GB *g, char const *data) {
g->loadSavedata(data);
}
-GBEXPORT int gambatte_savesavedatalength(GB *g)
-{
+GBEXPORT int gambatte_savesavedatalength(GB *g) {
return g->saveSavedataLength();
}
-GBEXPORT int gambatte_newstatelen(GB *g)
-{
+GBEXPORT int gambatte_newstatelen(GB *g) {
NewStateDummy dummy;
g->SyncState(&dummy);
return dummy.GetLength();
}
-GBEXPORT int gambatte_newstatesave(GB *g, char *data, int len)
-{
+GBEXPORT int gambatte_newstatesave(GB *g, char *data, int len) {
NewStateExternalBuffer saver(data, len);
g->SyncState(&saver);
return !saver.Overflow() && saver.GetLength() == len;
}
-GBEXPORT int gambatte_newstateload(GB *g, const char *data, int len)
-{
+GBEXPORT int gambatte_newstateload(GB *g, char const *data, int len) {
NewStateExternalBuffer loader((char *)data, len);
g->SyncState(&loader);
return !loader.Overflow() && loader.GetLength() == len;
}
-GBEXPORT void gambatte_newstatesave_ex(GB *g, FPtrs *ff)
-{
+GBEXPORT void gambatte_newstatesave_ex(GB *g, FPtrs *ff) {
NewStateExternalFunctions saver(ff);
g->SyncState(&saver);
}
-GBEXPORT void gambatte_newstateload_ex(GB *g, FPtrs *ff)
-{
+GBEXPORT void gambatte_newstateload_ex(GB *g, FPtrs *ff) {
NewStateExternalFunctions loader(ff);
g->SyncState(&loader);
}
-GBEXPORT void gambatte_romtitle(GB *g, char *dest)
-{
+GBEXPORT void gambatte_romtitle(GB *g, char *dest) {
std::strcpy(dest, g->romTitle().c_str());
}
-GBEXPORT int gambatte_getmemoryarea(GB *g, int which, unsigned char **data, int *length)
-{
+GBEXPORT int gambatte_getmemoryarea(GB *g, int which, unsigned char **data, int *length) {
return g->getMemoryArea(which, data, length);
}
-GBEXPORT unsigned char gambatte_cpuread(GB *g, unsigned short addr)
-{
- return g->ExternalRead(addr);
+GBEXPORT unsigned char gambatte_cpuread(GB *g, unsigned short addr) {
+ return g->externalRead(addr);
}
-GBEXPORT void gambatte_cpuwrite(GB *g, unsigned short addr, unsigned char val)
-{
- g->ExternalWrite(addr, val);
+GBEXPORT void gambatte_cpuwrite(GB *g, unsigned short addr, unsigned char val) {
+ g->externalWrite(addr, val);
}
GBEXPORT int gambatte_linkstatus(GB *g, int which)
{
- return g->LinkStatus(which);
+ return g->linkStatus(which);
}
-GBEXPORT void gambatte_getregs(GB *g, int *dest)
-{
- g->GetRegs(dest);
+GBEXPORT void gambatte_getregs(GB *g, int *dest) {
+ g->getRegs(dest);
}
-GBEXPORT void gambatte_setinterruptaddresses(GB *g, int *addrs, int numAddrs)
-{
- g->SetInterruptAddresses(addrs, numAddrs);
+GBEXPORT void gambatte_setinterruptaddresses(GB *g, int *addrs, int numAddrs) {
+ g->setInterruptAddresses(addrs, numAddrs);
+}
+
+GBEXPORT int gambatte_gethitinterruptaddress(GB *g) {
+ return g->getHitInterruptAddress();
}
-GBEXPORT int gambatte_gethitinterruptaddress(GB *g)
-{
- return g->GetHitInterruptAddress();
}
diff --git a/libgambatte/src/cinterface.h b/libgambatte/src/cinterface.h
index 5e8a0087ec..031392a097 100644
--- a/libgambatte/src/cinterface.h
+++ b/libgambatte/src/cinterface.h
@@ -1,3 +1,21 @@
+//
+// Copyright (C) 2007 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#ifndef CINTERFACE_H
#define CINTERFACE_H
diff --git a/libgambatte/src/common/array.h b/libgambatte/src/common/array.h
deleted file mode 100644
index c650390d4e..0000000000
--- a/libgambatte/src/common/array.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-#ifndef ARRAY_H
-#define ARRAY_H
-
-#include
-#include "uncopyable.h"
-
-template
-class Array : Uncopyable {
- T *a;
- std::size_t sz;
-
-public:
- explicit Array(const std::size_t size = 0) : a(size ? new T[size] : 0), sz(size) {}
- ~Array() { delete []a; }
- void reset(const std::size_t size = 0) { delete []a; a = size ? new T[size] : 0; sz = size; }
- std::size_t size() const { return sz; }
- T * get() const { return a; }
- operator T*() const { return a; }
-};
-
-template
-class ScopedArray : Uncopyable {
- T *a_;
-
-public:
- explicit ScopedArray(T *a = 0) : a_(a) {}
- ~ScopedArray() { delete []a_; }
- void reset(T *a = 0) { delete []a_; a_ = a; }
- T * release() { T *a = a_; a_ = 0; return a; }
- T * get() const { return a_; }
- operator T*() const { return a_; }
-};
-
-#endif
diff --git a/libgambatte/src/common/uncopyable.h b/libgambatte/src/common/uncopyable.h
deleted file mode 100644
index 71d77fef33..0000000000
--- a/libgambatte/src/common/uncopyable.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-#ifndef UNCOPYABLE_H
-#define UNCOPYABLE_H
-
-class Uncopyable {
- Uncopyable(const Uncopyable&);
- Uncopyable& operator=(const Uncopyable&);
-public:
- Uncopyable() {}
-};
-
-#endif
diff --git a/libgambatte/src/counterdef.h b/libgambatte/src/counterdef.h
index 9d19f44815..c48b80cdfa 100644
--- a/libgambatte/src/counterdef.h
+++ b/libgambatte/src/counterdef.h
@@ -2,7 +2,9 @@
#define COUNTERDEF_H
namespace gambatte {
-enum { DISABLED_TIME = 0xFFFFFFFFul };
+
+enum { disabled_time = 0xfffffffful };
+
}
#endif
diff --git a/libgambatte/src/cpu.cpp b/libgambatte/src/cpu.cpp
index 8ea6714cb3..d086c9842f 100644
--- a/libgambatte/src/cpu.cpp
+++ b/libgambatte/src/cpu.cpp
@@ -1,21 +1,21 @@
-/***************************************************************************
- * Copyright (C) 2007 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2007 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#include "cpu.h"
#include "memory.h"
#include "savestate.h"
@@ -23,229 +23,229 @@
namespace gambatte {
CPU::CPU()
-: memory(Interrupter(SP, PC), SP, PC),
- cycleCounter_(0),
- PC(0x100),
- SP(0xFFFE),
- HF1(0xF),
- HF2(0xF),
- ZF(0),
- CF(0x100),
- A(0x01),
- B(0x00),
- C(0x13),
- D(0x00),
- E(0xD8),
- H(0x01),
- L(0x4D),
- skip(false),
- numInterruptAddresses(),
- tracecallback(0)
+: mem_(sp, pc)
+, cycleCounter_(0)
+, pc(0x100)
+, sp(0xFFFE)
+, hf1(0xF)
+, hf2(0xF)
+, zf(0)
+, cf(0x100)
+, a(0x01)
+, b(0x00)
+, c(0x13)
+, d(0x00)
+, e(0xD8)
+, h(0x01)
+, l(0x4D)
+, skip_(false)
+, numInterruptAddresses()
+, tracecallback(0)
{
}
-long CPU::runFor(const unsigned long cycles) {
- memory.setBasetime(cycleCounter_);
- process(cycles/* << memory.isDoubleSpeed()*/);
-
- const long csb = memory.cyclesSinceBlit(cycleCounter_);
-
+long CPU::runFor(unsigned long const cycles) {
+ mem_.setBasetime(cycleCounter_);
+ process(cycles);
+
+ long const csb = mem_.cyclesSinceBlit(cycleCounter_);
+
if (cycleCounter_ & 0x80000000)
- cycleCounter_ = memory.resetCounters(cycleCounter_);
-
+ cycleCounter_ = mem_.resetCounters(cycleCounter_);
+
return csb;
}
-// (HF2 & 0x200) == true means HF is set.
-// (HF2 & 0x400) marks the subtract flag.
-// (HF2 & 0x800) is set for inc/dec.
-// (HF2 & 0x100) is set if there's a carry to add.
-static void calcHF(const unsigned HF1, unsigned& HF2) {
- unsigned arg1 = HF1 & 0xF;
- unsigned arg2 = (HF2 & 0xF) + (HF2 >> 8 & 1);
-
- if (HF2 & 0x800) {
- arg1 = arg2;
- arg2 = 1;
+enum { hf2_hcf = 0x200, hf2_subf = 0x400, hf2_incf = 0x800 };
+
+static unsigned updateHf2FromHf1(unsigned const hf1, unsigned hf2) {
+ unsigned lhs = hf1 & 0xF;
+ unsigned rhs = (hf2 & 0xF) + (hf2 >> 8 & 1);
+ if (hf2 & hf2_incf) {
+ lhs = rhs;
+ rhs = 1;
}
- if (HF2 & 0x400)
- arg1 -= arg2;
- else
- arg1 = (arg1 + arg2) << 5;
-
- HF2 |= arg1 & 0x200;
+ unsigned res = hf2 & hf2_subf
+ ? lhs - rhs
+ : (lhs + rhs) << 5;
+
+ hf2 |= res & hf2_hcf;
+ return hf2;
}
-#define F() (((HF2 & 0x600) | (CF & 0x100)) >> 4 | ((ZF & 0xFF) ? 0 : 0x80))
+static inline unsigned toF(unsigned hf2, unsigned cf, unsigned zf) {
+ return ((hf2 & (hf2_subf | hf2_hcf)) | (cf & 0x100)) >> 4
+ | (zf & 0xFF ? 0 : 0x80);
+}
-#define FROM_F(f_in) do { \
- unsigned from_f_var = f_in; \
-\
- ZF = ~from_f_var & 0x80; \
- HF2 = from_f_var << 4 & 0x600; \
- CF = from_f_var << 4 & 0x100; \
-} while (0)
+static inline unsigned zfFromF(unsigned f) { return ~f & 0x80; }
+static inline unsigned hf2FromF(unsigned f) { return f << 4 & (hf2_subf | hf2_hcf); }
+static inline unsigned cfFromF(unsigned f) { return f << 4 & 0x100; }
void CPU::setStatePtrs(SaveState &state) {
- memory.setStatePtrs(state);
+ mem_.setStatePtrs(state);
}
-void CPU::loadState(const SaveState &state) {
- memory.loadState(state/*, cycleCounter_*/);
-
+void CPU::loadState(SaveState const &state) {
+ mem_.loadState(state);
+
cycleCounter_ = state.cpu.cycleCounter;
- PC = state.cpu.PC & 0xFFFF;
- SP = state.cpu.SP & 0xFFFF;
- A = state.cpu.A & 0xFF;
- B = state.cpu.B & 0xFF;
- C = state.cpu.C & 0xFF;
- D = state.cpu.D & 0xFF;
- E = state.cpu.E & 0xFF;
- FROM_F(state.cpu.F);
- H = state.cpu.H & 0xFF;
- L = state.cpu.L & 0xFF;
- skip = state.cpu.skip;
+ pc = state.cpu.pc & 0xFFFF;
+ sp = state.cpu.sp & 0xFFFF;
+ a = state.cpu.a & 0xFF;
+ b = state.cpu.b & 0xFF;
+ c = state.cpu.c & 0xFF;
+ d = state.cpu.d & 0xFF;
+ e = state.cpu.e & 0xFF;
+ zf = zfFromF(state.cpu.f);
+ hf2 = hf2FromF(state.cpu.f);
+ cf = cfFromF(state.cpu.f);
+ h = state.cpu.h & 0xFF;
+ l = state.cpu.l & 0xFF;
+ skip_ = state.cpu.skip;
}
-#define BC() ( B << 8 | C )
-#define DE() ( D << 8 | E )
-#define HL() ( H << 8 | L )
+// The main reasons for the use of macros is to more conveniently be able to tweak
+// which variables are local and which are not, combined with the fact that at the
+// time they were written GCC had a tendency to not be able to keep hot variables
+// in regs if you took an address/reference in an inline function.
-#define READ(dest, addr) do { (dest) = memory.read(addr, cycleCounter); cycleCounter += 4; } while (0)
-#define PEEK(dest, addr) do { (dest) = memory.read(addr, cycleCounter); } while(0)
-// #define PC_READ(dest, addr) do { (dest) = memory.pc_read(addr, cycleCounter); cycleCounter += 4; } while (0)
-#define PC_READ(dest) do { (dest) = memory.read_excb(PC, cycleCounter, false); PC = (PC + 1) & 0xFFFF; cycleCounter += 4; } while (0)
-#define PC_READ_FIRST(dest) do { (dest) = memory.read_excb(PC, cycleCounter, true); PC = (PC + 1) & 0xFFFF; cycleCounter += 4; } while (0)
-#define FF_READ(dest, addr) do { (dest) = memory.ff_read(addr, cycleCounter); cycleCounter += 4; } while (0)
+#define bc() ( b << 8 | c )
+#define de() ( d << 8 | e )
+#define hl() ( h << 8 | l )
-#define WRITE(addr, data) do { memory.write(addr, data, cycleCounter); cycleCounter += 4; } while (0)
-#define FF_WRITE(addr, data) do { memory.ff_write(addr, data, cycleCounter); cycleCounter += 4; } while (0)
+#define READ(dest, addr) do { (dest) = mem_.read(addr, cycleCounter); cycleCounter += 4; } while (0)
+#define PEEK(dest, addr) do { (dest) = mem_.read(addr, cycleCounter); } while (0)
+#define PC_READ(dest) do { (dest) = mem_.read_excb(pc, cycleCounter, false); pc = (pc + 1) & 0xFFFF; cycleCounter += 4; } while (0)
+#define PC_READ_FIRST(dest) do { (dest) = mem_.read_excb(pc, cycleCounter, true); pc = (pc + 1) & 0xFFFF; cycleCounter += 4; } while (0)
+#define FF_READ(dest, addr) do { (dest) = mem_.ff_read(addr, cycleCounter); cycleCounter += 4; } while (0)
-#define PC_MOD(data) do { PC = data; cycleCounter += 4; } while (0)
+#define WRITE(addr, data) do { mem_.write(addr, data, cycleCounter); cycleCounter += 4; } while (0)
+#define FF_WRITE(addr, data) do { mem_.ff_write(addr, data, cycleCounter); cycleCounter += 4; } while (0)
+
+#define PC_MOD(data) do { pc = data; cycleCounter += 4; } while (0)
#define PUSH(r1, r2) do { \
- SP = (SP - 1) & 0xFFFF; \
- WRITE(SP, (r1)); \
- SP = (SP - 1) & 0xFFFF; \
- WRITE(SP, (r2)); \
+ sp = (sp - 1) & 0xFFFF; \
+ WRITE(sp, (r1)); \
+ sp = (sp - 1) & 0xFFFF; \
+ WRITE(sp, (r2)); \
} while (0)
-//CB OPCODES (Shifts, rotates and bits):
-//swap r (8 cycles):
-//Swap upper and lower nibbles of 8-bit register, reset flags, check zero flag:
+// CB OPCODES (Shifts, rotates and bits):
+// swap r (8 cycles):
+// Swap upper and lower nibbles of 8-bit register, reset flags, check zero flag:
#define swap_r(r) do { \
- CF = HF2 = 0; \
- ZF = (r); \
- (r) = (ZF << 4 | ZF >> 4) & 0xFF; \
+ cf = hf2 = 0; \
+ zf = (r); \
+ (r) = (zf << 4 | zf >> 4) & 0xFF; \
} while (0)
-//rlc r (8 cycles):
-//Rotate 8-bit register left, store old bit7 in CF. Reset SF and HCF, Check ZF:
+// rlc r (8 cycles):
+// Rotate 8-bit register left, store old bit7 in CF. Reset SF and HCF, Check ZF:
#define rlc_r(r) do { \
- CF = (r) << 1; \
- ZF = CF | CF >> 8; \
- (r) = ZF & 0xFF; \
- HF2 = 0; \
+ cf = (r) << 1; \
+ zf = cf | cf >> 8; \
+ (r) = zf & 0xFF; \
+ hf2 = 0; \
} while (0)
-//rl r (8 cycles):
-//Rotate 8-bit register left through CF, store old bit7 in CF, old CF value becomes bit0. Reset SF and HCF, Check ZF:
+// rl r (8 cycles):
+// Rotate 8-bit register left through CF, store old bit7 in CF, old CF value becomes bit0. Reset SF and HCF, Check ZF:
#define rl_r(r) do { \
- const unsigned rl_r_var_oldcf = CF >> 8 & 1; \
- CF = (r) << 1; \
- ZF = CF | rl_r_var_oldcf; \
- (r) = ZF & 0xFF; \
- HF2 = 0; \
+ unsigned const oldcf = cf >> 8 & 1; \
+ cf = (r) << 1; \
+ zf = cf | oldcf; \
+ (r) = zf & 0xFF; \
+ hf2 = 0; \
} while (0)
-//rrc r (8 cycles):
-//Rotate 8-bit register right, store old bit0 in CF. Reset SF and HCF, Check ZF:
+// rrc r (8 cycles):
+// Rotate 8-bit register right, store old bit0 in CF. Reset SF and HCF, Check ZF:
#define rrc_r(r) do { \
- ZF = (r); \
- CF = ZF << 8; \
- (r) = (ZF | CF) >> 1 & 0xFF; \
- HF2 = 0; \
+ zf = (r); \
+ cf = zf << 8; \
+ (r) = (zf | cf) >> 1 & 0xFF; \
+ hf2 = 0; \
} while (0)
-//rr r (8 cycles):
-//Rotate 8-bit register right through CF, store old bit0 in CF, old CF value becomes bit7. Reset SF and HCF, Check ZF:
+// rr r (8 cycles):
+// Rotate 8-bit register right through CF, store old bit0 in CF, old CF value becomes bit7. Reset SF and HCF, Check ZF:
#define rr_r(r) do { \
- const unsigned rr_r_var_oldcf = CF & 0x100; \
- CF = (r) << 8; \
- (r) = ZF = ((r) | rr_r_var_oldcf) >> 1; \
- HF2 = 0; \
+ unsigned const oldcf = cf & 0x100; \
+ cf = (r) << 8; \
+ (r) = zf = ((r) | oldcf) >> 1; \
+ hf2 = 0; \
} while (0)
-//sla r (8 cycles):
-//Shift 8-bit register left, store old bit7 in CF. Reset SF and HCF, Check ZF:
+// sla r (8 cycles):
+// Shift 8-bit register left, store old bit7 in CF. Reset SF and HCF, Check ZF:
#define sla_r(r) do { \
- ZF = CF = (r) << 1; \
- (r) = ZF & 0xFF; \
- HF2 = 0; \
+ zf = cf = (r) << 1; \
+ (r) = zf & 0xFF; \
+ hf2 = 0; \
} while (0)
-//sra r (8 cycles):
-//Shift 8-bit register right, store old bit0 in CF. bit7=old bit7. Reset SF and HCF, Check ZF:
+// sra r (8 cycles):
+// Shift 8-bit register right, store old bit0 in CF. bit7=old bit7. Reset SF and HCF, Check ZF:
#define sra_r(r) do { \
- CF = (r) << 8; \
- ZF = (r) >> 1; \
- (r) = ZF | ((r) & 0x80); \
- HF2 = 0; \
+ cf = (r) << 8; \
+ zf = (r) >> 1; \
+ (r) = zf | ((r) & 0x80); \
+ hf2 = 0; \
} while (0)
-//srl r (8 cycles):
-//Shift 8-bit register right, store old bit0 in CF. Reset SF and HCF, Check ZF:
+// srl r (8 cycles):
+// Shift 8-bit register right, store old bit0 in CF. Reset SF and HCF, Check ZF:
#define srl_r(r) do { \
- ZF = (r); \
- CF = (r) << 8; \
- ZF >>= 1; \
- (r) = ZF; \
- HF2 = 0; \
+ zf = (r); \
+ cf = (r) << 8; \
+ zf >>= 1; \
+ (r) = zf; \
+ hf2 = 0; \
} while (0)
-//bit n,r (8 cycles):
-//bit n,(hl) (12 cycles):
-//Test bitn in 8-bit value, check ZF, unset SF, set HCF:
+// bit n,r (8 cycles):
+// bit n,(hl) (12 cycles):
+// Test bitn in 8-bit value, check ZF, unset SF, set HCF:
#define bitn_u8(bitmask, u8) do { \
- ZF = (u8) & (bitmask); \
- HF2 = 0x200; \
+ zf = (u8) & (bitmask); \
+ hf2 = hf2_hcf; \
} while (0)
-#define bit0_u8(u8) bitn_u8(1, (u8))
-#define bit1_u8(u8) bitn_u8(2, (u8))
-#define bit2_u8(u8) bitn_u8(4, (u8))
-#define bit3_u8(u8) bitn_u8(8, (u8))
+#define bit0_u8(u8) bitn_u8(0x01, (u8))
+#define bit1_u8(u8) bitn_u8(0x02, (u8))
+#define bit2_u8(u8) bitn_u8(0x04, (u8))
+#define bit3_u8(u8) bitn_u8(0x08, (u8))
#define bit4_u8(u8) bitn_u8(0x10, (u8))
#define bit5_u8(u8) bitn_u8(0x20, (u8))
#define bit6_u8(u8) bitn_u8(0x40, (u8))
#define bit7_u8(u8) bitn_u8(0x80, (u8))
-//set n,r (8 cycles):
-//Set bitn of 8-bit register:
-#define set0_r(r) ( (r) |= 0x1 )
-#define set1_r(r) ( (r) |= 0x2 )
-#define set2_r(r) ( (r) |= 0x4 )
-#define set3_r(r) ( (r) |= 0x8 )
+// set n,r (8 cycles):
+// Set bitn of 8-bit register:
+#define set0_r(r) ( (r) |= 0x01 )
+#define set1_r(r) ( (r) |= 0x02 )
+#define set2_r(r) ( (r) |= 0x04 )
+#define set3_r(r) ( (r) |= 0x08 )
#define set4_r(r) ( (r) |= 0x10 )
#define set5_r(r) ( (r) |= 0x20 )
#define set6_r(r) ( (r) |= 0x40 )
#define set7_r(r) ( (r) |= 0x80 )
-//set n,(hl) (16 cycles):
-//Set bitn of value at address stored in HL:
+// set n,(hl) (16 cycles):
+// Set bitn of value at address stored in HL:
#define setn_mem_hl(n) do { \
- const unsigned setn_mem_hl_var_addr = HL(); \
- unsigned setn_mem_hl_var_tmp; \
-\
- READ(setn_mem_hl_var_tmp, setn_mem_hl_var_addr); \
- setn_mem_hl_var_tmp |= 1 << (n); \
-\
- WRITE(setn_mem_hl_var_addr, setn_mem_hl_var_tmp); \
+ unsigned const hl = hl(); \
+ unsigned val; \
+ READ(val, hl); \
+ val |= 1 << (n); \
+ WRITE(hl, val); \
} while (0)
-//res n,r (8 cycles):
-//Unset bitn of 8-bit register:
+// res n,r (8 cycles):
+// Unset bitn of 8-bit register:
#define res0_r(r) ( (r) &= 0xFE )
#define res1_r(r) ( (r) &= 0xFD )
#define res2_r(r) ( (r) &= 0xFB )
@@ -255,2656 +255,1854 @@ void CPU::loadState(const SaveState &state) {
#define res6_r(r) ( (r) &= 0xBF )
#define res7_r(r) ( (r) &= 0x7F )
-//res n,(hl) (16 cycles):
-//Unset bitn of value at address stored in HL:
+// res n,(hl) (16 cycles):
+// Unset bitn of value at address stored in HL:
#define resn_mem_hl(n) do { \
- const unsigned resn_mem_hl_var_addr = HL(); \
- unsigned resn_mem_hl_var_tmp; \
-\
- READ(resn_mem_hl_var_tmp, resn_mem_hl_var_addr); \
- resn_mem_hl_var_tmp &= ~(1 << (n)); \
-\
- WRITE(resn_mem_hl_var_addr, resn_mem_hl_var_tmp); \
+ unsigned const hl = hl(); \
+ unsigned val; \
+ READ(val, hl); \
+ val &= ~(1 << (n)); \
+ WRITE(hl, val); \
} while (0)
-//16-BIT LOADS:
-//ld rr,nn (12 cycles)
-//set rr to 16-bit value of next 2 bytes in memory
+// 16-BIT LOADS:
+// ld rr,nn (12 cycles)
+// set rr to 16-bit value of next 2 bytes in memory
#define ld_rr_nn(r1, r2) do { \
PC_READ(r2); \
PC_READ(r1); \
} while (0)
-//push rr (16 cycles):
-//Push value of register pair onto stack:
+// push rr (16 cycles):
+// Push value of register pair onto stack:
#define push_rr(r1, r2) do { \
+ cycleCounter += 4; \
PUSH(r1, r2); \
- cycleCounter += 4; \
} while (0)
-//pop rr (12 cycles):
-//Pop two bytes off stack into register pair:
+// pop rr (12 cycles):
+// Pop two bytes off stack into register pair:
#define pop_rr(r1, r2) do { \
- READ(r2, SP); \
- SP = (SP + 1) & 0xFFFF; \
- READ(r1, SP); \
- SP = (SP + 1) & 0xFFFF; \
+ READ(r2, sp); \
+ sp = (sp + 1) & 0xFFFF; \
+ READ(r1, sp); \
+ sp = (sp + 1) & 0xFFFF; \
} while (0)
-//8-BIT ALU:
-//add a,r (4 cycles):
-//add a,(addr) (8 cycles):
-//Add 8-bit value to A, check flags:
+// 8-BIT ALU:
+// add a,r (4 cycles):
+// add a,(addr) (8 cycles):
+// Add 8-bit value to A, check flags:
#define add_a_u8(u8) do { \
- HF1 = A; \
- HF2 = u8; \
- ZF = CF = A + HF2; \
- A = ZF & 0xFF; \
+ hf1 = a; \
+ hf2 = u8; \
+ zf = cf = a + hf2; \
+ a = zf & 0xFF; \
} while (0)
-//adc a,r (4 cycles):
-//adc a,(addr) (8 cycles):
-//Add 8-bit value+CF to A, check flags:
+// adc a,r (4 cycles):
+// adc a,(addr) (8 cycles):
+// Add 8-bit value+CF to A, check flags:
#define adc_a_u8(u8) do { \
- HF1 = A; \
- HF2 = (CF & 0x100) | (u8); \
- ZF = CF = (CF >> 8 & 1) + (u8) + A; \
- A = ZF & 0xFF; \
+ hf1 = a; \
+ hf2 = (cf & 0x100) | (u8); \
+ zf = cf = (cf >> 8 & 1) + (u8) + a; \
+ a = zf & 0xFF; \
} while (0)
-//sub a,r (4 cycles):
-//sub a,(addr) (8 cycles):
-//Subtract 8-bit value from A, check flags:
+// sub a,r (4 cycles):
+// sub a,(addr) (8 cycles):
+// Subtract 8-bit value from A, check flags:
#define sub_a_u8(u8) do { \
- HF1 = A; \
- HF2 = u8; \
- ZF = CF = A - HF2; \
- A = ZF & 0xFF; \
- HF2 |= 0x400; \
+ hf1 = a; \
+ hf2 = u8; \
+ zf = cf = a - hf2; \
+ a = zf & 0xFF; \
+ hf2 |= hf2_subf; \
} while (0)
-//sbc a,r (4 cycles):
-//sbc a,(addr) (8 cycles):
-//Subtract CF and 8-bit value from A, check flags:
+// sbc a,r (4 cycles):
+// sbc a,(addr) (8 cycles):
+// Subtract CF and 8-bit value from A, check flags:
#define sbc_a_u8(u8) do { \
- HF1 = A; \
- HF2 = 0x400 | (CF & 0x100) | (u8); \
- ZF = CF = A - ((CF >> 8) & 1) - (u8); \
- A = ZF & 0xFF; \
+ hf1 = a; \
+ hf2 = hf2_subf | (cf & 0x100) | (u8); \
+ zf = cf = a - ((cf >> 8) & 1) - (u8); \
+ a = zf & 0xFF; \
} while (0)
-//and a,r (4 cycles):
-//and a,(addr) (8 cycles):
-//bitwise and 8-bit value into A, check flags:
+// and a,r (4 cycles):
+// and a,(addr) (8 cycles):
+// bitwise and 8-bit value into A, check flags:
#define and_a_u8(u8) do { \
- HF2 = 0x200; \
- CF = 0; \
- A &= (u8); \
- ZF = A; \
+ hf2 = hf2_hcf; \
+ cf = 0; \
+ a &= (u8); \
+ zf = a; \
} while (0)
-//or a,r (4 cycles):
-//or a,(hl) (8 cycles):
-//bitwise or 8-bit value into A, check flags:
+// or a,r (4 cycles):
+// or a,(hl) (8 cycles):
+// bitwise or 8-bit value into A, check flags:
#define or_a_u8(u8) do { \
- CF = HF2 = 0; \
- A |= (u8); \
- ZF = A; \
+ cf = hf2 = 0; \
+ a |= (u8); \
+ zf = a; \
} while (0)
-//xor a,r (4 cycles):
-//xor a,(hl) (8 cycles):
-//bitwise xor 8-bit value into A, check flags:
+// xor a,r (4 cycles):
+// xor a,(hl) (8 cycles):
+// bitwise xor 8-bit value into A, check flags:
#define xor_a_u8(u8) do { \
- CF = HF2 = 0; \
- A ^= (u8); \
- ZF = A; \
+ cf = hf2 = 0; \
+ a ^= (u8); \
+ zf = a; \
} while (0)
-//cp a,r (4 cycles):
-//cp a,(addr) (8 cycles):
-//Compare (subtract without storing result) 8-bit value to A, check flags:
+// cp a,r (4 cycles):
+// cp a,(addr) (8 cycles):
+// Compare (subtract without storing result) 8-bit value to A, check flags:
#define cp_a_u8(u8) do { \
- HF1 = A; \
- HF2 = u8; \
- ZF = CF = A - HF2; \
- HF2 |= 0x400; \
+ hf1 = a; \
+ hf2 = u8; \
+ zf = cf = a - hf2; \
+ hf2 |= hf2_subf; \
} while (0)
-//inc r (4 cycles):
-//Increment value of 8-bit register, check flags except CF:
+// inc r (4 cycles):
+// Increment value of 8-bit register, check flags except CF:
#define inc_r(r) do { \
- HF2 = (r) | 0x800; \
- ZF = (r) + 1; \
- (r) = ZF & 0xFF; \
+ hf2 = (r) | hf2_incf; \
+ zf = (r) + 1; \
+ (r) = zf & 0xFF; \
} while (0)
-//dec r (4 cycles):
-//Decrement value of 8-bit register, check flags except CF:
+// dec r (4 cycles):
+// Decrement value of 8-bit register, check flags except CF:
#define dec_r(r) do { \
- HF2 = (r) | 0xC00; \
- ZF = (r) - 1; \
- (r) = ZF & 0xFF; \
+ hf2 = (r) | hf2_incf | hf2_subf; \
+ zf = (r) - 1; \
+ (r) = zf & 0xFF; \
} while (0)
-//16-BIT ARITHMETIC
-//add hl,rr (8 cycles):
-//add 16-bit register to HL, check flags except ZF:
-/*#define add_hl_rr(rh, rl) do { \
- L = HF1 = L + (rl); \
- HF1 >>= 8; \
- HF1 += H; \
- HF2 = (rh); \
- H = CF = HF1 + (rh); \
- cycleCounter += 4; \
-} while (0)*/
-
+// 16-BIT ARITHMETIC
+// add hl,rr (8 cycles):
+// add 16-bit register to HL, check flags except ZF:
#define add_hl_rr(rh, rl) do { \
- CF = L + (rl); \
- L = CF & 0xFF; \
- HF1 = H; \
- HF2 = (CF & 0x100) | (rh); \
- CF = H + (CF >> 8) + (rh); \
- H = CF & 0xFF; \
+ cf = l + (rl); \
+ l = cf & 0xFF; \
+ hf1 = h; \
+ hf2 = (cf & 0x100) | (rh); \
+ cf = h + (cf >> 8) + (rh); \
+ h = cf & 0xFF; \
cycleCounter += 4; \
} while (0)
-//inc rr (8 cycles):
-//Increment 16-bit register:
+// inc rr (8 cycles):
+// Increment 16-bit register:
#define inc_rr(rh, rl) do { \
- const unsigned inc_rr_var_tmp = (rl) + 1; \
- (rl) = inc_rr_var_tmp & 0xFF; \
- (rh) = ((rh) + (inc_rr_var_tmp >> 8)) & 0xFF; \
+ unsigned const lowinc = (rl) + 1; \
+ (rl) = lowinc & 0xFF; \
+ (rh) = ((rh) + (lowinc >> 8)) & 0xFF; \
cycleCounter += 4; \
} while (0)
-//dec rr (8 cycles):
-//Decrement 16-bit register:
+// dec rr (8 cycles):
+// Decrement 16-bit register:
#define dec_rr(rh, rl) do { \
- const unsigned dec_rr_var_tmp = (rl) - 1; \
- (rl) = dec_rr_var_tmp & 0xFF; \
- (rh) = ((rh) - (dec_rr_var_tmp >> 8 & 1)) & 0xFF; \
+ unsigned const lowdec = (rl) - 1; \
+ (rl) = lowdec & 0xFF; \
+ (rh) = ((rh) - (lowdec >> 8 & 1)) & 0xFF; \
cycleCounter += 4; \
} while (0)
#define sp_plus_n(sumout) do { \
- unsigned sp_plus_n_var_n; \
- PC_READ(sp_plus_n_var_n); \
- sp_plus_n_var_n = (sp_plus_n_var_n ^ 0x80) - 0x80; \
- \
- const unsigned sp_plus_n_var_sum = SP + sp_plus_n_var_n; \
- CF = SP ^ sp_plus_n_var_n ^ sp_plus_n_var_sum; \
- HF2 = CF << 5 & 0x200; \
- ZF = 1; \
+ unsigned disp; \
+ PC_READ(disp); \
+ disp = (disp ^ 0x80) - 0x80; \
+\
+ unsigned const res = sp + disp; \
+ cf = sp ^ disp ^ res; \
+ hf2 = cf << 5 & hf2_hcf; \
+ zf = 1; \
cycleCounter += 4; \
- (sumout) = sp_plus_n_var_sum & 0xFFFF; \
+ (sumout) = res & 0xFFFF; \
} while (0)
-//JUMPS:
-//jp nn (16 cycles):
-//Jump to address stored in the next two bytes in memory:
+// JUMPS:
+// jp nn (16 cycles):
+// Jump to address stored in the next two bytes in memory:
#define jp_nn() do { \
- unsigned jp_nn_var_l, jp_nn_var_h; \
-\
- PC_READ(jp_nn_var_l); \
- PC_READ(jp_nn_var_h); \
-\
- PC_MOD(jp_nn_var_h << 8 | jp_nn_var_l); \
+ unsigned imm0, imm1; \
+ PC_READ(imm0); \
+ PC_READ(imm1); \
+ PC_MOD(imm1 << 8 | imm0); \
} while (0)
-//jr disp (12 cycles):
-//Jump to value of next (signed) byte in memory+current address:
+// jr disp (12 cycles):
+// Jump to value of next (signed) byte in memory+current address:
#define jr_disp() do { \
- unsigned jr_disp_var_tmp; \
-\
- PC_READ(jr_disp_var_tmp); \
- jr_disp_var_tmp = (jr_disp_var_tmp ^ 0x80) - 0x80; \
-\
- PC_MOD((PC + jr_disp_var_tmp) & 0xFFFF); \
+ unsigned disp; \
+ PC_READ(disp); \
+ disp = (disp ^ 0x80) - 0x80; \
+ PC_MOD((pc + disp) & 0xFFFF); \
} while (0)
// CALLS, RESTARTS AND RETURNS:
// call nn (24 cycles):
// Jump to 16-bit immediate operand and push return address onto stack:
#define call_nn() do { \
- unsigned const npc = (PC + 2) & 0xFFFF; \
+ unsigned const npc = (pc + 2) & 0xFFFF; \
jp_nn(); \
PUSH(npc >> 8, npc & 0xFF); \
} while (0)
-//rst n (16 Cycles):
-//Push present address onto stack, jump to address n (one of 00h,08h,10h,18h,20h,28h,30h,38h):
+// rst n (16 Cycles):
+// Push present address onto stack, jump to address n (one of 00h,08h,10h,18h,20h,28h,30h,38h):
#define rst_n(n) do { \
- PUSH(PC >> 8, PC & 0xFF); \
- PC_MOD(n); \
+ cycleCounter += 4; \
+ PUSH(pc >> 8, pc & 0xFF); \
+ pc = n; \
} while (0)
-//ret (16 cycles):
-//Pop two bytes from the stack and jump to that address:
+// ret (16 cycles):
+// Pop two bytes from the stack and jump to that address:
#define ret() do { \
- unsigned ret_var_l, ret_var_h; \
-\
- pop_rr(ret_var_h, ret_var_l); \
-\
- PC_MOD(ret_var_h << 8 | ret_var_l); \
+ unsigned low, high; \
+ pop_rr(high, low); \
+ PC_MOD(high << 8 | low); \
} while (0)
-void CPU::process(const unsigned long cycles) {
- memory.setEndtime(cycleCounter_, cycles);
- hitInterruptAddress = 0;
- memory.updateInput();
+void CPU::process(unsigned long const cycles) {
+ mem_.setEndtime(cycleCounter_, cycles);
+ mem_.updateInput();
- //unsigned char A = A_;
+ hitInterruptAddress = -1;
+
+ //unsigned char a = a_;
unsigned long cycleCounter = cycleCounter_;
-
- while (memory.isActive()) {
- //unsigned short PC = PC_;
-
- if (memory.halted()) {
- if (cycleCounter < memory.nextEventTime()) {
- const unsigned long cycles = memory.nextEventTime() - cycleCounter;
+
+ while (mem_.isActive()) {
+ //unsigned short pc = pc_;
+
+ if (mem_.halted()) {
+ if (cycleCounter < mem_.nextEventTime()) {
+ unsigned long cycles = mem_.nextEventTime() - cycleCounter;
cycleCounter += cycles + (-cycles & 3);
}
- } else while (cycleCounter < memory.nextEventTime()) {
- unsigned char opcode = 0x00;
-
- int FullPC = PC;
+ } else while (cycleCounter < mem_.nextEventTime()) {
+ unsigned char opcode;
- if (PC >= 0x4000 && PC <= 0x7FFF)
- FullPC |= memory.curRomBank() << 16;
+#ifdef DLLABLES
+ for (int i = 0; i < numInterruptAddresses; ++i) {
+ if (pc == (interruptAddresses[i] & 0xFFFF)) {
+ unsigned bank = interruptAddresses[i] >> 16;
- for (int i = 0; i < numInterruptAddresses; i++) {
- if (FullPC == interruptAddresses[i]) {
- hitInterruptAddress = interruptAddresses[i];
- memory.setEndtime(cycleCounter, 0);
- break;
+ if (!bank || bank == mem_.curRomBank()) {
+ hitInterruptAddress = interruptAddresses[i];
+ mem_.setEndtime(cycleCounter, 0);
+ break;
+ }
}
}
- if (!hitInterruptAddress)
- {
- if (tracecallback) {
- int result[14];
- result[0] = cycleCounter;
- result[1] = PC;
- result[2] = SP;
- result[3] = A;
- result[4] = B;
- result[5] = C;
- result[6] = D;
- result[7] = E;
- result[8] = F();
- result[9] = H;
- result[10] = L;
- result[11] = skip;
- PC_READ_FIRST(opcode);
- result[12] = opcode;
- result[13] = memory.debugGetLY();
- tracecallback((void *)result);
- }
- else {
- PC_READ_FIRST(opcode);
- }
+ if (hitInterruptAddress != -1)
+ break;
+#endif
- if (skip) {
- PC = (PC - 1) & 0xFFFF;
- skip = false;
- }
+ if (tracecallback) {
+ int result[14];
+ result[0] = cycleCounter;
+ result[1] = pc;
+ result[2] = sp;
+ result[3] = a;
+ result[4] = b;
+ result[5] = c;
+ result[6] = d;
+ result[7] = e;
+ result[8] = toF(hf2, cf, zf);
+ result[9] = h;
+ result[10] = l;
+ result[11] = skip_;
+ PC_READ_FIRST(opcode);
+ result[12] = opcode;
+ result[13] = mem_.debugGetLY();
+ tracecallback((void *)result);
}
-
+ else {
+ PC_READ_FIRST(opcode);
+ }
+
+ if (skip_) {
+ pc = (pc - 1) & 0xFFFF;
+ skip_ = false;
+ }
+
switch (opcode) {
- //nop (4 cycles):
- //Do nothing for 4 cycles:
case 0x00:
break;
case 0x01:
- ld_rr_nn(B, C);
+ ld_rr_nn(b, c);
break;
case 0x02:
- WRITE(BC(), A);
+ WRITE(bc(), a);
break;
case 0x03:
- inc_rr(B, C);
+ inc_rr(b, c);
break;
case 0x04:
- inc_r(B);
+ inc_r(b);
break;
case 0x05:
- dec_r(B);
+ dec_r(b);
break;
case 0x06:
- PC_READ(B);
+ PC_READ(b);
break;
- //rlca (4 cycles):
- //Rotate 8-bit register A left, store old bit7 in CF. Reset SF, HCF, ZF:
+ // rlca (4 cycles):
+ // Rotate 8-bit register A left, store old bit7 in CF. Reset SF, HCF, ZF:
case 0x07:
- CF = A << 1;
- A = (CF | CF >> 8) & 0xFF;
- HF2 = 0;
- ZF = 1;
+ cf = a << 1;
+ a = (cf | cf >> 8) & 0xFF;
+ hf2 = 0;
+ zf = 1;
break;
- //ld (nn),SP (20 cycles):
- //Put value of SP into address given by next 2 bytes in memory:
+ // ld (nn),SP (20 cycles):
+ // Put value of SP into address given by next 2 bytes in memory:
case 0x08:
{
- unsigned l, h;
-
- PC_READ(l);
- PC_READ(h);
-
- const unsigned addr = h << 8 | l;
-
- WRITE(addr, SP & 0xFF);
- WRITE((addr + 1) & 0xFFFF, SP >> 8);
+ unsigned imml, immh;
+ PC_READ(imml);
+ PC_READ(immh);
+
+ unsigned const addr = immh << 8 | imml;
+ WRITE(addr, sp & 0xFF);
+ WRITE((addr + 1) & 0xFFFF, sp >> 8);
}
+
break;
case 0x09:
- add_hl_rr(B, C);
+ add_hl_rr(b, c);
break;
case 0x0A:
- READ(A, BC());
+ READ(a, bc());
break;
case 0x0B:
- dec_rr(B, C);
+ dec_rr(b, c);
break;
case 0x0C:
- inc_r(C);
+ inc_r(c);
break;
case 0x0D:
- dec_r(C);
+ dec_r(c);
break;
case 0x0E:
- PC_READ(C);
+ PC_READ(c);
break;
- //rrca (4 cycles):
- //Rotate 8-bit register A right, store old bit0 in CF. Reset SF, HCF, ZF:
+ // rrca (4 cycles):
+ // Rotate 8-bit register A right, store old bit0 in CF. Reset SF, HCF, ZF:
case 0x0F:
- CF = A << 8 | A;
- A = CF >> 1 & 0xFF;
- HF2 = 0;
- ZF = 1;
+ cf = a << 8 | a;
+ a = cf >> 1 & 0xFF;
+ hf2 = 0;
+ zf = 1;
break;
- //stop (4 cycles):
- //Halt CPU and LCD display until button pressed:
+ // stop (4 cycles):
+ // Halt CPU and LCD display until button pressed:
case 0x10:
{
- cycleCounter = memory.stop(cycleCounter);
+ cycleCounter = mem_.stop(cycleCounter);
- if (cycleCounter < memory.nextEventTime()) {
- const unsigned long cycles = memory.nextEventTime() - cycleCounter;
+ if (cycleCounter < mem_.nextEventTime()) {
+ unsigned long cycles = mem_.nextEventTime() - cycleCounter;
cycleCounter += cycles + (-cycles & 3);
}
}
break;
+
case 0x11:
- ld_rr_nn(D, E);
+ ld_rr_nn(d, e);
break;
case 0x12:
- WRITE(DE(), A);
+ WRITE(de(), a);
break;
case 0x13:
- inc_rr(D, E);
+ inc_rr(d, e);
break;
case 0x14:
- inc_r(D);
+ inc_r(d);
break;
case 0x15:
- dec_r(D);
+ dec_r(d);
break;
case 0x16:
- PC_READ(D);
+ PC_READ(d);
break;
- //rla (4 cycles):
- //Rotate 8-bit register A left through CF, store old bit7 in CF, old CF value becomes bit0. Reset SF, HCF, ZF:
+ // rla (4 cycles):
+ // Rotate 8-bit register A left through CF, store old bit7 in CF,
+ // old CF value becomes bit0. Reset SF, HCF, ZF:
case 0x17:
{
- const unsigned oldcf = CF >> 8 & 1;
- CF = A << 1;
- A = (CF | oldcf) & 0xFF;
+ unsigned oldcf = cf >> 8 & 1;
+ cf = a << 1;
+ a = (cf | oldcf) & 0xFF;
}
-
- HF2 = 0;
- ZF = 1;
+
+ hf2 = 0;
+ zf = 1;
break;
case 0x18:
jr_disp();
break;
case 0x19:
- add_hl_rr(D, E);
+ add_hl_rr(d, e);
break;
case 0x1A:
- READ(A, DE());
+ READ(a, de());
break;
case 0x1B:
- dec_rr(D, E);
+ dec_rr(d, e);
break;
case 0x1C:
- inc_r(E);
+ inc_r(e);
break;
case 0x1D:
- dec_r(E);
+ dec_r(e);
break;
case 0x1E:
- PC_READ(E);
+ PC_READ(e);
break;
- //rra (4 cycles):
- //Rotate 8-bit register A right through CF, store old bit0 in CF, old CF value becomes bit7. Reset SF, HCF, ZF:
+ // rra (4 cycles):
+ // Rotate 8-bit register A right through CF, store old bit0 in CF,
+ // old CF value becomes bit7. Reset SF, HCF, ZF:
case 0x1F:
{
- const unsigned oldcf = CF & 0x100;
- CF = A << 8;
- A = (A | oldcf) >> 1;
+ unsigned oldcf = cf & 0x100;
+ cf = a << 8;
+ a = (a | oldcf) >> 1;
}
-
- HF2 = 0;
- ZF = 1;
- break;
- //jr nz,disp (12;8 cycles):
- //Jump to value of next (signed) byte in memory+current address if ZF is unset:
+ hf2 = 0;
+ zf = 1;
+ break;
+
+ // jr nz,disp (12;8 cycles):
+ // Jump to value of next (signed) byte in memory+current address if ZF is unset:
case 0x20:
- if (ZF & 0xFF) {
+ if (zf & 0xFF) {
jr_disp();
} else {
- PC_MOD((PC + 1) & 0xFFFF);
+ PC_MOD((pc + 1) & 0xFFFF);
}
+
break;
- case 0x21:
- ld_rr_nn(H, L);
- break;
+ case 0x21: ld_rr_nn(h, l); break;
- //ldi (hl),a (8 cycles):
- //Put A into memory address in hl. Increment HL:
+ // ldi (hl),a (8 cycles):
+ // Put A into memory address in hl. Increment HL:
case 0x22:
{
- unsigned addr = HL();
-
- WRITE(addr, A);
-
+ unsigned addr = hl();
+ WRITE(addr, a);
+
addr = (addr + 1) & 0xFFFF;
- L = addr;
- H = addr >> 8;
+ l = addr;
+ h = addr >> 8;
}
+
break;
case 0x23:
- inc_rr(H, L);
+ inc_rr(h, l);
break;
case 0x24:
- inc_r(H);
+ inc_r(h);
break;
case 0x25:
- dec_r(H);
+ dec_r(h);
break;
case 0x26:
- PC_READ(H);
+ PC_READ(h);
break;
-
- //daa (4 cycles):
- //Adjust register A to correctly represent a BCD. Check ZF, HF and CF:
+ // daa (4 cycles):
+ // Adjust register A to correctly represent a BCD. Check ZF, HF and CF:
case 0x27:
- /*{
- unsigned correction = ((A > 0x99) || (CF & 0x100)) ? 0x60 : 0x00;
-
- calcHF(HF1, HF2);
-
- if ((A & 0x0F) > 0x09 || (HF2 & 0x200))
- correction |= 0x06;
-
- HF1 = A;
- HF2 = (HF2 & 0x400) | correction;
- CF = (correction & 0x40) << 2;
- A = (HF2 & 0x400) ? A - correction : (A + correction);
- ZF = A;
- }*/
-
- calcHF(HF1, HF2);
-
+ hf2 = updateHf2FromHf1(hf1, hf2);
+
{
- unsigned correction = (CF & 0x100) ? 0x60 : 0x00;
-
- if (HF2 & 0x200)
+ unsigned correction = cf & 0x100 ? 0x60 : 0x00;
+
+ if (hf2 & hf2_hcf)
correction |= 0x06;
-
- if (!(HF2 &= 0x400)) {
- if ((A & 0x0F) > 0x09)
+
+ if (!(hf2 &= hf2_subf)) {
+ if ((a & 0x0F) > 0x09)
correction |= 0x06;
-
- if (A > 0x99)
+ if (a > 0x99)
correction |= 0x60;
-
- A += correction;
+
+ a += correction;
} else
- A -= correction;
-
- CF = correction << 2 & 0x100;
- ZF = A;
- A &= 0xFF;
+ a -= correction;
+
+ cf = correction << 2 & 0x100;
+ zf = a;
+ a &= 0xFF;
}
+
break;
- //jr z,disp (12;8 cycles):
- //Jump to value of next (signed) byte in memory+current address if ZF is set:
+ // jr z,disp (12;8 cycles):
+ // Jump to value of next (signed) byte in memory+current address if ZF is set:
case 0x28:
- if (ZF & 0xFF) {
- PC_MOD((PC + 1) & 0xFFFF);
+ if (zf & 0xFF) {
+ PC_MOD((pc + 1) & 0xFFFF);
} else {
jr_disp();
}
+
break;
- //add hl,hl (8 cycles):
- //add 16-bit register HL to HL, check flags except ZF:
case 0x29:
- add_hl_rr(H, L);
+ add_hl_rr(h, l);
break;
- //ldi a,(hl) (8 cycles):
- //Put value at address in hl into A. Increment HL:
+ // ldi a,(hl) (8 cycles):
+ // Put value at address in hl into A. Increment HL:
case 0x2A:
{
- unsigned addr = HL();
-
- READ(A, addr);
-
+ unsigned addr = hl();
+ READ(a, addr);
+
addr = (addr + 1) & 0xFFFF;
- L = addr;
- H = addr >> 8;
+ l = addr;
+ h = addr >> 8;
}
+
break;
case 0x2B:
- dec_rr(H, L);
+ dec_rr(h, l);
break;
case 0x2C:
- inc_r(L);
+ inc_r(l);
break;
case 0x2D:
- dec_r(L);
+ dec_r(l);
break;
case 0x2E:
- PC_READ(L);
+ PC_READ(l);
break;
- //cpl (4 cycles):
- //Complement register A. (Flip all bits), set SF and HCF:
- case 0x2F: /*setSubtractFlag(); setHalfCarryFlag();*/
- HF2 = 0x600;
- A ^= 0xFF;
+ // cpl (4 cycles):
+ // Complement register A. (Flip all bits), set SF and HCF:
+ case 0x2F:
+ hf2 = hf2_subf | hf2_hcf;
+ a ^= 0xFF;
break;
- //jr nc,disp (12;8 cycles):
- //Jump to value of next (signed) byte in memory+current address if CF is unset:
+ // jr nc,disp (12;8 cycles):
+ // Jump to value of next (signed) byte in memory+current address if CF is unset:
case 0x30:
- if (CF & 0x100) {
- PC_MOD((PC + 1) & 0xFFFF);
+ if (cf & 0x100) {
+ PC_MOD((pc + 1) & 0xFFFF);
} else {
jr_disp();
}
+
break;
- //ld sp,nn (12 cycles)
- //set sp to 16-bit value of next 2 bytes in memory
+ // ld sp,nn (12 cycles)
+ // set sp to 16-bit value of next 2 bytes in memory
case 0x31:
{
- unsigned l, h;
-
- PC_READ(l);
- PC_READ(h);
-
- SP = h << 8 | l;
+ unsigned imml, immh;
+ PC_READ(imml);
+ PC_READ(immh);
+
+ sp = immh << 8 | imml;
}
+
break;
- //ldd (hl),a (8 cycles):
- //Put A into memory address in hl. Decrement HL:
+ // ldd (hl),a (8 cycles):
+ // Put A into memory address in hl. Decrement HL:
case 0x32:
{
- unsigned addr = HL();
-
- WRITE(addr, A);
-
+ unsigned addr = hl();
+ WRITE(addr, a);
+
addr = (addr - 1) & 0xFFFF;
- L = addr;
- H = addr >> 8;
+ l = addr;
+ h = addr >> 8;
}
+
break;
case 0x33:
- SP = (SP + 1) & 0xFFFF;
+ sp = (sp + 1) & 0xFFFF;
cycleCounter += 4;
break;
- //inc (hl) (12 cycles):
- //Increment value at address in hl, check flags except CF:
- case 0x34:
+ // inc (hl) (12 cycles):
+ // Increment value at address in hl, check flags except CF:
+ case 0x34:
{
- const unsigned addr = HL();
-
- READ(HF2, addr);
- ZF = HF2 + 1;
- WRITE(addr, ZF & 0xFF);
- HF2 |= 0x800;
+ unsigned const addr = hl();
+ READ(hf2, addr);
+ zf = hf2 + 1;
+ WRITE(addr, zf & 0xFF);
+ hf2 |= hf2_incf;
}
+
break;
- //dec (hl) (12 cycles):
- //Decrement value at address in hl, check flags except CF:
+ // dec (hl) (12 cycles):
+ // Decrement value at address in hl, check flags except CF:
case 0x35:
{
- const unsigned addr = HL();
-
- READ(HF2, addr);
- ZF = HF2 - 1;
- WRITE(addr, ZF & 0xFF);
- HF2 |= 0xC00;
+ unsigned const addr = hl();
+ READ(hf2, addr);
+ zf = hf2 - 1;
+ WRITE(addr, zf & 0xFF);
+ hf2 |= hf2_incf | hf2_subf;
}
+
break;
- //ld (hl),n (12 cycles):
- //set memory at address in hl to value of next byte in memory:
+ // ld (hl),n (12 cycles):
+ // set memory at address in hl to value of next byte in memory:
case 0x36:
{
- unsigned tmp;
-
- PC_READ(tmp);
- WRITE(HL(), tmp);
+ unsigned imm;
+ PC_READ(imm);
+ WRITE(hl(), imm);
}
+
break;
- //scf (4 cycles):
- //Set CF. Unset SF and HCF:
- case 0x37: /*setCarryFlag(); unsetSubtractFlag(); unsetHalfCarryFlag();*/
- CF = 0x100;
- HF2 = 0;
+ // scf (4 cycles):
+ // Set CF. Unset SF and HCF:
+ case 0x37:
+ cf = 0x100;
+ hf2 = 0;
break;
- //jr c,disp (12;8 cycles):
- //Jump to value of next (signed) byte in memory+current address if CF is set:
- case 0x38: //PC+=(((int8_t)memory.read(PC++))*CarryFlag()); Cycles(8); break;
- if (CF & 0x100) {
+ // jr c,disp (12;8 cycles):
+ // Jump to value of next (signed) byte in memory+current address if CF is set:
+ case 0x38:
+ if (cf & 0x100) {
jr_disp();
} else {
- PC_MOD((PC + 1) & 0xFFFF);
+ PC_MOD((pc + 1) & 0xFFFF);
}
+
break;
- //add hl,sp (8 cycles):
- //add SP to HL, check flags except ZF:
- case 0x39: /*add_hl_rr(SP>>8, SP); break;*/
- CF = L + SP;
- L = CF & 0xFF;
- HF1 = H;
- HF2 = ((CF ^ SP) & 0x100) | SP >> 8;
- CF >>= 8;
- CF += H;
- H = CF & 0xFF;
+ // add hl,sp (8 cycles):
+ // add SP to HL, check flags except ZF:
+ case 0x39:
+ cf = l + sp;
+ l = cf & 0xFF;
+ hf1 = h;
+ hf2 = ((cf ^ sp) & 0x100) | sp >> 8;
+ cf >>= 8;
+ cf += h;
+ h = cf & 0xFF;
cycleCounter += 4;
break;
- //ldd a,(hl) (8 cycles):
- //Put value at address in hl into A. Decrement HL:
+ // ldd a,(hl) (8 cycles):
+ // Put value at address in hl into A. Decrement HL:
case 0x3A:
{
- unsigned addr = HL();
-
- A = memory.read(addr, cycleCounter);
+ unsigned addr = hl();
+ a = mem_.read(addr, cycleCounter);
cycleCounter += 4;
-
+
addr = (addr - 1) & 0xFFFF;
- L = addr;
- H = addr >> 8;
+ l = addr;
+ h = addr >> 8;
}
+
break;
case 0x3B:
- SP = (SP - 1) & 0xFFFF;
+ sp = (sp - 1) & 0xFFFF;
cycleCounter += 4;
break;
+
case 0x3C:
- inc_r(A);
+ inc_r(a);
break;
case 0x3D:
- dec_r(A);
+ dec_r(a);
break;
case 0x3E:
- PC_READ(A);
+ PC_READ(a);
break;
- //ccf (4 cycles):
- //Complement CF (unset if set vv.) Unset SF and HCF.
- case 0x3F: /*complementCarryFlag(); unsetSubtractFlag(); unsetHalfCarryFlag();*/
- CF ^= 0x100;
- HF2 = 0;
+ // ccf (4 cycles):
+ // Complement CF (unset if set vv.) Unset SF and HCF.
+ case 0x3F:
+ cf ^= 0x100;
+ hf2 = 0;
break;
- //ld r,r (4 cycles):next_irqEventTime
- //ld r,(r) (8 cycles):
- case 0x40:
- B = B;
- break;
- case 0x41:
- B = C;
- break;
- case 0x42:
- B = D;
- break;
- case 0x43:
- B = E;
- break;
- case 0x44:
- B = H;
- break;
- case 0x45:
- B = L;
- break;
- case 0x46:
- READ(B, HL());
- break;
- case 0x47:
- B = A;
- break;
- case 0x48:
- C = B;
- break;
- case 0x49:
- C = C;
- break;
- case 0x4A:
- C = D;
- break;
- case 0x4B:
- C = E;
- break;
- case 0x4C:
- C = H;
- break;
- case 0x4D:
- C = L;
- break;
- case 0x4E:
- READ(C, HL());
- break;
- case 0x4F:
- C = A;
- break;
- case 0x50:
- D = B;
- break;
- case 0x51:
- D = C;
- break;
- case 0x52:
- D = D;
- break;
- case 0x53:
- D = E;
- break;
- case 0x54:
- D = H;
- break;
- case 0x55:
- D = L;
- break;
- case 0x56:
- READ(D, HL());
- break;
- case 0x57:
- D = A;
- break;
- case 0x58:
- E = B;
- break;
- case 0x59:
- E = C;
- break;
- case 0x5A:
- E = D;
- break;
- case 0x5B:
- E = E;
- break;
- case 0x5C:
- E = H;
- break;
- case 0x5D:
- E = L;
- break;
- case 0x5E:
- READ(E, HL());
- break;
- case 0x5F:
- E = A;
- break;
- case 0x60:
- H = B;
- break;
- case 0x61:
- H = C;
- break;
- case 0x62:
- H = D;
- break;
- case 0x63:
- H = E;
- break;
- case 0x64:
- H = H;
- break;
- case 0x65:
- H = L;
- break;
- case 0x66:
- READ(H, HL());
- break;
- case 0x67:
- H = A;
- break;
- case 0x68:
- L = B;
- break;
- case 0x69:
- L = C;
- break;
- case 0x6A:
- L = D;
- break;
- case 0x6B:
- L = E;
- break;
- case 0x6C:
- L = H;
- break;
- case 0x6D:
- L = L;
- break;
- case 0x6E:
- READ(L, HL());
- break;
- case 0x6F:
- L = A;
- break;
- case 0x70:
- WRITE(HL(), B);
- break;
- case 0x71:
- WRITE(HL(), C);
- break;
- case 0x72:
- WRITE(HL(), D);
- break;
- case 0x73:
- WRITE(HL(), E);
- break;
- case 0x74:
- WRITE(HL(), H);
- break;
- case 0x75:
- WRITE(HL(), L);
- break;
+ case 0x40: /*b = b;*/ break;
+ case 0x41: b = c; break;
+ case 0x42: b = d; break;
+ case 0x43: b = e; break;
+ case 0x44: b = h; break;
+ case 0x45: b = l; break;
+ case 0x46: READ(b, hl()); break;
+ case 0x47: b = a; break;
- //halt (4 cycles):
+ case 0x48: c = b; break;
+ case 0x49: /*c = c;*/ break;
+ case 0x4A: c = d; break;
+ case 0x4B: c = e; break;
+ case 0x4C: c = h; break;
+ case 0x4D: c = l; break;
+ case 0x4E: READ(c, hl()); break;
+ case 0x4F: c = a; break;
+
+ case 0x50: d = b; break;
+ case 0x51: d = c; break;
+ case 0x52: /*d = d;*/ break;
+ case 0x53: d = e; break;
+ case 0x54: d = h; break;
+ case 0x55: d = l; break;
+ case 0x56: READ(d, hl()); break;
+ case 0x57: d = a; break;
+
+ case 0x58: e = b; break;
+ case 0x59: e = c; break;
+ case 0x5A: e = d; break;
+ case 0x5B: /*e = e;*/ break;
+ case 0x5C: e = h; break;
+ case 0x5D: e = l; break;
+ case 0x5E: READ(e, hl()); break;
+ case 0x5F: e = a; break;
+
+ case 0x60: h = b; break;
+ case 0x61: h = c; break;
+ case 0x62: h = d; break;
+ case 0x63: h = e; break;
+ case 0x64: /*h = h;*/ break;
+ case 0x65: h = l; break;
+ case 0x66: READ(h, hl()); break;
+ case 0x67: h = a; break;
+
+ case 0x68: l = b; break;
+ case 0x69: l = c; break;
+ case 0x6A: l = d; break;
+ case 0x6B: l = e; break;
+ case 0x6C: l = h; break;
+ case 0x6D: /*l = l;*/ break;
+ case 0x6E: READ(l, hl()); break;
+ case 0x6F: l = a; break;
+
+ case 0x70: WRITE(hl(), b); break;
+ case 0x71: WRITE(hl(), c); break;
+ case 0x72: WRITE(hl(), d); break;
+ case 0x73: WRITE(hl(), e); break;
+ case 0x74: WRITE(hl(), h); break;
+ case 0x75: WRITE(hl(), l); break;
+
+ // halt (4 cycles):
case 0x76:
- if (memory.ff_read(0xFF0F, cycleCounter) & memory.ff_read(0xFFFF, cycleCounter) & 0x1F) {
- if (memory.ime())
- PC = (PC - 1) & 0xFFFF;
+ if (mem_.ff_read(0x0F, cycleCounter) & mem_.ff_read(0xFF, cycleCounter) & 0x1F) {
+ if (mem_.ime())
+ pc = (pc - 1) & 0xFFFF;
else
- skip = true;
+ skip_ = true;
} else {
- memory.halt(cycleCounter);
+ mem_.halt(cycleCounter);
- if (cycleCounter < memory.nextEventTime()) {
- const unsigned long cycles = memory.nextEventTime() - cycleCounter;
+ if (cycleCounter < mem_.nextEventTime()) {
+ unsigned long cycles = mem_.nextEventTime() - cycleCounter;
cycleCounter += cycles + (-cycles & 3);
}
}
break;
- case 0x77:
- WRITE(HL(), A);
- break;
- case 0x78:
- A = B;
- break;
- case 0x79:
- A = C;
- break;
- case 0x7A:
- A = D;
- break;
- case 0x7B:
- A = E;
- break;
- case 0x7C:
- A = H;
- break;
- case 0x7D:
- A = L;
- break;
- case 0x7E:
- READ(A, HL());
- break;
- case 0x7F:
- // A = A;
- break;
- case 0x80:
- add_a_u8(B);
- break;
- case 0x81:
- add_a_u8(C);
- break;
- case 0x82:
- add_a_u8(D);
- break;
- case 0x83:
- add_a_u8(E);
- break;
- case 0x84:
- add_a_u8(H);
- break;
- case 0x85:
- add_a_u8(L);
- break;
- case 0x86:
- {
- unsigned data;
- READ(data, HL());
-
- add_a_u8(data);
- }
- break;
- case 0x87:
- add_a_u8(A);
- break;
- case 0x88:
- adc_a_u8(B);
- break;
- case 0x89:
- adc_a_u8(C);
- break;
- case 0x8A:
- adc_a_u8(D);
- break;
- case 0x8B:
- adc_a_u8(E);
- break;
- case 0x8C:
- adc_a_u8(H);
- break;
- case 0x8D:
- adc_a_u8(L);
- break;
- case 0x8E:
- {
- unsigned data;
-
- READ(data, HL());
-
- adc_a_u8(data);
- }
- break;
- case 0x8F:
- adc_a_u8(A);
- break;
- case 0x90:
- sub_a_u8(B);
- break;
- case 0x91:
- sub_a_u8(C);
- break;
- case 0x92:
- sub_a_u8(D);
- break;
- case 0x93:
- sub_a_u8(E);
- break;
- case 0x94:
- sub_a_u8(H);
- break;
- case 0x95:
- sub_a_u8(L);
- break;
- case 0x96:
- {
- unsigned data;
-
- READ(data, HL());
-
- sub_a_u8(data);
- }
- break;
- //A-A is always 0:
+ case 0x77: WRITE(hl(), a); break;
+ case 0x78: a = b; break;
+ case 0x79: a = c; break;
+ case 0x7A: a = d; break;
+ case 0x7B: a = e; break;
+ case 0x7C: a = h; break;
+ case 0x7D: a = l; break;
+ case 0x7E: READ(a, hl()); break;
+ case 0x7F: /*a = a;*/ break;
+
+ case 0x80: add_a_u8(b); break;
+ case 0x81: add_a_u8(c); break;
+ case 0x82: add_a_u8(d); break;
+ case 0x83: add_a_u8(e); break;
+ case 0x84: add_a_u8(h); break;
+ case 0x85: add_a_u8(l); break;
+ case 0x86: { unsigned data; READ(data, hl()); add_a_u8(data); } break;
+ case 0x87: add_a_u8(a); break;
+
+ case 0x88: adc_a_u8(b); break;
+ case 0x89: adc_a_u8(c); break;
+ case 0x8A: adc_a_u8(d); break;
+ case 0x8B: adc_a_u8(e); break;
+ case 0x8C: adc_a_u8(h); break;
+ case 0x8D: adc_a_u8(l); break;
+ case 0x8E: { unsigned data; READ(data, hl()); adc_a_u8(data); } break;
+ case 0x8F: adc_a_u8(a); break;
+
+ case 0x90: sub_a_u8(b); break;
+ case 0x91: sub_a_u8(c); break;
+ case 0x92: sub_a_u8(d); break;
+ case 0x93: sub_a_u8(e); break;
+ case 0x94: sub_a_u8(h); break;
+ case 0x95: sub_a_u8(l); break;
+ case 0x96: { unsigned data; READ(data, hl()); sub_a_u8(data); } break;
+
+ // A-A is always 0:
case 0x97:
- HF2 = 0x400;
- CF = ZF = A = 0;
- break;
- case 0x98:
- sbc_a_u8(B);
- break;
- case 0x99:
- sbc_a_u8(C);
- break;
- case 0x9A:
- sbc_a_u8(D);
- break;
- case 0x9B:
- sbc_a_u8(E);
- break;
- case 0x9C:
- sbc_a_u8(H);
- break;
- case 0x9D:
- sbc_a_u8(L);
- break;
- case 0x9E:
- {
- unsigned data;
-
- READ(data, HL());
-
- sbc_a_u8(data);
- }
- break;
- case 0x9F:
- sbc_a_u8(A);
- break;
- case 0xA0:
- and_a_u8(B);
- break;
- case 0xA1:
- and_a_u8(C);
- break;
- case 0xA2:
- and_a_u8(D);
- break;
- case 0xA3:
- and_a_u8(E);
- break;
- case 0xA4:
- and_a_u8(H);
- break;
- case 0xA5:
- and_a_u8(L);
- break;
- case 0xA6:
- {
- unsigned data;
-
- READ(data, HL());
-
- and_a_u8(data);
- }
- break;
- //A&A will always be A:
- case 0xA7:
- ZF = A;
- CF = 0;
- HF2 = 0x200;
- break;
- case 0xA8:
- xor_a_u8(B);
- break;
- case 0xA9:
- xor_a_u8(C);
- break;
- case 0xAA:
- xor_a_u8(D);
- break;
- case 0xAB:
- xor_a_u8(E);
- break;
- case 0xAC:
- xor_a_u8(H);
- break;
- case 0xAD:
- xor_a_u8(L);
- break;
- case 0xAE:
- {
- unsigned data;
-
- READ(data, HL());
-
- xor_a_u8(data);
- }
- break;
- //A^A will always be 0:
- case 0xAF:
- CF = HF2 = ZF = A = 0;
- break;
- case 0xB0:
- or_a_u8(B);
- break;
- case 0xB1:
- or_a_u8(C);
- break;
- case 0xB2:
- or_a_u8(D);
- break;
- case 0xB3:
- or_a_u8(E);
- break;
- case 0xB4:
- or_a_u8(H);
- break;
- case 0xB5:
- or_a_u8(L);
- break;
- case 0xB6:
- {
- unsigned data;
-
- READ(data, HL());
-
- or_a_u8(data);
- }
- break;
- //A|A will always be A:
- case 0xB7:
- ZF = A;
- HF2 = CF = 0;
- break;
- case 0xB8:
- cp_a_u8(B);
- break;
- case 0xB9:
- cp_a_u8(C);
- break;
- case 0xBA:
- cp_a_u8(D);
- break;
- case 0xBB:
- cp_a_u8(E);
- break;
- case 0xBC:
- cp_a_u8(H);
- break;
- case 0xBD:
- cp_a_u8(L);
- break;
- case 0xBE:
- {
- unsigned data;
-
- READ(data, HL());
-
- cp_a_u8(data);
- }
- break;
- //A always equals A:
- case 0xBF:
- CF = ZF = 0;
- HF2 = 0x400;
+ hf2 = hf2_subf;
+ cf = zf = a = 0;
break;
- //ret nz (20;8 cycles):
- //Pop two bytes from the stack and jump to that address, if ZF is unset:
+ case 0x98: sbc_a_u8(b); break;
+ case 0x99: sbc_a_u8(c); break;
+ case 0x9A: sbc_a_u8(d); break;
+ case 0x9B: sbc_a_u8(e); break;
+ case 0x9C: sbc_a_u8(h); break;
+ case 0x9D: sbc_a_u8(l); break;
+ case 0x9E: { unsigned data; READ(data, hl()); sbc_a_u8(data); } break;
+ case 0x9F: sbc_a_u8(a); break;
+
+ case 0xA0: and_a_u8(b); break;
+ case 0xA1: and_a_u8(c); break;
+ case 0xA2: and_a_u8(d); break;
+ case 0xA3: and_a_u8(e); break;
+ case 0xA4: and_a_u8(h); break;
+ case 0xA5: and_a_u8(l); break;
+ case 0xA6: { unsigned data; READ(data, hl()); and_a_u8(data); } break;
+
+ // A&A will always be A:
+ case 0xA7:
+ zf = a;
+ cf = 0;
+ hf2 = hf2_hcf;
+ break;
+
+ case 0xA8: xor_a_u8(b); break;
+ case 0xA9: xor_a_u8(c); break;
+ case 0xAA: xor_a_u8(d); break;
+ case 0xAB: xor_a_u8(e); break;
+ case 0xAC: xor_a_u8(h); break;
+ case 0xAD: xor_a_u8(l); break;
+ case 0xAE: { unsigned data; READ(data, hl()); xor_a_u8(data); } break;
+
+ // A^A will always be 0:
+ case 0xAF: cf = hf2 = zf = a = 0; break;
+
+ case 0xB0: or_a_u8(b); break;
+ case 0xB1: or_a_u8(c); break;
+ case 0xB2: or_a_u8(d); break;
+ case 0xB3: or_a_u8(e); break;
+ case 0xB4: or_a_u8(h); break;
+ case 0xB5: or_a_u8(l); break;
+ case 0xB6: { unsigned data; READ(data, hl()); or_a_u8(data); } break;
+
+ // A|A will always be A:
+ case 0xB7:
+ zf = a;
+ hf2 = cf = 0;
+ break;
+
+ case 0xB8: cp_a_u8(b); break;
+ case 0xB9: cp_a_u8(c); break;
+ case 0xBA: cp_a_u8(d); break;
+ case 0xBB: cp_a_u8(e); break;
+ case 0xBC: cp_a_u8(h); break;
+ case 0xBD: cp_a_u8(l); break;
+ case 0xBE: { unsigned data; READ(data, hl()); cp_a_u8(data); } break;
+
+ // A always equals A:
+ case 0xBF:
+ cf = zf = 0;
+ hf2 = hf2_subf;
+ break;
+
+ // ret nz (20;8 cycles):
+ // Pop two bytes from the stack and jump to that address, if ZF is unset:
case 0xC0:
cycleCounter += 4;
-
- if (ZF & 0xFF) {
+
+ if (zf & 0xFF)
ret();
- }
+
break;
case 0xC1:
- pop_rr(B, C);
+ pop_rr(b, c);
break;
- //jp nz,nn (16;12 cycles):
- //Jump to address stored in next two bytes in memory if ZF is unset:
+ // jp nz,nn (16;12 cycles):
+ // Jump to address stored in next two bytes in memory if ZF is unset:
case 0xC2:
- if (ZF & 0xFF) {
+ if (zf & 0xFF) {
jp_nn();
} else {
- PC_MOD((PC + 2) & 0xFFFF);
+ PC_MOD((pc + 2) & 0xFFFF);
cycleCounter += 4;
}
+
break;
case 0xC3:
jp_nn();
break;
- //call nz,nn (24;12 cycles):
- //Push address of next instruction onto stack and then jump to address stored in next two bytes in memory, if ZF is unset:
+ // call nz,nn (24;12 cycles):
+ // Push address of next instruction onto stack and then jump to
+ // address stored in next two bytes in memory, if ZF is unset:
case 0xC4:
- if (ZF & 0xFF) {
+ if (zf & 0xFF) {
call_nn();
} else {
- PC_MOD((PC + 2) & 0xFFFF);
+ PC_MOD((pc + 2) & 0xFFFF);
cycleCounter += 4;
}
+
break;
case 0xC5:
- push_rr(B, C);
+ push_rr(b, c);
break;
case 0xC6:
{
unsigned data;
-
PC_READ(data);
-
add_a_u8(data);
}
+
break;
+
case 0xC7:
rst_n(0x00);
break;
- //ret z (20;8 cycles):
- //Pop two bytes from the stack and jump to that address, if ZF is set:
+ // ret z (20;8 cycles):
+ // Pop two bytes from the stack and jump to that address, if ZF is set:
case 0xC8:
cycleCounter += 4;
-
- if (!(ZF & 0xFF)) {
+
+ if (!(zf & 0xFF))
ret();
- }
-
+
break;
- //ret (16 cycles):
- //Pop two bytes from the stack and jump to that address:
+ // ret (16 cycles):
+ // Pop two bytes from the stack and jump to that address:
case 0xC9:
ret();
break;
- //jp z,nn (16;12 cycles):
- //Jump to address stored in next two bytes in memory if ZF is set:
+ // jp z,nn (16;12 cycles):
+ // Jump to address stored in next two bytes in memory if ZF is set:
case 0xCA:
- if (ZF & 0xFF) {
- PC_MOD((PC + 2) & 0xFFFF);
+ if (zf & 0xFF) {
+ PC_MOD((pc + 2) & 0xFFFF);
cycleCounter += 4;
} else {
jp_nn();
}
+
break;
- //CB OPCODES (Shifts, rotates and bits):
+ // CB OPCODES (Shifts, rotates and bits):
case 0xCB:
PC_READ(opcode);
-
+
switch (opcode) {
- case 0x00:
- rlc_r(B);
- break;
- case 0x01:
- rlc_r(C);
- break;
- case 0x02:
- rlc_r(D);
- break;
- case 0x03:
- rlc_r(E);
- break;
- case 0x04:
- rlc_r(H);
- break;
- case 0x05:
- rlc_r(L);
- break;
- //rlc (hl) (16 cycles):
- //Rotate 8-bit value stored at address in HL left, store old bit7 in CF. Reset SF and HCF. Check ZF:
+ case 0x00: rlc_r(b); break;
+ case 0x01: rlc_r(c); break;
+ case 0x02: rlc_r(d); break;
+ case 0x03: rlc_r(e); break;
+ case 0x04: rlc_r(h); break;
+ case 0x05: rlc_r(l); break;
+
+ // rlc (hl) (16 cycles):
+ // Rotate 8-bit value stored at address in HL left, store old bit7 in CF.
+ // Reset SF and HCF. Check ZF:
case 0x06:
{
- const unsigned addr = HL();
-
- READ(CF, addr);
- CF <<= 1;
-
- ZF = CF | (CF >> 8);
-
- WRITE(addr, ZF & 0xFF);
-
- HF2 = 0;
+ unsigned const addr = hl();
+ READ(cf, addr);
+ cf <<= 1;
+ zf = cf | (cf >> 8);
+ WRITE(addr, zf & 0xFF);
+ hf2 = 0;
}
+
break;
- case 0x07:
- rlc_r(A);
- break;
- case 0x08:
- rrc_r(B);
- break;
- case 0x09:
- rrc_r(C);
- break;
- case 0x0A:
- rrc_r(D);
- break;
- case 0x0B:
- rrc_r(E);
- break;
- case 0x0C:
- rrc_r(H);
- break;
- case 0x0D:
- rrc_r(L);
- break;
- //rrc (hl) (16 cycles):
- //Rotate 8-bit value stored at address in HL right, store old bit0 in CF. Reset SF and HCF. Check ZF:
+
+ case 0x07: rlc_r(a); break;
+
+ case 0x08: rrc_r(b); break;
+ case 0x09: rrc_r(c); break;
+ case 0x0A: rrc_r(d); break;
+ case 0x0B: rrc_r(e); break;
+ case 0x0C: rrc_r(h); break;
+ case 0x0D: rrc_r(l); break;
+
+ // rrc (hl) (16 cycles):
+ // Rotate 8-bit value stored at address in HL right, store old bit0 in CF.
+ // Reset SF and HCF. Check ZF:
case 0x0E:
{
- const unsigned addr = HL();
-
- READ(ZF, addr);
-
- CF = ZF << 8;
-
- WRITE(addr, (ZF | CF) >> 1 & 0xFF);
-
- HF2 = 0;
+ unsigned const addr = hl();
+ READ(zf, addr);
+ cf = zf << 8;
+ WRITE(addr, (zf | cf) >> 1 & 0xFF);
+ hf2 = 0;
}
+
break;
- case 0x0F:
- rrc_r(A);
- break;
- case 0x10:
- rl_r(B);
- break;
- case 0x11:
- rl_r(C);
- break;
- case 0x12:
- rl_r(D);
- break;
- case 0x13:
- rl_r(E);
- break;
- case 0x14:
- rl_r(H);
- break;
- case 0x15:
- rl_r(L);
- break;
- //rl (hl) (16 cycles):
- //Rotate 8-bit value stored at address in HL left thorugh CF, store old bit7 in CF, old CF value becoms bit0. Reset SF and HCF. Check ZF:
+
+ case 0x0F: rrc_r(a); break;
+
+ case 0x10: rl_r(b); break;
+ case 0x11: rl_r(c); break;
+ case 0x12: rl_r(d); break;
+ case 0x13: rl_r(e); break;
+ case 0x14: rl_r(h); break;
+ case 0x15: rl_r(l); break;
+
+ // rl (hl) (16 cycles):
+ // Rotate 8-bit value stored at address in HL left thorugh CF,
+ // store old bit7 in CF, old CF value becoms bit0. Reset SF and HCF. Check ZF:
case 0x16:
{
- const unsigned addr = HL();
- const unsigned oldcf = CF >> 8 & 1;
-
- READ(CF, addr);
- CF <<= 1;
-
- ZF = CF | oldcf;
-
- WRITE(addr, ZF & 0xFF);
-
- HF2 = 0;
+ unsigned const addr = hl();
+ unsigned const oldcf = cf >> 8 & 1;
+ READ(cf, addr);
+ cf <<= 1;
+ zf = cf | oldcf;
+ WRITE(addr, zf & 0xFF);
+ hf2 = 0;
}
break;
- case 0x17:
- rl_r(A);
- break;
- case 0x18:
- rr_r(B);
- break;
- case 0x19:
- rr_r(C);
- break;
- case 0x1A:
- rr_r(D);
- break;
- case 0x1B:
- rr_r(E);
- break;
- case 0x1C:
- rr_r(H);
- break;
- case 0x1D:
- rr_r(L);
- break;
- //rr (hl) (16 cycles):
- //Rotate 8-bit value stored at address in HL right thorugh CF, store old bit0 in CF, old CF value becoms bit7. Reset SF and HCF. Check ZF:
+
+ case 0x17: rl_r(a); break;
+
+ case 0x18: rr_r(b); break;
+ case 0x19: rr_r(c); break;
+ case 0x1A: rr_r(d); break;
+ case 0x1B: rr_r(e); break;
+ case 0x1C: rr_r(h); break;
+ case 0x1D: rr_r(l); break;
+
+ // rr (hl) (16 cycles):
+ // Rotate 8-bit value stored at address in HL right thorugh CF,
+ // store old bit0 in CF, old CF value becoms bit7. Reset SF and HCF. Check ZF:
case 0x1E:
{
- const unsigned addr = HL();
-
- READ(ZF, addr);
-
- const unsigned oldcf = CF & 0x100;
- CF = ZF << 8;
- ZF = (ZF | oldcf) >> 1;
-
- WRITE(addr, ZF);
-
- HF2 = 0;
+ unsigned const addr = hl();
+ READ(zf, addr);
+
+ unsigned const oldcf = cf & 0x100;
+ cf = zf << 8;
+ zf = (zf | oldcf) >> 1;
+ WRITE(addr, zf);
+ hf2 = 0;
}
+
break;
- case 0x1F:
- rr_r(A);
- break;
- case 0x20:
- sla_r(B);
- break;
- case 0x21:
- sla_r(C);
- break;
- case 0x22:
- sla_r(D);
- break;
- case 0x23:
- sla_r(E);
- break;
- case 0x24:
- sla_r(H);
- break;
- case 0x25:
- sla_r(L);
- break;
- //sla (hl) (16 cycles):
- //Shift 8-bit value stored at address in HL left, store old bit7 in CF. Reset SF and HCF. Check ZF:
+
+ case 0x1F: rr_r(a); break;
+
+ case 0x20: sla_r(b); break;
+ case 0x21: sla_r(c); break;
+ case 0x22: sla_r(d); break;
+ case 0x23: sla_r(e); break;
+ case 0x24: sla_r(h); break;
+ case 0x25: sla_r(l); break;
+
+ // sla (hl) (16 cycles):
+ // Shift 8-bit value stored at address in HL left, store old bit7 in CF.
+ // Reset SF and HCF. Check ZF:
case 0x26:
{
- const unsigned addr = HL();
-
- READ(CF, addr);
- CF <<= 1;
-
- ZF = CF;
-
- WRITE(addr, ZF & 0xFF);
-
- HF2 = 0;
+ unsigned const addr = hl();
+ READ(cf, addr);
+ cf <<= 1;
+ zf = cf;
+ WRITE(addr, zf & 0xFF);
+ hf2 = 0;
}
+
break;
- case 0x27:
- sla_r(A);
- break;
- case 0x28:
- sra_r(B);
- break;
- case 0x29:
- sra_r(C);
- break;
- case 0x2A:
- sra_r(D);
- break;
- case 0x2B:
- sra_r(E);
- break;
- case 0x2C:
- sra_r(H);
- break;
- case 0x2D:
- sra_r(L);
- break;
- //sra (hl) (16 cycles):
- //Shift 8-bit value stored at address in HL right, store old bit0 in CF, bit7=old bit7. Reset SF and HCF. Check ZF:
+
+ case 0x27: sla_r(a); break;
+
+ case 0x28: sra_r(b); break;
+ case 0x29: sra_r(c); break;
+ case 0x2A: sra_r(d); break;
+ case 0x2B: sra_r(e); break;
+ case 0x2C: sra_r(h); break;
+ case 0x2D: sra_r(l); break;
+
+ // sra (hl) (16 cycles):
+ // Shift 8-bit value stored at address in HL right, store old bit0 in CF,
+ // bit7=old bit7. Reset SF and HCF. Check ZF:
case 0x2E:
{
- const unsigned addr = HL();
-
- READ(CF, addr);
-
- ZF = CF >> 1;
-
- WRITE(addr, ZF | (CF & 0x80));
-
- CF <<= 8;
- HF2 = 0;
+ unsigned const addr = hl();
+ READ(cf, addr);
+ zf = cf >> 1;
+ WRITE(addr, zf | (cf & 0x80));
+ cf <<= 8;
+ hf2 = 0;
}
+
break;
- case 0x2F:
- sra_r(A);
- break;
- case 0x30:
- swap_r(B);
- break;
- case 0x31:
- swap_r(C);
- break;
- case 0x32:
- swap_r(D);
- break;
- case 0x33:
- swap_r(E);
- break;
- case 0x34:
- swap_r(H);
- break;
- case 0x35:
- swap_r(L);
- break;
- //swap (hl) (16 cycles):
- //Swap upper and lower nibbles of 8-bit value stored at address in HL, reset flags, check zero flag:
+
+ case 0x2F: sra_r(a); break;
+
+ case 0x30: swap_r(b); break;
+ case 0x31: swap_r(c); break;
+ case 0x32: swap_r(d); break;
+ case 0x33: swap_r(e); break;
+ case 0x34: swap_r(h); break;
+ case 0x35: swap_r(l); break;
+
+ // swap (hl) (16 cycles):
+ // Swap upper and lower nibbles of 8-bit value stored at address in HL,
+ // reset flags, check zero flag:
case 0x36:
{
- const unsigned addr = HL();
-
- READ(ZF, addr);
-
- WRITE(addr, (ZF << 4 | ZF >> 4) & 0xFF);
-
- CF = HF2 = 0;
+ unsigned const addr = hl();
+ READ(zf, addr);
+ WRITE(addr, (zf << 4 | zf >> 4) & 0xFF);
+ cf = hf2 = 0;
}
+
break;
- case 0x37:
- swap_r(A);
- break;
- case 0x38:
- srl_r(B);
- break;
- case 0x39:
- srl_r(C);
- break;
- case 0x3A:
- srl_r(D);
- break;
- case 0x3B:
- srl_r(E);
- break;
- case 0x3C:
- srl_r(H);
- break;
- case 0x3D:
- srl_r(L);
- break;
- //srl (hl) (16 cycles):
- //Shift 8-bit value stored at address in HL right, store old bit0 in CF. Reset SF and HCF. Check ZF:
+
+ case 0x37: swap_r(a); break;
+
+ case 0x38: srl_r(b); break;
+ case 0x39: srl_r(c); break;
+ case 0x3A: srl_r(d); break;
+ case 0x3B: srl_r(e); break;
+ case 0x3C: srl_r(h); break;
+ case 0x3D: srl_r(l); break;
+
+ // srl (hl) (16 cycles):
+ // Shift 8-bit value stored at address in HL right,
+ // store old bit0 in CF. Reset SF and HCF. Check ZF:
case 0x3E:
{
- const unsigned addr = HL();
-
- READ(CF, addr);
-
- ZF = CF >> 1;
-
- WRITE(addr, ZF);
-
- CF <<= 8;
- HF2 = 0;
+ unsigned const addr = hl();
+ READ(cf, addr);
+ zf = cf >> 1;
+ WRITE(addr, zf);
+ cf <<= 8;
+ hf2 = 0;
}
- break;
- case 0x3F:
- srl_r(A);
- break;
- case 0x40:
- bit0_u8(B);
- break;
- case 0x41:
- bit0_u8(C);
- break;
- case 0x42:
- bit0_u8(D);
- break;
- case 0x43:
- bit0_u8(E);
- break;
- case 0x44:
- bit0_u8(H);
- break;
- case 0x45:
- bit0_u8(L);
- break;
- case 0x46:
- {
- unsigned data;
-
- READ(data, HL());
-
- bit0_u8(data);
- }
- break;
- case 0x47:
- bit0_u8(A);
- break;
- case 0x48:
- bit1_u8(B);
- break;
- case 0x49:
- bit1_u8(C);
- break;
- case 0x4A:
- bit1_u8(D);
- break;
- case 0x4B:
- bit1_u8(E);
- break;
- case 0x4C:
- bit1_u8(H);
- break;
- case 0x4D:
- bit1_u8(L);
- break;
- case 0x4E:
- {
- unsigned data;
-
- READ(data, HL());
-
- bit1_u8(data);
- }
- break;
- case 0x4F:
- bit1_u8(A);
- break;
- case 0x50:
- bit2_u8(B);
- break;
- case 0x51:
- bit2_u8(C);
- break;
- case 0x52:
- bit2_u8(D);
- break;
- case 0x53:
- bit2_u8(E);
- break;
- case 0x54:
- bit2_u8(H);
- break;
- case 0x55:
- bit2_u8(L);
- break;
- case 0x56:
- {
- unsigned data;
-
- READ(data, HL());
-
- bit2_u8(data);
- }
- break;
- case 0x57:
- bit2_u8(A);
- break;
- case 0x58:
- bit3_u8(B);
- break;
- case 0x59:
- bit3_u8(C);
- break;
- case 0x5A:
- bit3_u8(D);
- break;
- case 0x5B:
- bit3_u8(E);
- break;
- case 0x5C:
- bit3_u8(H);
- break;
- case 0x5D:
- bit3_u8(L);
- break;
- case 0x5E:
- {
- unsigned data;
-
- READ(data, HL());
-
- bit3_u8(data);
- }
- break;
- case 0x5F:
- bit3_u8(A);
- break;
- case 0x60:
- bit4_u8(B);
- break;
- case 0x61:
- bit4_u8(C);
- break;
- case 0x62:
- bit4_u8(D);
- break;
- case 0x63:
- bit4_u8(E);
- break;
- case 0x64:
- bit4_u8(H);
- break;
- case 0x65:
- bit4_u8(L);
- break;
- case 0x66:
- {
- unsigned data;
-
- READ(data, HL());
-
- bit4_u8(data);
- }
- break;
- case 0x67:
- bit4_u8(A);
- break;
- case 0x68:
- bit5_u8(B);
- break;
- case 0x69:
- bit5_u8(C);
- break;
- case 0x6A:
- bit5_u8(D);
- break;
- case 0x6B:
- bit5_u8(E);
- break;
- case 0x6C:
- bit5_u8(H);
- break;
- case 0x6D:
- bit5_u8(L);
- break;
- case 0x6E:
- {
- unsigned data;
-
- READ(data, HL());
-
- bit5_u8(data);
- }
- break;
- case 0x6F:
- bit5_u8(A);
- break;
- case 0x70:
- bit6_u8(B);
- break;
- case 0x71:
- bit6_u8(C);
- break;
- case 0x72:
- bit6_u8(D);
- break;
- case 0x73:
- bit6_u8(E);
- break;
- case 0x74:
- bit6_u8(H);
- break;
- case 0x75:
- bit6_u8(L);
- break;
- case 0x76:
- {
- unsigned data;
-
- READ(data, HL());
-
- bit6_u8(data);
- }
- break;
- case 0x77:
- bit6_u8(A);
- break;
- case 0x78:
- bit7_u8(B);
- break;
- case 0x79:
- bit7_u8(C);
- break;
- case 0x7A:
- bit7_u8(D);
- break;
- case 0x7B:
- bit7_u8(E);
- break;
- case 0x7C:
- bit7_u8(H);
- break;
- case 0x7D:
- bit7_u8(L);
- break;
- case 0x7E:
- {
- unsigned data;
-
- READ(data, HL());
-
- bit7_u8(data);
- }
- break;
- case 0x7F:
- bit7_u8(A);
- break;
- case 0x80:
- res0_r(B);
- break;
- case 0x81:
- res0_r(C);
- break;
- case 0x82:
- res0_r(D);
- break;
- case 0x83:
- res0_r(E);
- break;
- case 0x84:
- res0_r(H);
- break;
- case 0x85:
- res0_r(L);
- break;
- case 0x86:
- resn_mem_hl(0);
- break;
- case 0x87:
- res0_r(A);
- break;
- case 0x88:
- res1_r(B);
- break;
- case 0x89:
- res1_r(C);
- break;
- case 0x8A:
- res1_r(D);
- break;
- case 0x8B:
- res1_r(E);
- break;
- case 0x8C:
- res1_r(H);
- break;
- case 0x8D:
- res1_r(L);
- break;
- case 0x8E:
- resn_mem_hl(1);
- break;
- case 0x8F:
- res1_r(A);
- break;
- case 0x90:
- res2_r(B);
- break;
- case 0x91:
- res2_r(C);
- break;
- case 0x92:
- res2_r(D);
- break;
- case 0x93:
- res2_r(E);
- break;
- case 0x94:
- res2_r(H);
- break;
- case 0x95:
- res2_r(L);
- break;
- case 0x96:
- resn_mem_hl(2);
- break;
- case 0x97:
- res2_r(A);
- break;
- case 0x98:
- res3_r(B);
- break;
- case 0x99:
- res3_r(C);
- break;
- case 0x9A:
- res3_r(D);
- break;
- case 0x9B:
- res3_r(E);
- break;
- case 0x9C:
- res3_r(H);
- break;
- case 0x9D:
- res3_r(L);
- break;
- case 0x9E:
- resn_mem_hl(3);
- break;
- case 0x9F:
- res3_r(A);
- break;
- case 0xA0:
- res4_r(B);
- break;
- case 0xA1:
- res4_r(C);
- break;
- case 0xA2:
- res4_r(D);
- break;
- case 0xA3:
- res4_r(E);
- break;
- case 0xA4:
- res4_r(H);
- break;
- case 0xA5:
- res4_r(L);
- break;
- case 0xA6:
- resn_mem_hl(4);
- break;
- case 0xA7:
- res4_r(A);
- break;
- case 0xA8:
- res5_r(B);
- break;
- case 0xA9:
- res5_r(C);
- break;
- case 0xAA:
- res5_r(D);
- break;
- case 0xAB:
- res5_r(E);
- break;
- case 0xAC:
- res5_r(H);
- break;
- case 0xAD:
- res5_r(L);
- break;
- case 0xAE:
- resn_mem_hl(5);
- break;
- case 0xAF:
- res5_r(A);
- break;
- case 0xB0:
- res6_r(B);
- break;
- case 0xB1:
- res6_r(C);
- break;
- case 0xB2:
- res6_r(D);
- break;
- case 0xB3:
- res6_r(E);
- break;
- case 0xB4:
- res6_r(H);
- break;
- case 0xB5:
- res6_r(L);
- break;
- case 0xB6:
- resn_mem_hl(6);
- break;
- case 0xB7:
- res6_r(A);
- break;
- case 0xB8:
- res7_r(B);
- break;
- case 0xB9:
- res7_r(C);
- break;
- case 0xBA:
- res7_r(D);
- break;
- case 0xBB:
- res7_r(E);
- break;
- case 0xBC:
- res7_r(H);
- break;
- case 0xBD:
- res7_r(L);
- break;
- case 0xBE:
- resn_mem_hl(7);
- break;
- case 0xBF:
- res7_r(A);
- break;
- case 0xC0:
- set0_r(B);
- break;
- case 0xC1:
- set0_r(C);
- break;
- case 0xC2:
- set0_r(D);
- break;
- case 0xC3:
- set0_r(E);
- break;
- case 0xC4:
- set0_r(H);
- break;
- case 0xC5:
- set0_r(L);
- break;
- case 0xC6:
- setn_mem_hl(0);
- break;
- case 0xC7:
- set0_r(A);
- break;
- case 0xC8:
- set1_r(B);
- break;
- case 0xC9:
- set1_r(C);
- break;
- case 0xCA:
- set1_r(D);
- break;
- case 0xCB:
- set1_r(E);
- break;
- case 0xCC:
- set1_r(H);
- break;
- case 0xCD:
- set1_r(L);
- break;
- case 0xCE:
- setn_mem_hl(1);
- break;
- case 0xCF:
- set1_r(A);
- break;
- case 0xD0:
- set2_r(B);
- break;
- case 0xD1:
- set2_r(C);
- break;
- case 0xD2:
- set2_r(D);
- break;
- case 0xD3:
- set2_r(E);
- break;
- case 0xD4:
- set2_r(H);
- break;
- case 0xD5:
- set2_r(L);
- break;
- case 0xD6:
- setn_mem_hl(2);
- break;
- case 0xD7:
- set2_r(A);
- break;
- case 0xD8:
- set3_r(B);
- break;
- case 0xD9:
- set3_r(C);
- break;
- case 0xDA:
- set3_r(D);
- break;
- case 0xDB:
- set3_r(E);
- break;
- case 0xDC:
- set3_r(H);
- break;
- case 0xDD:
- set3_r(L);
- break;
- case 0xDE:
- setn_mem_hl(3);
- break;
- case 0xDF:
- set3_r(A);
- break;
- case 0xE0:
- set4_r(B);
- break;
- case 0xE1:
- set4_r(C);
- break;
- case 0xE2:
- set4_r(D);
- break;
- case 0xE3:
- set4_r(E);
- break;
- case 0xE4:
- set4_r(H);
- break;
- case 0xE5:
- set4_r(L);
- break;
- case 0xE6:
- setn_mem_hl(4);
- break;
- case 0xE7:
- set4_r(A);
- break;
- case 0xE8:
- set5_r(B);
- break;
- case 0xE9:
- set5_r(C);
- break;
- case 0xEA:
- set5_r(D);
- break;
- case 0xEB:
- set5_r(E);
- break;
- case 0xEC:
- set5_r(H);
- break;
- case 0xED:
- set5_r(L);
- break;
- case 0xEE:
- setn_mem_hl(5);
- break;
- case 0xEF:
- set5_r(A);
- break;
- case 0xF0:
- set6_r(B);
- break;
- case 0xF1:
- set6_r(C);
- break;
- case 0xF2:
- set6_r(D);
- break;
- case 0xF3:
- set6_r(E);
- break;
- case 0xF4:
- set6_r(H);
- break;
- case 0xF5:
- set6_r(L);
- break;
- case 0xF6:
- setn_mem_hl(6);
- break;
- case 0xF7:
- set6_r(A);
- break;
- case 0xF8:
- set7_r(B);
- break;
- case 0xF9:
- set7_r(C);
- break;
- case 0xFA:
- set7_r(D);
- break;
- case 0xFB:
- set7_r(E);
- break;
- case 0xFC:
- set7_r(H);
- break;
- case 0xFD:
- set7_r(L);
- break;
- case 0xFE:
- setn_mem_hl(7);
- break;
- case 0xFF:
- set7_r(A);
- break;
-// default: break;
+
+ break;
+
+ case 0x3F: srl_r(a); break;
+
+ case 0x40: bit0_u8(b); break;
+ case 0x41: bit0_u8(c); break;
+ case 0x42: bit0_u8(d); break;
+ case 0x43: bit0_u8(e); break;
+ case 0x44: bit0_u8(h); break;
+ case 0x45: bit0_u8(l); break;
+ case 0x46: { unsigned data; READ(data, hl()); bit0_u8(data); } break;
+ case 0x47: bit0_u8(a); break;
+
+ case 0x48: bit1_u8(b); break;
+ case 0x49: bit1_u8(c); break;
+ case 0x4A: bit1_u8(d); break;
+ case 0x4B: bit1_u8(e); break;
+ case 0x4C: bit1_u8(h); break;
+ case 0x4D: bit1_u8(l); break;
+ case 0x4E: { unsigned data; READ(data, hl()); bit1_u8(data); } break;
+ case 0x4F: bit1_u8(a); break;
+
+ case 0x50: bit2_u8(b); break;
+ case 0x51: bit2_u8(c); break;
+ case 0x52: bit2_u8(d); break;
+ case 0x53: bit2_u8(e); break;
+ case 0x54: bit2_u8(h); break;
+ case 0x55: bit2_u8(l); break;
+ case 0x56: { unsigned data; READ(data, hl()); bit2_u8(data); } break;
+ case 0x57: bit2_u8(a); break;
+
+ case 0x58: bit3_u8(b); break;
+ case 0x59: bit3_u8(c); break;
+ case 0x5A: bit3_u8(d); break;
+ case 0x5B: bit3_u8(e); break;
+ case 0x5C: bit3_u8(h); break;
+ case 0x5D: bit3_u8(l); break;
+ case 0x5E: { unsigned data; READ(data, hl()); bit3_u8(data); } break;
+ case 0x5F: bit3_u8(a); break;
+
+ case 0x60: bit4_u8(b); break;
+ case 0x61: bit4_u8(c); break;
+ case 0x62: bit4_u8(d); break;
+ case 0x63: bit4_u8(e); break;
+ case 0x64: bit4_u8(h); break;
+ case 0x65: bit4_u8(l); break;
+ case 0x66: { unsigned data; READ(data, hl()); bit4_u8(data); } break;
+ case 0x67: bit4_u8(a); break;
+
+ case 0x68: bit5_u8(b); break;
+ case 0x69: bit5_u8(c); break;
+ case 0x6A: bit5_u8(d); break;
+ case 0x6B: bit5_u8(e); break;
+ case 0x6C: bit5_u8(h); break;
+ case 0x6D: bit5_u8(l); break;
+ case 0x6E: { unsigned data; READ(data, hl()); bit5_u8(data); } break;
+ case 0x6F: bit5_u8(a); break;
+
+ case 0x70: bit6_u8(b); break;
+ case 0x71: bit6_u8(c); break;
+ case 0x72: bit6_u8(d); break;
+ case 0x73: bit6_u8(e); break;
+ case 0x74: bit6_u8(h); break;
+ case 0x75: bit6_u8(l); break;
+ case 0x76: { unsigned data; READ(data, hl()); bit6_u8(data); } break;
+ case 0x77: bit6_u8(a); break;
+
+ case 0x78: bit7_u8(b); break;
+ case 0x79: bit7_u8(c); break;
+ case 0x7A: bit7_u8(d); break;
+ case 0x7B: bit7_u8(e); break;
+ case 0x7C: bit7_u8(h); break;
+ case 0x7D: bit7_u8(l); break;
+ case 0x7E: { unsigned data; READ(data, hl()); bit7_u8(data); } break;
+ case 0x7F: bit7_u8(a); break;
+
+ case 0x80: res0_r(b); break;
+ case 0x81: res0_r(c); break;
+ case 0x82: res0_r(d); break;
+ case 0x83: res0_r(e); break;
+ case 0x84: res0_r(h); break;
+ case 0x85: res0_r(l); break;
+ case 0x86: resn_mem_hl(0); break;
+ case 0x87: res0_r(a); break;
+
+ case 0x88: res1_r(b); break;
+ case 0x89: res1_r(c); break;
+ case 0x8A: res1_r(d); break;
+ case 0x8B: res1_r(e); break;
+ case 0x8C: res1_r(h); break;
+ case 0x8D: res1_r(l); break;
+ case 0x8E: resn_mem_hl(1); break;
+ case 0x8F: res1_r(a); break;
+
+ case 0x90: res2_r(b); break;
+ case 0x91: res2_r(c); break;
+ case 0x92: res2_r(d); break;
+ case 0x93: res2_r(e); break;
+ case 0x94: res2_r(h); break;
+ case 0x95: res2_r(l); break;
+ case 0x96: resn_mem_hl(2); break;
+ case 0x97: res2_r(a); break;
+
+ case 0x98: res3_r(b); break;
+ case 0x99: res3_r(c); break;
+ case 0x9A: res3_r(d); break;
+ case 0x9B: res3_r(e); break;
+ case 0x9C: res3_r(h); break;
+ case 0x9D: res3_r(l); break;
+ case 0x9E: resn_mem_hl(3); break;
+ case 0x9F: res3_r(a); break;
+
+ case 0xA0: res4_r(b); break;
+ case 0xA1: res4_r(c); break;
+ case 0xA2: res4_r(d); break;
+ case 0xA3: res4_r(e); break;
+ case 0xA4: res4_r(h); break;
+ case 0xA5: res4_r(l); break;
+ case 0xA6: resn_mem_hl(4); break;
+ case 0xA7: res4_r(a); break;
+
+ case 0xA8: res5_r(b); break;
+ case 0xA9: res5_r(c); break;
+ case 0xAA: res5_r(d); break;
+ case 0xAB: res5_r(e); break;
+ case 0xAC: res5_r(h); break;
+ case 0xAD: res5_r(l); break;
+ case 0xAE: resn_mem_hl(5); break;
+ case 0xAF: res5_r(a); break;
+
+ case 0xB0: res6_r(b); break;
+ case 0xB1: res6_r(c); break;
+ case 0xB2: res6_r(d); break;
+ case 0xB3: res6_r(e); break;
+ case 0xB4: res6_r(h); break;
+ case 0xB5: res6_r(l); break;
+ case 0xB6: resn_mem_hl(6); break;
+ case 0xB7: res6_r(a); break;
+
+ case 0xB8: res7_r(b); break;
+ case 0xB9: res7_r(c); break;
+ case 0xBA: res7_r(d); break;
+ case 0xBB: res7_r(e); break;
+ case 0xBC: res7_r(h); break;
+ case 0xBD: res7_r(l); break;
+ case 0xBE: resn_mem_hl(7); break;
+ case 0xBF: res7_r(a); break;
+
+ case 0xC0: set0_r(b); break;
+ case 0xC1: set0_r(c); break;
+ case 0xC2: set0_r(d); break;
+ case 0xC3: set0_r(e); break;
+ case 0xC4: set0_r(h); break;
+ case 0xC5: set0_r(l); break;
+ case 0xC6: setn_mem_hl(0); break;
+ case 0xC7: set0_r(a); break;
+
+ case 0xC8: set1_r(b); break;
+ case 0xC9: set1_r(c); break;
+ case 0xCA: set1_r(d); break;
+ case 0xCB: set1_r(e); break;
+ case 0xCC: set1_r(h); break;
+ case 0xCD: set1_r(l); break;
+ case 0xCE: setn_mem_hl(1); break;
+ case 0xCF: set1_r(a); break;
+
+ case 0xD0: set2_r(b); break;
+ case 0xD1: set2_r(c); break;
+ case 0xD2: set2_r(d); break;
+ case 0xD3: set2_r(e); break;
+ case 0xD4: set2_r(h); break;
+ case 0xD5: set2_r(l); break;
+ case 0xD6: setn_mem_hl(2); break;
+ case 0xD7: set2_r(a); break;
+
+ case 0xD8: set3_r(b); break;
+ case 0xD9: set3_r(c); break;
+ case 0xDA: set3_r(d); break;
+ case 0xDB: set3_r(e); break;
+ case 0xDC: set3_r(h); break;
+ case 0xDD: set3_r(l); break;
+ case 0xDE: setn_mem_hl(3); break;
+ case 0xDF: set3_r(a); break;
+
+ case 0xE0: set4_r(b); break;
+ case 0xE1: set4_r(c); break;
+ case 0xE2: set4_r(d); break;
+ case 0xE3: set4_r(e); break;
+ case 0xE4: set4_r(h); break;
+ case 0xE5: set4_r(l); break;
+ case 0xE6: setn_mem_hl(4); break;
+ case 0xE7: set4_r(a); break;
+
+ case 0xE8: set5_r(b); break;
+ case 0xE9: set5_r(c); break;
+ case 0xEA: set5_r(d); break;
+ case 0xEB: set5_r(e); break;
+ case 0xEC: set5_r(h); break;
+ case 0xED: set5_r(l); break;
+ case 0xEE: setn_mem_hl(5); break;
+ case 0xEF: set5_r(a); break;
+
+ case 0xF0: set6_r(b); break;
+ case 0xF1: set6_r(c); break;
+ case 0xF2: set6_r(d); break;
+ case 0xF3: set6_r(e); break;
+ case 0xF4: set6_r(h); break;
+ case 0xF5: set6_r(l); break;
+ case 0xF6: setn_mem_hl(6); break;
+ case 0xF7: set6_r(a); break;
+
+ case 0xF8: set7_r(b); break;
+ case 0xF9: set7_r(c); break;
+ case 0xFA: set7_r(d); break;
+ case 0xFB: set7_r(e); break;
+ case 0xFC: set7_r(h); break;
+ case 0xFD: set7_r(l); break;
+ case 0xFE: setn_mem_hl(7); break;
+ case 0xFF: set7_r(a); break;
}
+
break;
- //call z,nn (24;12 cycles):
- //Push address of next instruction onto stack and then jump to address stored in next two bytes in memory, if ZF is set:
+ // call z,nn (24;12 cycles):
+ // Push address of next instruction onto stack and then jump to
+ // address stored in next two bytes in memory, if ZF is set:
case 0xCC:
- if (ZF & 0xFF) {
- PC_MOD((PC + 2) & 0xFFFF);
+ if (zf & 0xFF) {
+ PC_MOD((pc + 2) & 0xFFFF);
cycleCounter += 4;
} else {
call_nn();
}
+
break;
case 0xCD:
call_nn();
break;
+
case 0xCE:
{
unsigned data;
-
PC_READ(data);
-
adc_a_u8(data);
}
+
break;
+
case 0xCF:
rst_n(0x08);
break;
- //ret nc (20;8 cycles):
- //Pop two bytes from the stack and jump to that address, if CF is unset:
+ // ret nc (20;8 cycles):
+ // Pop two bytes from the stack and jump to that address, if CF is unset:
case 0xD0:
cycleCounter += 4;
-
- if (!(CF & 0x100)) {
+
+ if (!(cf & 0x100))
ret();
- }
-
+
break;
case 0xD1:
- pop_rr(D, E);
+ pop_rr(d, e);
break;
- //jp nc,nn (16;12 cycles):
- //Jump to address stored in next two bytes in memory if CF is unset:
+ // jp nc,nn (16;12 cycles):
+ // Jump to address stored in next two bytes in memory if CF is unset:
case 0xD2:
- if (CF & 0x100) {
- PC_MOD((PC + 2) & 0xFFFF);
+ if (cf & 0x100) {
+ PC_MOD((pc + 2) & 0xFFFF);
cycleCounter += 4;
} else {
jp_nn();
}
+
break;
- case 0xD3: /*doesn't exist*/
- skip = true;
- memory.di();
+ case 0xD3: // not specified. should freeze.
+ mem_.di();
+ cycleCounter = mem_.stop(cycleCounter);
+
+ if (cycleCounter < mem_.nextEventTime()) {
+ unsigned long cycles = mem_.nextEventTime() - cycleCounter;
+ cycleCounter += cycles + (-cycles & 3);
+ }
break;
- //call nc,nn (24;12 cycles):
- //Push address of next instruction onto stack and then jump to address stored in next two bytes in memory, if CF is unset:
+ // call nc,nn (24;12 cycles):
+ // Push address of next instruction onto stack and then jump to
+ // address stored in next two bytes in memory, if CF is unset:
case 0xD4:
- if (CF & 0x100) {
- PC_MOD((PC + 2) & 0xFFFF);
+ if (cf & 0x100) {
+ PC_MOD((pc + 2) & 0xFFFF);
cycleCounter += 4;
} else {
call_nn();
}
+
break;
case 0xD5:
- push_rr(D, E);
+ push_rr(d, e);
break;
+
case 0xD6:
{
unsigned data;
-
PC_READ(data);
-
sub_a_u8(data);
}
+
break;
+
case 0xD7:
rst_n(0x10);
break;
- //ret c (20;8 cycles):
- //Pop two bytes from the stack and jump to that address, if CF is set:
+ // ret c (20;8 cycles):
+ // Pop two bytes from the stack and jump to that address, if CF is set:
case 0xD8:
cycleCounter += 4;
-
- if (CF & 0x100) {
+
+ if (cf & 0x100)
ret();
- }
-
+
break;
- //reti (16 cycles):
- //Pop two bytes from the stack and jump to that address, then enable interrupts:
+ // reti (16 cycles):
+ // Pop two bytes from the stack and jump to that address, then enable interrupts:
case 0xD9:
{
- unsigned l, h;
-
- pop_rr(h, l);
-
- memory.ei(cycleCounter);
-
- PC_MOD(h << 8 | l);
+ unsigned sl, sh;
+ pop_rr(sh, sl);
+ mem_.ei(cycleCounter);
+ PC_MOD(sh << 8 | sl);
}
+
break;
- //jp c,nn (16;12 cycles):
- //Jump to address stored in next two bytes in memory if CF is set:
- case 0xDA: //PC=( ((PC+2)*(1-CarryFlag())) + (((memory.read(PC+1)<<8)+memory.read(PC))*CarryFlag()) ); Cycles(12); break;
- if (CF & 0x100) {
+ // jp c,nn (16;12 cycles):
+ // Jump to address stored in next two bytes in memory if CF is set:
+ case 0xDA:
+ if (cf & 0x100) {
jp_nn();
} else {
- PC_MOD((PC + 2) & 0xFFFF);
+ PC_MOD((pc + 2) & 0xFFFF);
cycleCounter += 4;
}
+
+ break;
+
+ case 0xDB: // not specified. should freeze.
+ mem_.di();
+ cycleCounter = mem_.stop(cycleCounter);
+
+ if (cycleCounter < mem_.nextEventTime()) {
+ unsigned long cycles = mem_.nextEventTime() - cycleCounter;
+ cycleCounter += cycles + (-cycles & 3);
+ }
break;
- case 0xDB: /*doesn't exist*/
- skip = true;
- memory.di();
- break;
-
- //call z,nn (24;12 cycles):
- //Push address of next instruction onto stack and then jump to address stored in next two bytes in memory, if CF is set:
+ // call z,nn (24;12 cycles):
+ // Push address of next instruction onto stack and then jump to
+ // address stored in next two bytes in memory, if CF is set:
case 0xDC:
- if (CF & 0x100) {
+ if (cf & 0x100) {
call_nn();
} else {
- PC_MOD((PC + 2) & 0xFFFF);
+ PC_MOD((pc + 2) & 0xFFFF);
cycleCounter += 4;
}
- break;
- case 0xDD: /*doesn't exist*/
- skip = true;
- memory.di();
+ break;
+ case 0xDD: // not specified. should freeze.
+ mem_.di();
+ cycleCounter = mem_.stop(cycleCounter);
+
+ if (cycleCounter < mem_.nextEventTime()) {
+ unsigned long cycles = mem_.nextEventTime() - cycleCounter;
+ cycleCounter += cycles + (-cycles & 3);
+ }
break;
case 0xDE:
{
unsigned data;
-
PC_READ(data);
-
sbc_a_u8(data);
}
+
break;
+
case 0xDF:
rst_n(0x18);
break;
- //ld ($FF00+n),a (12 cycles):
- //Put value in A into address (0xFF00 + next byte in memory):
+ // ld ($FF00+n),a (12 cycles):
+ // Put value in A into address (0xFF00 + next byte in memory):
case 0xE0:
{
- unsigned tmp;
-
- PC_READ(tmp);
-
- FF_WRITE(0xFF00 | tmp, A);
+ unsigned imm;
+ PC_READ(imm);
+ FF_WRITE(imm, a);
}
+
break;
case 0xE1:
- pop_rr(H, L);
+ pop_rr(h, l);
break;
- //ld ($FF00+C),a (8 ycles):
- //Put A into address (0xFF00 + register C):
+ // ld ($FF00+C),a (8 ycles):
+ // Put A into address (0xFF00 + register C):
case 0xE2:
- FF_WRITE(0xFF00 | C, A);
+ FF_WRITE(c, a);
break;
- case 0xE3: /*doesn't exist*/
- skip = true;
- memory.di();
- break;
- case 0xE4: /*doesn't exist*/
- skip = true;
- memory.di();
+
+ case 0xE3:
+ case 0xE4: // not specified. should freeze.
+ mem_.di();
+ cycleCounter = mem_.stop(cycleCounter);
+
+ if (cycleCounter < mem_.nextEventTime()) {
+ unsigned long cycles = mem_.nextEventTime() - cycleCounter;
+ cycleCounter += cycles + (-cycles & 3);
+ }
break;
+
case 0xE5:
- push_rr(H, L);
+ push_rr(h, l);
break;
+
case 0xE6:
{
unsigned data;
-
PC_READ(data);
-
and_a_u8(data);
}
+
break;
+
case 0xE7:
rst_n(0x20);
break;
- //add sp,n (16 cycles):
- //Add next (signed) byte in memory to SP, reset ZF and SF, check HCF and CF:
+ // add sp,n (16 cycles):
+ // Add next (signed) byte in memory to SP, reset ZF and SF, check HCF and CF:
case 0xE8:
- /*{
- int8_t tmp = int8_t(memory.pc_read(PC++, cycleCounter));
- HF2 = (((SP & 0xFFF) + tmp) >> 3) & 0x200;
- CF = SP + tmp;
- SP = CF;
- CF >>= 8;
- ZF = 1;
- cycleCounter += 12;
- }*/
- sp_plus_n(SP);
+ sp_plus_n(sp);
cycleCounter += 4;
- break;
-
- //jp hl (4 cycles):
- //Jump to address in hl:
- case 0xE9:
- PC = HL();
break;
- //ld (nn),a (16 cycles):
- //set memory at address given by the next 2 bytes to value in A:
- //Incrementing PC before call, because of possible interrupt.
+ // jp hl (4 cycles):
+ // Jump to address in hl:
+ case 0xE9:
+ pc = hl();
+ break;
+
+ // ld (nn),a (16 cycles):
+ // set memory at address given by the next 2 bytes to value in A:
+ // Incrementing PC before call, because of possible interrupt.
case 0xEA:
{
- unsigned l, h;
-
- PC_READ(l);
- PC_READ(h);
-
- WRITE(h << 8 | l, A);
+ unsigned imml, immh;
+ PC_READ(imml);
+ PC_READ(immh);
+ WRITE(immh << 8 | imml, a);
+ }
+
+ break;
+
+ case 0xEB:
+ case 0xEC:
+ case 0xED: // not specified. should freeze.
+ mem_.di();
+ cycleCounter = mem_.stop(cycleCounter);
+
+ if (cycleCounter < mem_.nextEventTime()) {
+ unsigned long cycles = mem_.nextEventTime() - cycleCounter;
+ cycleCounter += cycles + (-cycles & 3);
}
break;
- case 0xEB: /*doesn't exist*/
- skip = true;
- memory.di();
- break;
- case 0xEC: /*doesn't exist*/
- skip = true;
- memory.di();
- break;
- case 0xED: /*doesn't exist*/
- skip = true;
- memory.di();
- break;
case 0xEE:
{
unsigned data;
-
PC_READ(data);
-
xor_a_u8(data);
}
+
break;
+
case 0xEF:
rst_n(0x28);
break;
- //ld a,($FF00+n) (12 cycles):
- //Put value at address (0xFF00 + next byte in memory) into A:
+ // ld a,($FF00+n) (12 cycles):
+ // Put value at address (0xFF00 + next byte in memory) into A:
case 0xF0:
{
- unsigned tmp;
-
- PC_READ(tmp);
-
- FF_READ(A, 0xFF00 | tmp);
+ unsigned imm;
+ PC_READ(imm);
+ FF_READ(a, imm);
}
+
break;
- case 0xF1: /*pop_rr(A, F); Cycles(12); break;*/
+ case 0xF1:
{
unsigned F;
-
- pop_rr(A, F);
-
- FROM_F(F);
+ pop_rr(a, F);
+ zf = zfFromF(F);
+ hf2 = hf2FromF(F);
+ cf = cfFromF(F);
}
+
break;
- //ld a,($FF00+C) (8 cycles):
- //Put value at address (0xFF00 + register C) into A:
+ // ld a,($FF00+C) (8 cycles):
+ // Put value at address (0xFF00 + register C) into A:
case 0xF2:
- FF_READ(A, 0xFF00 | C);
+ FF_READ(a, c);
break;
- //di (4 cycles):
+ // di (4 cycles):
case 0xF3:
- memory.di();
+ mem_.di();
break;
- case 0xF4: /*doesn't exist*/
- skip = true;
- memory.di();
- break;
- case 0xF5: /*push_rr(A, F); Cycles(16); break;*/
- calcHF(HF1, HF2);
-
- {
- unsigned F = F();
-
- push_rr(A, F);
+ case 0xF4: // not specified. should freeze.
+ mem_.di();
+ cycleCounter = mem_.stop(cycleCounter);
+
+ if (cycleCounter < mem_.nextEventTime()) {
+ unsigned long cycles = mem_.nextEventTime() - cycleCounter;
+ cycleCounter += cycles + (-cycles & 3);
}
break;
+ case 0xF5:
+ hf2 = updateHf2FromHf1(hf1, hf2);
+
+ {
+ unsigned F = toF(hf2, cf, zf);
+ push_rr(a, F);
+ }
+
+ break;
+
case 0xF6:
{
unsigned data;
-
PC_READ(data);
-
or_a_u8(data);
}
+
break;
+
case 0xF7:
rst_n(0x30);
break;
- //ldhl sp,n (12 cycles):
- //Put (sp+next (signed) byte in memory) into hl (unsets ZF and SF, may enable HF and CF):
+ // ldhl sp,n (12 cycles):
+ // Put (sp+next (signed) byte in memory) into hl (unsets ZF and SF, may enable HF and CF):
case 0xF8:
- /*{
- int8_t tmp = int8_t(memory.pc_read(PC++, cycleCounter));
- HF2 = (((SP & 0xFFF) + tmp) >> 3) & 0x200;
- CF = SP + tmp;
- L = CF;
- CF >>= 8;
- H = CF;
- ZF = 1;
- cycleCounter += 8;
- }*/
{
unsigned sum;
sp_plus_n(sum);
- L = sum & 0xFF;
- H = sum >> 8;
+ l = sum & 0xFF;
+ h = sum >> 8;
}
+
break;
- //ld sp,hl (8 cycles):
- //Put value in HL into SP
+ // ld sp,hl (8 cycles):
+ // Put value in HL into SP
case 0xF9:
- SP = HL();
+ sp = hl();
cycleCounter += 4;
break;
- //ld a,(nn) (16 cycles):
- //set A to value in memory at address given by the 2 next bytes.
+ // ld a,(nn) (16 cycles):
+ // set A to value in memory at address given by the 2 next bytes.
case 0xFA:
{
- unsigned l, h;
-
- PC_READ(l);
- PC_READ(h);
-
- READ(A, h << 8 | l);
+ unsigned imml, immh;
+ PC_READ(imml);
+ PC_READ(immh);
+
+ READ(a, immh << 8 | imml);
}
+
break;
- //ei (4 cycles):
- //Enable Interrupts after next instruction:
+ // ei (4 cycles):
+ // Enable Interrupts after next instruction:
case 0xFB:
- memory.ei(cycleCounter);
+ mem_.ei(cycleCounter);
break;
- case 0xFC: /*doesn't exist*/
- skip = true;
- memory.di();
- break;
- case 0xFD: /*doesn't exist*/
- skip = true;
- memory.di();
+ case 0xFC:
+ case 0xFD: // not specified. should freeze
+ mem_.di();
+ cycleCounter = mem_.stop(cycleCounter);
+
+ if (cycleCounter < mem_.nextEventTime()) {
+ unsigned long cycles = mem_.nextEventTime() - cycleCounter;
+ cycleCounter += cycles + (-cycles & 3);
+ }
break;
case 0xFE:
{
unsigned data;
-
PC_READ(data);
-
+
cp_a_u8(data);
}
+
break;
+
case 0xFF:
rst_n(0x38);
break;
-// default: break;
}
}
-
- //PC_ = PC;
- cycleCounter = memory.event(cycleCounter);
+
+ //pc_ = pc;
+ cycleCounter = mem_.event(cycleCounter);
}
-
- //A_ = A;
+
+ //a_ = a;
cycleCounter_ = cycleCounter;
}
-void CPU::GetRegs(int *dest)
-{
- dest[0] = PC;
- dest[1] = SP;
- dest[2] = A;
- dest[3] = B;
- dest[4] = C;
- dest[5] = D;
- dest[6] = E;
- dest[7] = F();
- dest[8] = H;
- dest[9] = L;
+void CPU::getRegs(int *dest) {
+ hf2 = updateHf2FromHf1(hf1, hf2);
+
+ dest[0] = pc;
+ dest[1] = sp;
+ dest[2] = a;
+ dest[3] = b;
+ dest[4] = c;
+ dest[5] = d;
+ dest[6] = e;
+ dest[7] = toF(hf2, cf, zf);
+ dest[8] = h;
+ dest[9] = l;
}
-void CPU::SetInterruptAddresses(int *addrs, int numAddrs)
-{
+void CPU::setInterruptAddresses(int *addrs, int numAddrs) {
interruptAddresses = addrs;
numInterruptAddresses = numAddrs;
}
-int CPU::GetHitInterruptAddress()
-{
+int CPU::getHitInterruptAddress() {
return hitInterruptAddress;
}
SYNCFUNC(CPU)
{
- SSS(memory);
+ SSS(mem_);
NSS(cycleCounter_);
- NSS(PC);
- NSS(SP);
- NSS(HF1);
- NSS(HF2);
- NSS(ZF);
- NSS(CF);
- NSS(A);
- NSS(B);
- NSS(C);
- NSS(D);
- NSS(E);
- NSS(H);
- NSS(L);
- NSS(skip);
+ NSS(pc);
+ NSS(sp);
+ NSS(hf1);
+ NSS(hf2);
+ NSS(zf);
+ NSS(cf);
+ NSS(a);
+ NSS(b);
+ NSS(c);
+ NSS(d);
+ NSS(e);
+ NSS(h);
+ NSS(l);
+ NSS(skip_);
}
}
diff --git a/libgambatte/src/cpu.h b/libgambatte/src/cpu.h
index 427847e95d..96c1a25b4f 100644
--- a/libgambatte/src/cpu.h
+++ b/libgambatte/src/cpu.h
@@ -1,21 +1,21 @@
-/***************************************************************************
- * Copyright (C) 2007 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2007 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#ifndef CPU_H
#define CPU_H
@@ -25,67 +25,40 @@
namespace gambatte {
class CPU {
- Memory memory;
-
- unsigned long cycleCounter_;
-
- unsigned short PC;
- unsigned short SP;
-
- unsigned HF1, HF2, ZF, CF;
-
- unsigned char A, B, C, D, E, /*F,*/ H, L;
-
- bool skip;
-
- int *interruptAddresses;
- int numInterruptAddresses;
- int hitInterruptAddress;
-
- void process(unsigned long cycles);
-
- void (*tracecallback)(void *);
-
public:
-
CPU();
-// void halt();
-
-// unsigned interrupt(unsigned address, unsigned cycleCounter);
-
long runFor(unsigned long cycles);
void setStatePtrs(SaveState &state);
- void loadState(const SaveState &state);
- void setLayers(unsigned mask) { memory.setLayers(mask); }
-
- void loadSavedata(const char *data) { memory.loadSavedata(data); }
- int saveSavedataLength() {return memory.saveSavedataLength(); }
- void saveSavedata(char *dest) { memory.saveSavedata(dest); }
-
- bool getMemoryArea(int which, unsigned char **data, int *length) { return memory.getMemoryArea(which, data, length); }
+ void loadState(SaveState const &state);
+ void setLayers(unsigned mask) { mem_.setLayers(mask); }
+ void loadSavedata(char const *data) { mem_.loadSavedata(data, cycleCounter_); }
+ int saveSavedataLength() {return mem_.saveSavedataLength(); }
+ void saveSavedata(char *dest) { mem_.saveSavedata(dest, cycleCounter_); }
- void setVideoBuffer(uint_least32_t *const videoBuf, const int pitch) {
- memory.setVideoBuffer(videoBuf, pitch);
+ bool getMemoryArea(int which, unsigned char **data, int *length) { return mem_.getMemoryArea(which, data, length); }
+
+ void setVideoBuffer(uint_least32_t *videoBuf, std::ptrdiff_t pitch) {
+ mem_.setVideoBuffer(videoBuf, pitch);
}
-
+
void setInputGetter(unsigned (*getInput)()) {
- memory.setInputGetter(getInput);
+ mem_.setInputGetter(getInput);
}
void setReadCallback(MemoryCallback callback) {
- memory.setReadCallback(callback);
+ mem_.setReadCallback(callback);
}
void setWriteCallback(MemoryCallback callback) {
- memory.setWriteCallback(callback);
+ mem_.setWriteCallback(callback);
}
void setExecCallback(MemoryCallback callback) {
- memory.setExecCallback(callback);
+ mem_.setExecCallback(callback);
}
void setCDCallback(CDCallback cdc) {
- memory.setCDCallback(cdc);
+ mem_.setCDCallback(cdc);
}
void setTraceCallback(void (*callback)(void *)) {
@@ -93,52 +66,66 @@ public:
}
void setScanlineCallback(void (*callback)(), int sl) {
- memory.setScanlineCallback(callback, sl);
- }
-
- void setRTCCallback(std::uint32_t (*callback)()) {
- memory.setRTCCallback(callback);
+ mem_.setScanlineCallback(callback, sl);
}
void setLinkCallback(void(*callback)()) {
- memory.setLinkCallback(callback);
+ mem_.setLinkCallback(callback);
}
-
- int load(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat) {
- return memory.loadROM(romfiledata, romfilelength, forceDmg, multicartCompat);
+
+ LoadRes load(char const *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat) {
+ return mem_.loadROM(romfiledata, romfilelength, forceDmg, multicartCompat);
}
-
- bool loaded() const { return memory.loaded(); }
- const char * romTitle() const { return memory.romTitle(); }
-
- void setSoundBuffer(uint_least32_t *const buf) { memory.setSoundBuffer(buf); }
- unsigned fillSoundBuffer() { return memory.fillSoundBuffer(cycleCounter_); }
-
- bool isCgb() const { return memory.isCgb(); }
-
- void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32) {
- memory.setDmgPaletteColor(palNum, colorNum, rgb32);
+
+ bool loaded() const { return mem_.loaded(); }
+ char const * romTitle() const { return mem_.romTitle(); }
+ void setSoundBuffer(uint_least32_t *buf) { mem_.setSoundBuffer(buf); }
+ std::size_t fillSoundBuffer() { return mem_.fillSoundBuffer(cycleCounter_); }
+ bool isCgb() const { return mem_.isCgb(); }
+
+ void setDmgPaletteColor(int palNum, int colorNum, unsigned long rgb32) {
+ mem_.setDmgPaletteColor(palNum, colorNum, rgb32);
}
void setCgbPalette(unsigned *lut) {
- memory.setCgbPalette(lut);
+ mem_.setCgbPalette(lut);
}
-
- unsigned char* cgbBiosBuffer() { return memory.cgbBiosBuffer(); }
- unsigned char* dmgBiosBuffer() { return memory.dmgBiosBuffer(); }
- bool gbIsCgb() { return memory.gbIsCgb(); }
+ void setTimeMode(bool useCycles) { mem_.setTimeMode(useCycles, cycleCounter_); }
+ void setRtcDivisorOffset(long const rtcDivisorOffset) { mem_.setRtcDivisorOffset(rtcDivisorOffset); }
- //unsigned char ExternalRead(unsigned short addr) { return memory.read(addr, cycleCounter_); }
- unsigned char ExternalRead(unsigned short addr) { return memory.peek(addr); }
- void ExternalWrite(unsigned short addr, unsigned char val) { memory.write_nocb(addr, val, cycleCounter_); }
+ void setBios(char const *buffer, std::size_t size) { mem_.setBios(buffer, size); }
+ bool gbIsCgb() { return mem_.gbIsCgb(); }
- int LinkStatus(int which) { return memory.LinkStatus(which); }
+ unsigned char externalRead(unsigned short addr) {return mem_.peek(addr); }
- void GetRegs(int *dest);
+ void externalWrite(unsigned short addr, unsigned char val) {
+ mem_.write_nocb(addr, val, cycleCounter_);
+ }
- void SetInterruptAddresses(int *addrs, int numAddrs);
- int GetHitInterruptAddress();
+ int linkStatus(int which) { return mem_.linkStatus(which); }
+ void getRegs(int *dest);
+ void setInterruptAddresses(int *addrs, int numAddrs);
+ int getHitInterruptAddress();
+
+private:
+ Memory mem_;
+ unsigned long cycleCounter_;
+ unsigned short pc;
+ unsigned short sp;
+ unsigned hf1, hf2, zf, cf;
+ unsigned char a, b, c, d, e, /*f,*/ h, l;
+ bool skip_;
+
+ int *interruptAddresses;
+ int numInterruptAddresses;
+ int hitInterruptAddress;
+
+ void process(unsigned long cycles);
+
+ void (*tracecallback)(void *);
+
+public:
templatevoid SyncState(NewState *ns);
};
diff --git a/libgambatte/src/file/stdfile.h b/libgambatte/src/file/stdfile.h
deleted file mode 100644
index 625e765c57..0000000000
--- a/libgambatte/src/file/stdfile.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/***************************************************************************
-Copyright (C) 2007 by Nach
-http://nsrt.edgeemu.com
-
-Copyright (C) 2007-2011 by Sindre Aamås
-aamas@stud.ntnu.no
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License version 2 as
-published by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License version 2 for more details.
-
-You should have received a copy of the GNU General Public License
-version 2 along with this program; if not, write to the
-Free Software Foundation, Inc.,
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-***************************************************************************/
-#ifndef GAMBATTE_STD_FILE_H
-#define GAMBATTE_STD_FILE_H
-
-#include "file.h"
-#include
-
-namespace gambatte {
-
-class StdFile : public File {
- std::ifstream stream;
- std::size_t fsize;
-
-public:
- explicit StdFile(const char *filename)
- : stream(filename, std::ios::in | std::ios::binary), fsize(0)
- {
- if (stream) {
- stream.seekg(0, std::ios::end);
- fsize = stream.tellg();
- stream.seekg(0, std::ios::beg);
- }
- }
-
- virtual void rewind() { stream.seekg(0, std::ios::beg); }
- virtual std::size_t size() const { return fsize; };
- virtual void read(char *buffer, std::size_t amount) { stream.read(buffer, amount); }
- virtual bool fail() const { return stream.fail(); }
-};
-
-}
-
-#endif
diff --git a/libgambatte/src/gambatte.cpp b/libgambatte/src/gambatte.cpp
index a1e3dfa65c..0bc0639a76 100644
--- a/libgambatte/src/gambatte.cpp
+++ b/libgambatte/src/gambatte.cpp
@@ -1,89 +1,83 @@
-/***************************************************************************
- * Copyright (C) 2007 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2007 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#include "gambatte.h"
#include "cpu.h"
-#include "savestate.h"
#include "initstate.h"
-#include
+#include "savestate.h"
#include
+#include
namespace gambatte {
+
struct GB::Priv {
CPU cpu;
unsigned loadflags;
unsigned layersMask;
uint_least32_t vbuff[160*144];
-
- Priv() : loadflags(0), layersMask(LAYER_MASK_BG | LAYER_MASK_OBJ)
- {
- }
- ~Priv()
+ Priv() : loadflags(0), layersMask(layer_mask_bg | layer_mask_window | layer_mask_obj)
{
}
};
-
+
GB::GB() : p_(new Priv) {}
GB::~GB() {
- //if (p_->cpu.loaded())
- // p_->cpu.saveSavedata();
-
delete p_;
}
-long GB::runFor(gambatte::uint_least32_t *const soundBuf, unsigned &samples) {
+std::ptrdiff_t GB::runFor(gambatte::uint_least32_t *const soundBuf, std::size_t &samples) {
if (!p_->cpu.loaded()) {
samples = 0;
return -1;
}
-
+
p_->cpu.setVideoBuffer(p_->vbuff, 160);
p_->cpu.setSoundBuffer(soundBuf);
- const long cyclesSinceBlit = p_->cpu.runFor(samples * 2);
+
+ long const cyclesSinceBlit = p_->cpu.runFor(samples * 2);
samples = p_->cpu.fillSoundBuffer();
-
- return cyclesSinceBlit < 0 ? cyclesSinceBlit : static_cast(samples) - (cyclesSinceBlit >> 1);
+ return cyclesSinceBlit >= 0
+ ? static_cast(samples) - (cyclesSinceBlit >> 1)
+ : cyclesSinceBlit;
}
-void GB::setLayers(unsigned mask)
-{
+void GB::setLayers(unsigned mask) {
p_->cpu.setLayers(mask);
}
-void GB::blitTo(gambatte::uint_least32_t *videoBuf, int pitch)
-{
+void GB::blitTo(gambatte::uint_least32_t *videoBuf, std::ptrdiff_t pitch) {
gambatte::uint_least32_t *src = p_->vbuff;
gambatte::uint_least32_t *dst = videoBuf;
for (int i = 0; i < 144; i++)
{
- std::memcpy(dst, src, sizeof(gambatte::uint_least32_t) * 160);
+ std::memcpy(dst, src, sizeof gambatte::uint_least32_t * 160);
src += 160;
dst += pitch;
}
}
-void GB::reset(const std::uint32_t now, const unsigned div) {
+void GB::reset() {
if (p_->cpu.loaded()) {
-
+
int length = p_->cpu.saveSavedataLength();
char *s;
if (length > 0)
@@ -91,10 +85,10 @@ void GB::reset(const std::uint32_t now, const unsigned div) {
s = (char *) std::malloc(length);
p_->cpu.saveSavedata(s);
}
-
+
SaveState state;
p_->cpu.setStatePtrs(state);
- setInitState(state, !(p_->loadflags & FORCE_DMG), p_->loadflags & GBA_CGB, now, div);
+ setInitState(state, !(p_->loadflags & FORCE_DMG), p_->loadflags & GBA_CGB);
p_->cpu.loadState(state);
if (length > 0)
{
@@ -132,39 +126,34 @@ void GB::setScanlineCallback(void (*callback)(), int sl) {
p_->cpu.setScanlineCallback(callback, sl);
}
-void GB::setRTCCallback(std::uint32_t (*callback)()) {
- p_->cpu.setRTCCallback(callback);
-}
-
void GB::setLinkCallback(void(*callback)()) {
p_->cpu.setLinkCallback(callback);
}
-int GB::load(const char *romfiledata, unsigned romfilelength, const std::uint32_t now, const unsigned flags, const unsigned div) {
- //if (p_->cpu.loaded())
- // p_->cpu.saveSavedata();
-
- const int failed = p_->cpu.load(romfiledata, romfilelength, flags & FORCE_DMG, flags & MULTICART_COMPAT);
-
- if (!failed) {
+void GB::setTimeMode(bool useCycles) {
+ p_->cpu.setTimeMode(useCycles);
+}
+
+void GB::setRtcDivisorOffset(long const rtcDivisorOffset) {
+ p_->cpu.setRtcDivisorOffset(rtcDivisorOffset);
+}
+
+LoadRes GB::load(char const *romfiledata, unsigned romfilelength, unsigned const flags) {
+ LoadRes const loadres = p_->cpu.load(romfiledata, romfilelength, flags & FORCE_DMG, flags & MULTICART_COMPAT);
+
+ if (loadres == LOADRES_OK) {
SaveState state;
p_->cpu.setStatePtrs(state);
p_->loadflags = flags;
- setInitState(state, !(flags & FORCE_DMG), flags & GBA_CGB, now, div);
+ setInitState(state, !(flags & FORCE_DMG), flags & GBA_CGB);
p_->cpu.loadState(state);
- //p_->cpu.loadSavedata();
}
-
- return failed;
+
+ return loadres;
}
-int GB::loadGBCBios(const char* biosfiledata) {
- memcpy(p_->cpu.cgbBiosBuffer(), biosfiledata, 0x900);
- return 0;
-}
-
-int GB::loadDMGBios(const char* biosfiledata) {
- memcpy(p_->cpu.dmgBiosBuffer(), biosfiledata, 0x100);
+int GB::loadBios(char const* biosfiledata, std::size_t size) {
+ p_->cpu.setBios(biosfiledata, size);
return 0;
}
@@ -180,7 +169,7 @@ void GB::saveSavedata(char *dest) {
if (p_->cpu.loaded())
p_->cpu.saveSavedata(dest);
}
-void GB::loadSavedata(const char *data) {
+void GB::loadSavedata(char const *data) {
if (p_->cpu.loaded())
p_->cpu.loadSavedata(data);
}
@@ -198,20 +187,20 @@ bool GB::getMemoryArea(int which, unsigned char **data, int *length) {
return false;
}
-unsigned char GB::ExternalRead(unsigned short addr) {
+unsigned char GB::externalRead(unsigned short addr) {
if (p_->cpu.loaded())
- return p_->cpu.ExternalRead(addr);
+ return p_->cpu.externalRead(addr);
else
return 0;
}
-void GB::ExternalWrite(unsigned short addr, unsigned char val) {
+void GB::externalWrite(unsigned short addr, unsigned char val) {
if (p_->cpu.loaded())
- p_->cpu.ExternalWrite(addr, val);
+ p_->cpu.externalWrite(addr, val);
}
-void GB::setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32) {
+void GB::setDmgPaletteColor(int palNum, int colorNum, unsigned long rgb32) {
p_->cpu.setDmgPaletteColor(palNum, colorNum, rgb32);
}
@@ -219,33 +208,31 @@ void GB::setCgbPalette(unsigned *lut) {
p_->cpu.setCgbPalette(lut);
}
-const std::string GB::romTitle() const {
+std::string const GB::romTitle() const {
if (p_->cpu.loaded()) {
char title[0x11];
std::memcpy(title, p_->cpu.romTitle(), 0x10);
- title[(title[0xF] & 0x80) ? 0xF : 0x10] = '\0';
+ title[title[0xF] & 0x80 ? 0xF : 0x10] = '\0';
return std::string(title);
}
-
+
return std::string();
}
-int GB::LinkStatus(int which) {
- return p_->cpu.LinkStatus(which);
+int GB::linkStatus(int which) {
+ return p_->cpu.linkStatus(which);
}
-void GB::GetRegs(int *dest) {
- p_->cpu.GetRegs(dest);
+void GB::getRegs(int *dest) {
+ p_->cpu.getRegs(dest);
}
-void GB::SetInterruptAddresses(int *addrs, int numAddrs)
-{
- p_->cpu.SetInterruptAddresses(addrs, numAddrs);
+void GB::setInterruptAddresses(int *addrs, int numAddrs) {
+ p_->cpu.setInterruptAddresses(addrs, numAddrs);
}
-int GB::GetHitInterruptAddress()
-{
- return p_->cpu.GetHitInterruptAddress();
+int GB::getHitInterruptAddress() {
+ return p_->cpu.getHitInterruptAddress();
}
SYNCFUNC(GB)
diff --git a/libgambatte/src/initstate.cpp b/libgambatte/src/initstate.cpp
index 6f6e3a6e7c..72e26c6f85 100644
--- a/libgambatte/src/initstate.cpp
+++ b/libgambatte/src/initstate.cpp
@@ -1,32 +1,33 @@
-/***************************************************************************
- * Copyright (C) 2008 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2008 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#include "initstate.h"
#include "counterdef.h"
#include "savestate.h"
#include "sound/sound_unit.h"
+#include "mem/time.h"
#include
#include
namespace {
-static void setInitialCgbWram(unsigned char *const wram) {
- static const struct { unsigned short addr; unsigned char val; } cgbWramDumpDiff[] = {
+static void setInitialCgbWram(unsigned char wram[]) {
+ static struct { unsigned short addr; unsigned char val; } const cgbWramDumpDiff[] = {
{ 0x0083, 0x7F }, { 0x008B, 0x10 }, { 0x00C0, 0x7F }, { 0x00E1, 0x7F },
{ 0x00E2, 0x7F }, { 0x00EA, 0x10 }, { 0x010A, 0x40 }, { 0x0179, 0x01 },
{ 0x01AF, 0x01 }, { 0x0201, 0xFB }, { 0x0254, 0xF7 }, { 0x0264, 0x7F },
@@ -677,35 +678,35 @@ static void setInitialCgbWram(unsigned char *const wram) {
{ 0x7FCD, 0xBF }, { 0x7FCE, 0x7F }, { 0x7FCF, 0xFB }, { 0x7FDB, 0xF7 },
{ 0x7FDF, 0x7F }, { 0x7FE8, 0xDF }, { 0x7FEC, 0xFB }, { 0x7FF2, 0xF7 }
};
-
+
for (unsigned addr = 0x0000; addr < 0x0800; addr += 0x10) {
std::memset(wram + addr + 0x00, 0xFF, 0x08);
std::memset(wram + addr + 0x08, 0x00, 0x08);
}
-
+
for (unsigned addr = 0x0800; addr < 0x1000; addr += 0x10) {
std::memset(wram + addr + 0x00, 0x00, 0x08);
std::memset(wram + addr + 0x08, 0xFF, 0x08);
}
-
+
for (unsigned addr = 0x0E00; addr < 0x1000; addr += 0x10) {
wram[addr + 0x02] = 0xFF;
wram[addr + 0x0A] = 0x00;
}
-
+
for (unsigned addr = 0x1000; addr < 0x8000; addr += 0x1000) {
if (0x2000 != addr)
std::memcpy(wram + addr, wram, 0x1000);
}
-
+
std::memset(wram + 0x2000, 0, 0x1000);
-
- for (std::size_t i = 0; i < sizeof(cgbWramDumpDiff) / sizeof(cgbWramDumpDiff[0]); ++i)
+
+ for (std::size_t i = 0; i < sizeof cgbWramDumpDiff / sizeof cgbWramDumpDiff[0]; ++i)
wram[cgbWramDumpDiff[i].addr] = cgbWramDumpDiff[i].val;
}
-static void setInitialDmgWram(unsigned char *const wram) {
- static const struct { unsigned short addr; unsigned char val; } dmgWramDumpDiff[] = {
+static void setInitialDmgWram(unsigned char wram[]) {
+ static struct { unsigned short addr; unsigned char val; } const dmgWramDumpDiff[] = {
{ 0x0000, 0x08 }, { 0x0004, 0x08 }, { 0x0008, 0x4D }, { 0x000A, 0x80 },
{ 0x0010, 0x02 }, { 0x0018, 0x04 }, { 0x0020, 0x10 }, { 0x0028, 0x05 },
{ 0x002C, 0x08 }, { 0x0038, 0x21 }, { 0x003A, 0x40 }, { 0x0060, 0x02 },
@@ -959,25 +960,25 @@ static void setInitialDmgWram(unsigned char *const wram) {
{ 0x1FA2, 0x40 }, { 0x1FB6, 0x80 }, { 0x1FC6, 0x10 }, { 0x1FCC, 0x20 },
{ 0x1FD2, 0x20 }, { 0x1FD8, 0x04 }, { 0x1FDC, 0x10 }, { 0x1FDE, 0x04 }
};
-
+
for (unsigned addr = 0x0000; addr < 0x0800; addr += 0x200) {
std::memset(wram + addr , 0x00, 0x100);
std::memset(wram + addr + 0x100, 0xFF, 0x100);
}
-
+
for (unsigned addr = 0x0800; addr < 0x1000; addr += 0x200) {
std::memset(wram + addr , 0xFF, 0x100);
std::memset(wram + addr + 0x100, 0x00, 0x100);
}
-
+
std::memcpy(wram + 0x1000, wram, 0x1000);
-
- for (std::size_t i = 0; i < sizeof(dmgWramDumpDiff) / sizeof(dmgWramDumpDiff[0]); ++i)
+
+ for (std::size_t i = 0; i < sizeof dmgWramDumpDiff / sizeof dmgWramDumpDiff[0]; ++i)
wram[dmgWramDumpDiff[i].addr] = dmgWramDumpDiff[i].val;
}
-static void setInitialVram(unsigned char *const vram, const bool cgb) {
- static const unsigned char even_numbered_8010_to_81a0_dump[] = {
+static void setInitialVram(unsigned char vram[], bool const cgb) {
+ static unsigned char const even_numbered_8010_to_81a0_dump[] = {
0xF0, 0xF0, 0xFC, 0xFC, 0xFC, 0xFC, 0xF3, 0xF3,
0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C,
0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0xF3, 0xF3,
@@ -1004,28 +1005,28 @@ static void setInitialVram(unsigned char *const vram, const bool cgb) {
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFC, 0xFC,
0x3C, 0x42, 0xB9, 0xA5, 0xB9, 0xA5, 0x42, 0x3C
};
-
+
std::memset(vram, 0, 0x4000);
-
- for (std::size_t i = 0; i < sizeof(even_numbered_8010_to_81a0_dump) / sizeof(even_numbered_8010_to_81a0_dump[0]); ++i) {
+
+ for (std::size_t i = 0; i < sizeof even_numbered_8010_to_81a0_dump; ++i) {
vram[0x0010 + i * 2] = even_numbered_8010_to_81a0_dump[i];
}
-
+
if (!cgb) {
unsigned i = 1;
-
+
for (unsigned addr = 0x1904; addr < 0x1910; ++addr)
vram[addr] = i++;
-
+
vram[0x1910] = 0x19;
-
+
for (unsigned addr = 0x1924; addr < 0x1930; ++addr)
vram[addr] = i++;
}
}
-static void setInitialCgbIoamhram(unsigned char *const ioamhram) {
- static const unsigned char feaxDump[0x60] = {
+static void setInitialCgbIoamhram(unsigned char ioamhram[]) {
+ static unsigned char const feaxDump[0x60] = {
0x08, 0x01, 0xEF, 0xDE, 0x06, 0x4A, 0xCD, 0xBD,
0x08, 0x01, 0xEF, 0xDE, 0x06, 0x4A, 0xCD, 0xBD,
0x08, 0x01, 0xEF, 0xDE, 0x06, 0x4A, 0xCD, 0xBD,
@@ -1039,8 +1040,8 @@ static void setInitialCgbIoamhram(unsigned char *const ioamhram) {
0x24, 0x13, 0xFD, 0x3A, 0x10, 0x10, 0xAD, 0x45,
0x24, 0x13, 0xFD, 0x3A, 0x10, 0x10, 0xAD, 0x45
};
-
- static const unsigned char ffxxDump[0x100] = {
+
+ static unsigned char const ffxxDump[0x100] = {
0xCF, 0x00, 0x7C, 0xFF, 0x00, 0x00, 0x00, 0xF8,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1,
0x80, 0x3F, 0x00, 0xFF, 0xBF, 0xFF, 0x3F, 0x00,
@@ -1074,14 +1075,14 @@ static void setInitialCgbIoamhram(unsigned char *const ioamhram) {
0x98, 0xD1, 0x71, 0x02, 0x4D, 0x01, 0xC1, 0xFF,
0x0D, 0x00, 0xD3, 0x05, 0xF9, 0x00, 0x0B, 0x00
};
-
+
std::memset(ioamhram, 0x00, 0x0A0);
- std::memcpy(ioamhram + 0x0A0, feaxDump, sizeof(feaxDump));
- std::memcpy(ioamhram + 0x100, ffxxDump, sizeof(ffxxDump));
+ std::memcpy(ioamhram + 0x0A0, feaxDump, sizeof feaxDump);
+ std::memcpy(ioamhram + 0x100, ffxxDump, sizeof ffxxDump);
}
-static void setInitialDmgIoamhram(unsigned char *const ioamhram) {
- static const unsigned char oamDump[0xA0] = {
+static void setInitialDmgIoamhram(unsigned char ioamhram[]) {
+ static unsigned char const oamDump[0xA0] = {
0xBB, 0xD8, 0xC4, 0x04, 0xCD, 0xAC, 0xA1, 0xC7,
0x7D, 0x85, 0x15, 0xF0, 0xAD, 0x19, 0x11, 0x6A,
0xBA, 0xC7, 0x76, 0xF8, 0x5C, 0xA0, 0x67, 0x0A,
@@ -1103,13 +1104,13 @@ static void setInitialDmgIoamhram(unsigned char *const ioamhram) {
0x24, 0x40, 0x42, 0x05, 0x0E, 0x04, 0x20, 0xA6,
0x5E, 0xC1, 0x97, 0x7E, 0x44, 0x05, 0x01, 0xA9
};
-
- static const unsigned char ffxxDump[0x100] = {
+
+ static unsigned char const ffxxDump[0x100] = {
0xCF, 0x00, 0x7E, 0xFF, 0xD3, 0x00, 0x00, 0xF8,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1,
- 0x80, 0xBF, 0xF3, 0xFF, 0xBF, 0xFF, 0x3F, 0x00,
+ 0x80, 0x3F, 0x00, 0xFF, 0xBF, 0xFF, 0x3F, 0x00,
0xFF, 0xBF, 0x7F, 0xFF, 0x9F, 0xFF, 0xBF, 0xFF,
- 0xFF, 0x00, 0x00, 0xBF, 0x77, 0xF3, 0xF1, 0xFF,
+ 0xFF, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x70, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x71, 0x72, 0xD5, 0x91, 0x58, 0xBB, 0x2A, 0xFA,
0xCF, 0x3C, 0x54, 0x75, 0x48, 0xCF, 0x8F, 0xD9,
@@ -1138,52 +1139,52 @@ static void setInitialDmgIoamhram(unsigned char *const ioamhram) {
0xBC, 0x7F, 0x7E, 0xD0, 0xC7, 0xC3, 0xBD, 0xCF,
0x59, 0xEA, 0x39, 0x01, 0x2E, 0x00, 0x69, 0x00
};
-
- std::memcpy(ioamhram , oamDump, sizeof(oamDump));
+
+ std::memcpy(ioamhram , oamDump, sizeof oamDump);
std::memset(ioamhram + 0x0A0, 0x00, 0x060);
- std::memcpy(ioamhram + 0x100, ffxxDump, sizeof(ffxxDump));
+ std::memcpy(ioamhram + 0x100, ffxxDump, sizeof ffxxDump);
}
} // anon namespace
-void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbMode, const std::uint32_t now, const unsigned div) {
- static const unsigned char cgbObjpDump[0x40] = {
- 0x00, 0x00, 0xF2, 0xAB,
- 0x61, 0xC2, 0xD9, 0xBA,
- 0x88, 0x6E, 0xDD, 0x63,
- 0x28, 0x27, 0xFB, 0x9F,
- 0x35, 0x42, 0xD6, 0xD4,
- 0x50, 0x48, 0x57, 0x5E,
- 0x23, 0x3E, 0x3D, 0xCA,
- 0x71, 0x21, 0x37, 0xC0,
- 0xC6, 0xB3, 0xFB, 0xF9,
- 0x08, 0x00, 0x8D, 0x29,
- 0xA3, 0x20, 0xDB, 0x87,
- 0x62, 0x05, 0x5D, 0xD4,
- 0x0E, 0x08, 0xFE, 0xAF,
- 0x20, 0x02, 0xD7, 0xFF,
- 0x07, 0x6A, 0x55, 0xEC,
+void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbMode) {
+ static unsigned char const cgbObjpDump[0x40] = {
+ 0x00, 0x00, 0xF2, 0xAB,
+ 0x61, 0xC2, 0xD9, 0xBA,
+ 0x88, 0x6E, 0xDD, 0x63,
+ 0x28, 0x27, 0xFB, 0x9F,
+ 0x35, 0x42, 0xD6, 0xD4,
+ 0x50, 0x48, 0x57, 0x5E,
+ 0x23, 0x3E, 0x3D, 0xCA,
+ 0x71, 0x21, 0x37, 0xC0,
+ 0xC6, 0xB3, 0xFB, 0xF9,
+ 0x08, 0x00, 0x8D, 0x29,
+ 0xA3, 0x20, 0xDB, 0x87,
+ 0x62, 0x05, 0x5D, 0xD4,
+ 0x0E, 0x08, 0xFE, 0xAF,
+ 0x20, 0x02, 0xD7, 0xFF,
+ 0x07, 0x6A, 0x55, 0xEC,
0x83, 0x40, 0x0B, 0x77
};
-
+
state.cpu.cycleCounter = 8;
- state.cpu.PC = 0;
- state.cpu.SP = 0;
- state.cpu.A = 0;
- state.cpu.B = 0;
- state.cpu.C = 0;
- state.cpu.D = 0;
- state.cpu.E = 0;
- state.cpu.F = 0;
- state.cpu.H = 0;
- state.cpu.L = 0;
+ state.cpu.pc = 0;
+ state.cpu.sp = 0;
+ state.cpu.a = 0;
+ state.cpu.b = 0;
+ state.cpu.c = 0;
+ state.cpu.d = 0;
+ state.cpu.e = 0;
+ state.cpu.f = 0;
+ state.cpu.h = 0;
+ state.cpu.l = 0;
state.cpu.skip = false;
state.mem.biosMode = true;
state.mem.cgbSwitching = false;
state.mem.agbMode = gbaCgbMode;
- std::memset(state.mem.sram.ptr, 0xFF, state.mem.sram.getSz());
-
+ std::memset(state.mem.sram.ptr, 0xFF, state.mem.sram.size());
+
setInitialVram(state.mem.vram.ptr, cgb);
if (cgb) {
@@ -1193,18 +1194,20 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM
setInitialDmgWram(state.mem.wram.ptr);
setInitialDmgIoamhram(state.mem.ioamhram.ptr);
}
-
+
state.mem.ioamhram.ptr[0x104] = 0;
state.mem.ioamhram.ptr[0x140] = 0;
state.mem.ioamhram.ptr[0x144] = 0x00;
-
- state.mem.divLastUpdate = 0 - div;
+
+ state.mem.divLastUpdate = 0;
+ state.mem.timaBasetime = 0;
state.mem.timaLastUpdate = 0;
- state.mem.tmatime = DISABLED_TIME;
- state.mem.nextSerialtime = DISABLED_TIME;
- state.mem.lastOamDmaUpdate = DISABLED_TIME;
- state.mem.unhaltTime = DISABLED_TIME;
+ state.mem.tmatime = disabled_time;
+ state.mem.nextSerialtime = disabled_time;
+ state.mem.lastOamDmaUpdate = disabled_time;
+ state.mem.unhaltTime = disabled_time;
state.mem.minIntTime = 0;
+ state.mem.halttime = 0;
state.mem.rombank = 1;
state.mem.dmaSource = 0;
state.mem.dmaDestination = 0;
@@ -1216,28 +1219,29 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM
state.mem.rambankMode = false;
state.mem.hdmaTransfer = false;
state.mem.gbIsCgb = cgb;
+ state.mem.stopped = false;
-
- for (unsigned i = 0x00; i < 0x40; i += 0x02) {
+
+ for (int i = 0x00; i < 0x40; i += 0x02) {
state.ppu.bgpData.ptr[i ] = 0xFF;
state.ppu.bgpData.ptr[i + 1] = 0x7F;
}
-
- std::memcpy(state.ppu.objpData.ptr, cgbObjpDump, sizeof(cgbObjpDump));
-
+
+ std::memcpy(state.ppu.objpData.ptr, cgbObjpDump, sizeof cgbObjpDump);
+
if (!cgb) {
state.ppu.bgpData.ptr[0] = state.mem.ioamhram.get()[0x147];
state.ppu.objpData.ptr[0] = state.mem.ioamhram.get()[0x148];
state.ppu.objpData.ptr[1] = state.mem.ioamhram.get()[0x149];
}
-
- for (unsigned pos = 0; pos < 80; ++pos)
+
+ for (int pos = 0; pos < 80; ++pos)
state.ppu.oamReaderBuf.ptr[pos] = state.mem.ioamhram.ptr[(pos * 2 & ~3) | (pos & 1)];
-
+
std::fill_n(state.ppu.oamReaderSzbuf.ptr, 40, false);
- std::memset(state.ppu.spAttribList, 0, sizeof(state.ppu.spAttribList));
- std::memset(state.ppu.spByte0List, 0, sizeof(state.ppu.spByte0List));
- std::memset(state.ppu.spByte1List, 0, sizeof(state.ppu.spByte1List));
+ std::memset(state.ppu.spAttribList, 0, sizeof state.ppu.spAttribList);
+ std::memset(state.ppu.spByte0List, 0, sizeof state.ppu.spByte0List);
+ std::memset(state.ppu.spByte1List, 0, sizeof state.ppu.spByte1List);
state.ppu.videoCycles = 0;
state.ppu.enableDisplayM0Time = state.cpu.cycleCounter;
state.ppu.winYPos = 0xFF;
@@ -1263,57 +1267,61 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM
state.ppu.pendingLcdstatIrq = false;
state.ppu.isCgb = cgb;
-
- state.spu.cycleCounter = 0; // spu.cycleCounter >> 12 & 7 represents the frame sequencer position.
-
- state.spu.ch1.sweep.counter = SoundUnit::COUNTER_DISABLED;
+ // spu.cycleCounter >> 12 & 7 represents the frame sequencer position.
+ state.spu.cycleCounter = state.cpu.cycleCounter >> 1;
+
+ state.spu.ch1.sweep.counter = SoundUnit::counter_disabled;
state.spu.ch1.sweep.shadow = 0;
state.spu.ch1.sweep.nr0 = 0;
state.spu.ch1.sweep.negging = false;
- state.spu.ch1.duty.nextPosUpdate = (state.spu.cycleCounter & ~1ul) + 37 * 2;
- state.spu.ch1.duty.nr3 = 0;
+ state.spu.ch1.duty.nextPosUpdate = SoundUnit::counter_disabled;
state.spu.ch1.duty.pos = 0;
- state.spu.ch1.env.counter = SoundUnit::COUNTER_DISABLED;
+ state.spu.ch1.duty.high = false;
+ state.spu.ch1.duty.nr3 = 0;
+ state.spu.ch1.env.counter = SoundUnit::counter_disabled;
state.spu.ch1.env.volume = 0;
- state.spu.ch1.lcounter.counter = SoundUnit::COUNTER_DISABLED;
+ state.spu.ch1.lcounter.counter = SoundUnit::counter_disabled;
state.spu.ch1.lcounter.lengthCounter = 0;
state.spu.ch1.nr4 = 0;
state.spu.ch1.master = false;
-
- state.spu.ch2.duty.nextPosUpdate = SoundUnit::COUNTER_DISABLED;
+
+ state.spu.ch2.duty.nextPosUpdate = SoundUnit::counter_disabled;
state.spu.ch2.duty.nr3 = 0;
state.spu.ch2.duty.pos = 0;
- state.spu.ch2.env.counter = SoundUnit::COUNTER_DISABLED;
+ state.spu.ch2.duty.high = false;
+ state.spu.ch2.env.counter = SoundUnit::counter_disabled;
state.spu.ch2.env.volume = 0;
- state.spu.ch2.lcounter.counter = SoundUnit::COUNTER_DISABLED;
+ state.spu.ch2.lcounter.counter = SoundUnit::counter_disabled;
state.spu.ch2.lcounter.lengthCounter = 0;
state.spu.ch2.nr4 = 0;
state.spu.ch2.master = false;
-
- for (unsigned i = 0; i < 0x10; ++i)
- state.spu.ch3.waveRam.ptr[i] = state.mem.ioamhram.get()[0x130 + i];
-
- state.spu.ch3.lcounter.counter = SoundUnit::COUNTER_DISABLED;
+
+ std::memcpy(state.spu.ch3.waveRam.ptr, state.mem.ioamhram.get() + 0x130, 0x10);
+ state.spu.ch3.lcounter.counter = SoundUnit::counter_disabled;
state.spu.ch3.lcounter.lengthCounter = 0x100;
- state.spu.ch3.waveCounter = SoundUnit::COUNTER_DISABLED;
- state.spu.ch3.lastReadTime = SoundUnit::COUNTER_DISABLED;
+ state.spu.ch3.waveCounter = SoundUnit::counter_disabled;
+ state.spu.ch3.lastReadTime = SoundUnit::counter_disabled;
state.spu.ch3.nr3 = 0;
state.spu.ch3.nr4 = 0;
state.spu.ch3.wavePos = 0;
state.spu.ch3.sampleBuf = 0;
state.spu.ch3.master = false;
-
+
state.spu.ch4.lfsr.counter = state.spu.cycleCounter + 4;
state.spu.ch4.lfsr.reg = 0xFF;
- state.spu.ch4.env.counter = SoundUnit::COUNTER_DISABLED;
+ state.spu.ch4.env.counter = SoundUnit::counter_disabled;
state.spu.ch4.env.volume = 0;
- state.spu.ch4.lcounter.counter = SoundUnit::COUNTER_DISABLED;
+ state.spu.ch4.lcounter.counter = SoundUnit::counter_disabled;
state.spu.ch4.lcounter.lengthCounter = 0;
state.spu.ch4.nr4 = 0;
state.spu.ch4.master = false;
-
- state.rtc.baseTime = now;
- state.rtc.haltTime = state.rtc.baseTime;
+
+ state.time.seconds = 0;
+ state.time.lastTimeSec = Time::now().tv_sec;
+ state.time.lastTimeUsec = Time::now().tv_usec;
+ state.time.lastCycles = state.cpu.cycleCounter;
+
+ state.rtc.haltTime = state.time.seconds;
state.rtc.dataDh = 0;
state.rtc.dataDl = 0;
state.rtc.dataH = 0;
diff --git a/libgambatte/src/initstate.h b/libgambatte/src/initstate.h
index dd20a3d07a..0e31dd35bb 100644
--- a/libgambatte/src/initstate.h
+++ b/libgambatte/src/initstate.h
@@ -1,28 +1,29 @@
-/***************************************************************************
- * Copyright (C) 2008 by Sindre Aams *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2008 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#ifndef INITSTATE_H
#define INITSTATE_H
#include
namespace gambatte {
-void setInitState(struct SaveState &state, bool cgb, bool gbaCgbMode, std::uint32_t now, unsigned div);
+
+void setInitState(struct SaveState &state, bool cgb, bool gbaCgbMode);
}
#endif
diff --git a/libgambatte/src/insertion_sort.h b/libgambatte/src/insertion_sort.h
index f6a3c991a4..8b76d9385a 100644
--- a/libgambatte/src/insertion_sort.h
+++ b/libgambatte/src/insertion_sort.h
@@ -1,21 +1,20 @@
-/***************************************************************************
- * Copyright (C) 2007 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2007 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
#ifndef INSERTION_SORT_H
#define INSERTION_SORT_H
@@ -26,25 +25,24 @@ template
void insertionSort(T *const start, T *const end, Less less) {
if (start >= end)
return;
-
+
T *a = start;
-
+
while (++a < end) {
- const T e = *a;
-
+ T const e = *a;
T *b = a;
-
+
while (b != start && less(e, *(b - 1))) {
*b = *(b - 1);
b = b - 1;
}
-
+
*b = e;
}
}
template
-inline void insertionSort(T *const start, T *const end) {
+inline void insertionSort(T *start, T *end) {
insertionSort(start, end, std::less());
}
diff --git a/libgambatte/src/interrupter.cpp b/libgambatte/src/interrupter.cpp
deleted file mode 100644
index 9eac990516..0000000000
--- a/libgambatte/src/interrupter.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-#include "interrupter.h"
-#include "memory.h"
-
-namespace gambatte {
-
-Interrupter::Interrupter(unsigned short &SP_in, unsigned short &PC_in) :
- SP(SP_in),
- PC(PC_in)
-{}
-
-unsigned long Interrupter::interrupt(const unsigned address, unsigned long cycleCounter, Memory &memory) {
- cycleCounter += 8;
- SP = (SP - 1) & 0xFFFF;
- memory.write(SP, PC >> 8, cycleCounter);
- cycleCounter += 4;
- SP = (SP - 1) & 0xFFFF;
- memory.write(SP, PC & 0xFF, cycleCounter);
- PC = address;
- cycleCounter += 8;
-
- return cycleCounter;
-}
-
-}
diff --git a/libgambatte/src/interrupter.h b/libgambatte/src/interrupter.h
deleted file mode 100644
index 903368c391..0000000000
--- a/libgambatte/src/interrupter.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-#ifndef INTERRUPTER_H
-#define INTERRUPTER_H
-
-#include
-#include
-
-namespace gambatte {
-
-class Interrupter {
- unsigned short &SP;
- unsigned short &PC;
-public:
- Interrupter(unsigned short &SP, unsigned short &PC);
- unsigned long interrupt(const unsigned address, unsigned long cycleCounter, class Memory &memory);
-};
-
-}
-
-#endif
diff --git a/libgambatte/src/interruptrequester.cpp b/libgambatte/src/interruptrequester.cpp
index c656ad2368..af37ed584e 100644
--- a/libgambatte/src/interruptrequester.cpp
+++ b/libgambatte/src/interruptrequester.cpp
@@ -1,106 +1,120 @@
-/***************************************************************************
- * Copyright (C) 2010 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2010 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#include "interruptrequester.h"
#include "savestate.h"
namespace gambatte {
-InterruptRequester::InterruptRequester() : minIntTime(0), ifreg_(0), iereg_(0) {}
+InterruptRequester::InterruptRequester()
+: eventTimes_(disabled_time)
+, minIntTime_(0)
+, ifreg_(0)
+, iereg_(0)
+{
+}
-void InterruptRequester::loadState(const SaveState &state) {
- minIntTime = state.mem.minIntTime;
+void InterruptRequester::loadState(SaveState const &state) {
+ minIntTime_ = state.mem.minIntTime;
ifreg_ = state.mem.ioamhram.get()[0x10F];
iereg_ = state.mem.ioamhram.get()[0x1FF] & 0x1F;
- intFlags.set(state.mem.IME, state.mem.halted);
-
- eventTimes.setValue(intFlags.imeOrHalted() && pendingIrqs() ? minIntTime : static_cast(DISABLED_TIME));
+ intFlags_.set(state.mem.IME, state.mem.halted);
+
+ eventTimes_.setValue(intFlags_.imeOrHalted() && pendingIrqs()
+ ? minIntTime_
+ : static_cast(disabled_time));
}
-void InterruptRequester::resetCc(const unsigned long oldCc, const unsigned long newCc) {
- minIntTime = minIntTime < oldCc ? 0 : minIntTime - (oldCc - newCc);
-
- if (eventTimes.value(INTERRUPTS) != DISABLED_TIME)
- eventTimes.setValue(minIntTime);
+void InterruptRequester::resetCc(unsigned long oldCc, unsigned long newCc) {
+ minIntTime_ = minIntTime_ < oldCc ? 0 : minIntTime_ - (oldCc - newCc);
+
+ if (eventTimes_.value(intevent_interrupts) != disabled_time)
+ eventTimes_.setValue(minIntTime_);
}
-void InterruptRequester::ei(const unsigned long cc) {
- intFlags.setIme();
- minIntTime = cc + 1;
-
+void InterruptRequester::ei(unsigned long cc) {
+ intFlags_.setIme();
+ minIntTime_ = cc + 1;
+
if (pendingIrqs())
- eventTimes.setValue(minIntTime);
+ eventTimes_.setValue(minIntTime_);
}
void InterruptRequester::di() {
- intFlags.unsetIme();
-
- if (!intFlags.imeOrHalted())
- eventTimes.setValue(DISABLED_TIME);
+ intFlags_.unsetIme();
+
+ if (!intFlags_.imeOrHalted())
+ eventTimes_.setValue(disabled_time);
}
void InterruptRequester::halt() {
- intFlags.setHalted();
-
+ intFlags_.setHalted();
+
if (pendingIrqs())
- eventTimes.setValue(minIntTime);
+ eventTimes_.setValue(minIntTime_);
}
void InterruptRequester::unhalt() {
- intFlags.unsetHalted();
-
- if (!intFlags.imeOrHalted())
- eventTimes.setValue(DISABLED_TIME);
+ intFlags_.unsetHalted();
+
+ if (!intFlags_.imeOrHalted())
+ eventTimes_.setValue(disabled_time);
}
-void InterruptRequester::flagIrq(const unsigned bit) {
+void InterruptRequester::flagIrq(unsigned bit) {
ifreg_ |= bit;
-
- if (intFlags.imeOrHalted() && pendingIrqs())
- eventTimes.setValue(minIntTime);
+
+ if (intFlags_.imeOrHalted() && pendingIrqs())
+ eventTimes_.setValue(minIntTime_);
}
-void InterruptRequester::ackIrq(const unsigned bit) {
+void InterruptRequester::ackIrq(unsigned bit) {
ifreg_ ^= bit;
di();
}
-void InterruptRequester::setIereg(const unsigned iereg) {
+void InterruptRequester::setIereg(unsigned iereg) {
iereg_ = iereg & 0x1F;
-
- if (intFlags.imeOrHalted())
- eventTimes.setValue(pendingIrqs() ? minIntTime : static_cast(DISABLED_TIME));
+
+ if (intFlags_.imeOrHalted()) {
+ eventTimes_.setValue(pendingIrqs()
+ ? minIntTime_
+ : static_cast(disabled_time));
+ }
}
-void InterruptRequester::setIfreg(const unsigned ifreg) {
+void InterruptRequester::setIfreg(unsigned ifreg) {
ifreg_ = ifreg;
-
- if (intFlags.imeOrHalted())
- eventTimes.setValue(pendingIrqs() ? minIntTime : static_cast(DISABLED_TIME));
+
+ if (intFlags_.imeOrHalted()) {
+ eventTimes_.setValue(pendingIrqs()
+ ? minIntTime_
+ : static_cast(disabled_time));
+ }
}
SYNCFUNC(InterruptRequester)
{
- SSS(eventTimes);
- NSS(minIntTime);
+ SSS(eventTimes_);
+ NSS(minIntTime_);
NSS(ifreg_);
NSS(iereg_);
- NSS(intFlags.flags_);
+ NSS(intFlags_.flags_);
}
}
diff --git a/libgambatte/src/interruptrequester.h b/libgambatte/src/interruptrequester.h
index 8d22e35afb..cb54265078 100644
--- a/libgambatte/src/interruptrequester.h
+++ b/libgambatte/src/interruptrequester.h
@@ -1,21 +1,21 @@
-/***************************************************************************
- * Copyright (C) 2010 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2010 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#ifndef INTERRUPT_REQUESTER_H
#define INTERRUPT_REQUESTER_H
@@ -24,49 +24,29 @@
#include "newstate.h"
namespace gambatte {
+
struct SaveState;
-enum MemEventId { UNHALT, END, BLIT, SERIAL, OAM, DMA, TIMA, VIDEO, INTERRUPTS };
+
+enum IntEventId { intevent_unhalt,
+ intevent_end,
+ intevent_blit,
+ intevent_serial,
+ intevent_oam,
+ intevent_dma,
+ intevent_tima,
+ intevent_video,
+ intevent_interrupts, intevent_last = intevent_interrupts };
class InterruptRequester {
- MinKeeper eventTimes;
- unsigned long minIntTime;
- unsigned ifreg_;
- unsigned iereg_;
-
- class IntFlags {
- friend class InterruptRequester;
- unsigned char flags_;
- enum { IME_MASK = 1, HALTED_MASK = 2 };
-
- public:
- IntFlags() : flags_(0) {}
-
- bool ime() const { return flags_ & IME_MASK; }
- bool halted() const { return flags_ & HALTED_MASK; }
- bool imeOrHalted() const { return flags_; }
-
- void setIme() { flags_ |= IME_MASK; }
- void unsetIme() { flags_ &= ~IME_MASK; }
-
- void setHalted() { flags_ |= HALTED_MASK; }
- void unsetHalted() { flags_ &= ~HALTED_MASK; }
-
- void set(const bool ime, const bool halted) { flags_ = halted * HALTED_MASK + ime * IME_MASK; }
- } intFlags;
-
public:
InterruptRequester();
-
- void loadState(const SaveState &);
-
+ void loadState(SaveState const &);
void resetCc(unsigned long oldCc, unsigned long newCc);
-
unsigned ifreg() const { return ifreg_; }
unsigned iereg() const { return iereg_; }
unsigned pendingIrqs() const { return ifreg_ & iereg_; }
- bool ime() const { return intFlags.ime(); }
- bool halted() const { return intFlags.halted(); }
-
+ bool ime() const { return intFlags_.ime(); }
+ bool halted() const { return intFlags_.halted(); }
void ei(unsigned long cc);
void di();
void halt();
@@ -75,21 +55,48 @@ public:
void ackIrq(unsigned bit);
void setIereg(unsigned iereg);
void setIfreg(unsigned ifreg);
-
- MemEventId minEventId() const { return static_cast(eventTimes.min()); }
- unsigned long minEventTime() const { return eventTimes.minValue(); }
- template void setEventTime(unsigned long value) { eventTimes.setValue(value); }
- void setEventTime(const MemEventId id, unsigned long value) { eventTimes.setValue(id, value); }
- unsigned long eventTime(MemEventId id) const { return eventTimes.value(id); }
+ IntEventId minEventId() const { return static_cast(eventTimes_.min()); }
+ unsigned long minEventTime() const { return eventTimes_.minValue(); }
+ template void setEventTime(unsigned long value) { eventTimes_.setValue(value); }
+ void setEventTime(IntEventId id, unsigned long value) { eventTimes_.setValue(id, value); }
+ unsigned long eventTime(IntEventId id) const { return eventTimes_.value(id); }
+
+private:
+ class IntFlags {
+ friend class InterruptRequester;
+ public:
+ IntFlags() : flags_(0) {}
+ bool ime() const { return flags_ & flag_ime; }
+ bool halted() const { return flags_ & flag_halted; }
+ bool imeOrHalted() const { return flags_; }
+ void setIme() { flags_ |= flag_ime; }
+ void unsetIme() { flags_ &= ~flag_ime; }
+ void setHalted() { flags_ |= flag_halted; }
+ void unsetHalted() { flags_ &= ~flag_halted; }
+ void set(bool ime, bool halted) { flags_ = halted * flag_halted + ime * flag_ime; }
+
+ private:
+ unsigned char flags_;
+ enum { flag_ime = 1, flag_halted = 2 };
+ };
+
+ MinKeeper eventTimes_;
+ unsigned long minIntTime_;
+ unsigned ifreg_;
+ unsigned iereg_;
+ IntFlags intFlags_;
+
+
+public:
templatevoid SyncState(NewState *ns);
};
-inline void flagHdmaReq(InterruptRequester *const intreq) { intreq->setEventTime(0); }
-inline void flagGdmaReq(InterruptRequester *const intreq) { intreq->setEventTime(1); }
-inline void ackDmaReq(InterruptRequester *const intreq) { intreq->setEventTime(DISABLED_TIME); }
-inline bool hdmaReqFlagged(const InterruptRequester &intreq) { return intreq.eventTime(DMA) == 0; }
-inline bool gdmaReqFlagged(const InterruptRequester &intreq) { return intreq.eventTime(DMA) == 1; }
+inline void flagHdmaReq(InterruptRequester &intreq) { intreq.setEventTime(0); }
+inline void flagGdmaReq(InterruptRequester &intreq) { intreq.setEventTime(1); }
+inline void ackDmaReq(InterruptRequester &intreq) { intreq.setEventTime(disabled_time); }
+inline bool hdmaReqFlagged(InterruptRequester const &intreq) { return intreq.eventTime(intevent_dma) == 0; }
+inline bool gdmaReqFlagged(InterruptRequester const &intreq) { return intreq.eventTime(intevent_dma) == 1; }
}
diff --git a/libgambatte/src/mem/cartridge.cpp b/libgambatte/src/mem/cartridge.cpp
index e062fb0c96..0d6539af68 100644
--- a/libgambatte/src/mem/cartridge.cpp
+++ b/libgambatte/src/mem/cartridge.cpp
@@ -1,21 +1,21 @@
-/***************************************************************************
- * Copyright (C) 2007-2010 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2007-2010 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#include "cartridge.h"
#include "../savestate.h"
#include
@@ -27,7 +27,7 @@ namespace gambatte {
namespace {
-static unsigned toMulti64Rombank(const unsigned rombank) {
+static unsigned toMulti64Rombank(unsigned rombank) {
return (rombank >> 1 & 0x30) | (rombank & 0xF);
}
@@ -43,83 +43,71 @@ public:
};
class Mbc0 : public DefaultMbc {
- MemPtrs &memptrs;
- bool enableRam;
-
public:
explicit Mbc0(MemPtrs &memptrs)
- : memptrs(memptrs),
- enableRam(false)
+ : memptrs_(memptrs)
+ , enableRam_(false)
{
}
- virtual void romWrite(const unsigned P, const unsigned data) {
- if (P < 0x2000) {
- enableRam = (data & 0xF) == 0xA;
- memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0);
+ virtual void romWrite(unsigned const p, unsigned const data, unsigned long const /*cc*/) {
+ if (p < 0x2000) {
+ enableRam_ = (data & 0xF) == 0xA;
+ memptrs_.setRambank(enableRam_ ? MemPtrs::read_en | MemPtrs::write_en : 0, 0);
}
}
- virtual void saveState(SaveState::Mem &ss) const {
- ss.enableRam = enableRam;
+ virtual void loadState(SaveState::Mem const &ss) {
+ enableRam_ = ss.enableRam;
+ memptrs_.setRambank(enableRam_ ? MemPtrs::read_en | MemPtrs::write_en : 0, 0);
}
- virtual void loadState(const SaveState::Mem &ss) {
- enableRam = ss.enableRam;
- memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0);
- }
+private:
+ MemPtrs &memptrs_;
+ bool enableRam_;
+public:
virtual void SyncState(NewState *ns, bool isReader)
{
- NSS(enableRam);
+ NSS(enableRam_);
}
};
-static inline unsigned rambanks(const MemPtrs &memptrs) {
- return static_cast(memptrs.rambankdataend() - memptrs.rambankdata()) / 0x2000;
+static inline unsigned rambanks(MemPtrs const &memptrs) {
+ return std::size_t(memptrs.rambankdataend() - memptrs.rambankdata()) / 0x2000;
}
-static inline unsigned rombanks(const MemPtrs &memptrs) {
- return static_cast(memptrs.romdataend() - memptrs.romdata() ) / 0x4000;
+static inline unsigned rombanks(MemPtrs const &memptrs) {
+ return std::size_t(memptrs.romdataend() - memptrs.romdata() ) / 0x4000;
}
class Mbc1 : public DefaultMbc {
- MemPtrs &memptrs;
- unsigned char rombank;
- unsigned char rambank;
- bool enableRam;
- bool rambankMode;
-
- static unsigned adjustedRombank(unsigned bank) { return bank & 0x1F ? bank : bank | 1; }
- void setRambank() const { memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, rambank & (rambanks(memptrs) - 1)); }
- void setRombank() const { memptrs.setRombank(adjustedRombank(rombank & (rombanks(memptrs) - 1))); }
-
public:
explicit Mbc1(MemPtrs &memptrs)
- : memptrs(memptrs),
- rombank(1),
- rambank(0),
- enableRam(false),
- rambankMode(false)
+ : memptrs_(memptrs)
+ , rombank_(1)
+ , rambank_(0)
+ , enableRam_(false)
+ , rambankMode_(false)
{
}
- virtual void romWrite(const unsigned P, const unsigned data) {
- switch (P >> 13 & 3) {
+ virtual void romWrite(unsigned const p, unsigned const data, unsigned long const /*cc*/) {
+ switch (p >> 13 & 3) {
case 0:
- enableRam = (data & 0xF) == 0xA;
+ enableRam_ = (data & 0xF) == 0xA;
setRambank();
break;
case 1:
- rombank = rambankMode ? data & 0x1F : (rombank & 0x60) | (data & 0x1F);
+ rombank_ = rambankMode_ ? data & 0x1F : (rombank_ & 0x60) | (data & 0x1F);
setRombank();
break;
case 2:
- if (rambankMode) {
- rambank = data & 3;
+ if (rambankMode_) {
+ rambank_ = data & 3;
setRambank();
} else {
- rombank = (data << 5 & 0x60) | (rombank & 0x1F);
+ rombank_ = (data << 5 & 0x60) | (rombank_ & 0x1F);
setRombank();
}
@@ -127,337 +115,329 @@ public:
case 3:
// Pretty sure this should take effect immediately, but I have a policy not to change old behavior
// unless I have something (eg. a verified test or a game) that justifies it.
- rambankMode = data & 1;
+ rambankMode_ = data & 1;
break;
}
}
- virtual void saveState(SaveState::Mem &ss) const {
- ss.rombank = rombank;
- ss.rambank = rambank;
- ss.enableRam = enableRam;
- ss.rambankMode = rambankMode;
- }
-
- virtual void loadState(const SaveState::Mem &ss) {
- rombank = ss.rombank;
- rambank = ss.rambank;
- enableRam = ss.enableRam;
- rambankMode = ss.rambankMode;
+ virtual void loadState(SaveState::Mem const &ss) {
+ rombank_ = ss.rombank;
+ rambank_ = ss.rambank;
+ enableRam_ = ss.enableRam;
+ rambankMode_ = ss.rambankMode;
setRambank();
setRombank();
}
+private:
+ MemPtrs &memptrs_;
+ unsigned char rombank_;
+ unsigned char rambank_;
+ bool enableRam_;
+ bool rambankMode_;
+
+ static unsigned adjustedRombank(unsigned bank) { return bank & 0x1F ? bank : bank | 1; }
+
+ void setRambank() const {
+ memptrs_.setRambank(enableRam_ ? MemPtrs::read_en | MemPtrs::write_en : 0,
+ rambank_ & (rambanks(memptrs_) - 1));
+ }
+
+ void setRombank() const { memptrs_.setRombank(adjustedRombank(rombank_) & (rombanks(memptrs_) - 1)); }
+
+
+public:
virtual void SyncState(NewState *ns, bool isReader)
{
- NSS(rombank);
- NSS(rambank);
- NSS(enableRam);
- NSS(rambankMode);
+ NSS(rombank_);
+ NSS(rambank_);
+ NSS(enableRam_);
+ NSS(rambankMode_);
}
};
class Mbc1Multi64 : public Mbc {
- MemPtrs &memptrs;
- unsigned char rombank;
- bool enableRam;
- bool rombank0Mode;
-
- static unsigned adjustedRombank(unsigned bank) { return bank & 0x1F ? bank : bank | 1; }
-
- void setRombank() const {
- if (rombank0Mode) {
- const unsigned rb = toMulti64Rombank(rombank);
- memptrs.setRombank0(rb & 0x30);
- memptrs.setRombank(adjustedRombank(rb));
- } else {
- memptrs.setRombank0(0);
- memptrs.setRombank(adjustedRombank(rombank & (rombanks(memptrs) - 1)));
- }
- }
-
public:
explicit Mbc1Multi64(MemPtrs &memptrs)
- : memptrs(memptrs),
- rombank(1),
- enableRam(false),
- rombank0Mode(false)
+ : memptrs_(memptrs)
+ , rombank_(1)
+ , enableRam_(false)
+ , rombank0Mode_(false)
{
}
- virtual void romWrite(const unsigned P, const unsigned data) {
- switch (P >> 13 & 3) {
+ virtual void romWrite(unsigned const p, unsigned const data, unsigned long const /*cc*/) {
+ switch (p >> 13 & 3) {
case 0:
- enableRam = (data & 0xF) == 0xA;
- memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0);
+ enableRam_ = (data & 0xF) == 0xA;
+ memptrs_.setRambank(enableRam_ ? MemPtrs::read_en | MemPtrs::write_en : 0, 0);
break;
case 1:
- rombank = (rombank & 0x60) | (data & 0x1F);
- memptrs.setRombank(adjustedRombank(rombank0Mode ? toMulti64Rombank(rombank) : rombank & (rombanks(memptrs) - 1)));
+ rombank_ = (rombank_ & 0x60) | (data & 0x1F);
+ memptrs_.setRombank(rombank0Mode_
+ ? adjustedRombank(toMulti64Rombank(rombank_))
+ : adjustedRombank(rombank_) & (rombanks(memptrs_) - 1));
break;
case 2:
- rombank = (data << 5 & 0x60) | (rombank & 0x1F);
+ rombank_ = (data << 5 & 0x60) | (rombank_ & 0x1F);
setRombank();
break;
case 3:
- rombank0Mode = data & 1;
+ rombank0Mode_ = data & 1;
setRombank();
break;
}
}
- virtual void saveState(SaveState::Mem &ss) const {
- ss.rombank = rombank;
- ss.enableRam = enableRam;
- ss.rambankMode = rombank0Mode;
- }
-
- virtual void loadState(const SaveState::Mem &ss) {
- rombank = ss.rombank;
- enableRam = ss.enableRam;
- rombank0Mode = ss.rambankMode;
- memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0);
+ virtual void loadState(SaveState::Mem const &ss) {
+ rombank_ = ss.rombank;
+ enableRam_ = ss.enableRam;
+ rombank0Mode_ = ss.rambankMode;
+ memptrs_.setRambank(enableRam_ ? MemPtrs::read_en | MemPtrs::write_en : 0, 0);
setRombank();
}
-
+
virtual bool isAddressWithinAreaRombankCanBeMappedTo(unsigned addr, unsigned bank) const {
return (addr < 0x4000) == ((bank & 0xF) == 0);
}
+private:
+ MemPtrs &memptrs_;
+ unsigned char rombank_;
+ bool enableRam_;
+ bool rombank0Mode_;
+
+ static unsigned adjustedRombank(unsigned bank) { return bank & 0x1F ? bank : bank | 1; }
+
+ void setRombank() const {
+ if (rombank0Mode_) {
+ unsigned const rb = toMulti64Rombank(rombank_);
+ memptrs_.setRombank0(rb & 0x30);
+ memptrs_.setRombank(adjustedRombank(rb));
+ } else {
+ memptrs_.setRombank0(0);
+ memptrs_.setRombank(adjustedRombank(rombank_) & (rombanks(memptrs_) - 1));
+ }
+ }
+
+public:
virtual void SyncState(NewState *ns, bool isReader)
{
- NSS(rombank);
- NSS(enableRam);
- NSS(rombank0Mode);
+ NSS(rombank_);
+ NSS(enableRam_);
+ NSS(rombank0Mode_);
}
};
class Mbc2 : public DefaultMbc {
- MemPtrs &memptrs;
- unsigned char rombank;
- bool enableRam;
-
public:
explicit Mbc2(MemPtrs &memptrs)
- : memptrs(memptrs),
- rombank(1),
- enableRam(false)
+ : memptrs_(memptrs)
+ , rombank_(1)
+ , enableRam_(false)
{
}
- virtual void romWrite(const unsigned P, const unsigned data) {
- switch (P & 0x6100) {
+ virtual void romWrite(unsigned const p, unsigned const data, unsigned long const /*cc*/) {
+ switch (p & 0x6100) {
case 0x0000:
- enableRam = (data & 0xF) == 0xA;
- memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0);
+ enableRam_ = (data & 0xF) == 0xA;
+ memptrs_.setRambank(enableRam_ ? MemPtrs::read_en | MemPtrs::write_en : 0, 0);
break;
case 0x2100:
- rombank = data & 0xF;
- memptrs.setRombank(rombank & (rombanks(memptrs) - 1));
+ rombank_ = data & 0xF;
+ memptrs_.setRombank(rombank_ & (rombanks(memptrs_) - 1));
break;
}
}
- virtual void saveState(SaveState::Mem &ss) const {
- ss.rombank = rombank;
- ss.enableRam = enableRam;
+ virtual void loadState(SaveState::Mem const &ss) {
+ rombank_ = ss.rombank;
+ enableRam_ = ss.enableRam;
+ memptrs_.setRambank(enableRam_ ? MemPtrs::read_en | MemPtrs::write_en : 0, 0);
+ memptrs_.setRombank(rombank_ & (rombanks(memptrs_) - 1));
}
- virtual void loadState(const SaveState::Mem &ss) {
- rombank = ss.rombank;
- enableRam = ss.enableRam;
- memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0);
- memptrs.setRombank(rombank & (rombanks(memptrs) - 1));
- }
+private:
+ MemPtrs &memptrs_;
+ unsigned char rombank_;
+ bool enableRam_;
+public:
virtual void SyncState(NewState *ns, bool isReader)
{
- NSS(rombank);
- NSS(enableRam);
+ NSS(rombank_);
+ NSS(enableRam_);
}
};
class Mbc3 : public DefaultMbc {
- MemPtrs &memptrs;
- Rtc *const rtc;
- unsigned char rombank;
- unsigned char rambank;
- bool enableRam;
-
- static unsigned adjustedRombank(unsigned bank) { return bank & 0x7F ? bank : bank | 1; }
- void setRambank() const {
- unsigned flags = enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0;
-
- if (rtc) {
- rtc->set(enableRam, rambank);
-
- if (rtc->getActive())
- flags |= MemPtrs::RTC_EN;
- }
-
- memptrs.setRambank(flags, rambank & (rambanks(memptrs) - 1));
- }
- // we adjust the rombank before masking with size? this seems correct, as how would the mbc
- // know that high rom address outputs were not connected
- void setRombank() const { memptrs.setRombank(adjustedRombank(rombank) & (rombanks(memptrs) - 1)); }
-
public:
Mbc3(MemPtrs &memptrs, Rtc *const rtc)
- : memptrs(memptrs),
- rtc(rtc),
- rombank(1),
- rambank(0),
- enableRam(false)
+ : memptrs_(memptrs)
+ , rtc_(rtc)
+ , rombank_(1)
+ , rambank_(0)
+ , enableRam_(false)
{
}
- virtual void romWrite(const unsigned P, const unsigned data) {
- switch (P >> 13 & 3) {
+ virtual void romWrite(unsigned const p, unsigned const data, unsigned long const cc) {
+ switch (p >> 13 & 3) {
case 0:
- enableRam = (data & 0xF) == 0xA;
+ enableRam_ = (data & 0xF) == 0xA;
setRambank();
break;
case 1:
- rombank = data & 0x7F;
+ rombank_ = data & 0x7F;
setRombank();
break;
case 2:
- rambank = data;
+ rambank_ = data;
setRambank();
break;
case 3:
- if (rtc)
- rtc->latch(data);
+ if (rtc_)
+ rtc_->latch(data, cc);
break;
}
}
- virtual void saveState(SaveState::Mem &ss) const {
- ss.rombank = rombank;
- ss.rambank = rambank;
- ss.enableRam = enableRam;
- }
-
- virtual void loadState(const SaveState::Mem &ss) {
- rombank = ss.rombank;
- rambank = ss.rambank;
- enableRam = ss.enableRam;
+ virtual void loadState(SaveState::Mem const &ss) {
+ rombank_ = ss.rombank;
+ rambank_ = ss.rambank;
+ enableRam_ = ss.enableRam;
setRambank();
setRombank();
}
+private:
+ MemPtrs &memptrs_;
+ Rtc *const rtc_;
+ unsigned char rombank_;
+ unsigned char rambank_;
+ bool enableRam_;
+
+ void setRambank() const {
+ unsigned flags = enableRam_ ? MemPtrs::read_en | MemPtrs::write_en : 0;
+
+ if (rtc_) {
+ rtc_->set(enableRam_, rambank_);
+
+ if (rtc_->activeData())
+ flags |= MemPtrs::rtc_en;
+ }
+
+ memptrs_.setRambank(flags, rambank_ & (rambanks(memptrs_) - 1));
+ }
+
+ void setRombank() const {
+ memptrs_.setRombank(std::max(rombank_ & (rombanks(memptrs_) - 1), 1u));
+ }
+
+public:
virtual void SyncState(NewState *ns, bool isReader)
{
- NSS(rombank);
- NSS(rambank);
- NSS(enableRam);
+ NSS(rombank_);
+ NSS(rambank_);
+ NSS(enableRam_);
}
};
class HuC1 : public DefaultMbc {
- MemPtrs &memptrs;
- unsigned char rombank;
- unsigned char rambank;
- bool enableRam;
- bool rambankMode;
-
- void setRambank() const {
- memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : MemPtrs::READ_EN,
- rambankMode ? rambank & (rambanks(memptrs) - 1) : 0);
- }
-
- void setRombank() const { memptrs.setRombank((rambankMode ? rombank : rambank << 6 | rombank) & (rombanks(memptrs) - 1)); }
-
public:
explicit HuC1(MemPtrs &memptrs)
- : memptrs(memptrs),
- rombank(1),
- rambank(0),
- enableRam(false),
- rambankMode(false)
+ : memptrs_(memptrs)
+ , rombank_(1)
+ , rambank_(0)
+ , enableRam_(false)
+ , rambankMode_(false)
{
}
- virtual void romWrite(const unsigned P, const unsigned data) {
- switch (P >> 13 & 3) {
+ virtual void romWrite(unsigned const p, unsigned const data, unsigned long const /*cc*/) {
+ switch (p >> 13 & 3) {
case 0:
- enableRam = (data & 0xF) == 0xA;
+ enableRam_ = (data & 0xF) == 0xA;
setRambank();
break;
case 1:
- rombank = data & 0x3F;
+ rombank_ = data & 0x3F;
setRombank();
break;
case 2:
- rambank = data & 3;
- rambankMode ? setRambank() : setRombank();
+ rambank_ = data & 3;
+ rambankMode_ ? setRambank() : setRombank();
break;
case 3:
- rambankMode = data & 1;
+ rambankMode_ = data & 1;
setRambank();
setRombank();
break;
}
}
- virtual void saveState(SaveState::Mem &ss) const {
- ss.rombank = rombank;
- ss.rambank = rambank;
- ss.enableRam = enableRam;
- ss.rambankMode = rambankMode;
- }
-
- virtual void loadState(const SaveState::Mem &ss) {
- rombank = ss.rombank;
- rambank = ss.rambank;
- enableRam = ss.enableRam;
- rambankMode = ss.rambankMode;
+ virtual void loadState(SaveState::Mem const &ss) {
+ rombank_ = ss.rombank;
+ rambank_ = ss.rambank;
+ enableRam_ = ss.enableRam;
+ rambankMode_ = ss.rambankMode;
setRambank();
setRombank();
}
+private:
+ MemPtrs &memptrs_;
+ unsigned char rombank_;
+ unsigned char rambank_;
+ bool enableRam_;
+ bool rambankMode_;
+
+ void setRambank() const {
+ memptrs_.setRambank(enableRam_ ? MemPtrs::read_en | MemPtrs::write_en : MemPtrs::read_en,
+ rambankMode_ ? rambank_ & (rambanks(memptrs_) - 1) : 0);
+ }
+
+ void setRombank() const {
+ memptrs_.setRombank((rambankMode_ ? rombank_ : rambank_ << 6 | rombank_)
+ & (rombanks(memptrs_) - 1));
+ }
+
+public:
virtual void SyncState(NewState *ns, bool isReader)
{
- NSS(rombank);
- NSS(rambank);
- NSS(enableRam);
- NSS(rambankMode);
+ NSS(rombank_);
+ NSS(rambank_);
+ NSS(enableRam_);
+ NSS(rambankMode_);
}
};
class Mbc5 : public DefaultMbc {
- MemPtrs &memptrs;
- unsigned short rombank;
- unsigned char rambank;
- bool enableRam;
-
- static unsigned adjustedRombank(const unsigned bank) { return bank; }
- void setRambank() const { memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, rambank & (rambanks(memptrs) - 1)); }
- void setRombank() const { memptrs.setRombank(adjustedRombank(rombank & (rombanks(memptrs) - 1))); }
-
public:
explicit Mbc5(MemPtrs &memptrs)
- : memptrs(memptrs),
- rombank(1),
- rambank(0),
- enableRam(false)
+ : memptrs_(memptrs)
+ , rombank_(1)
+ , rambank_(0)
+ , enableRam_(false)
{
}
- virtual void romWrite(const unsigned P, const unsigned data) {
- switch (P >> 13 & 3) {
+ virtual void romWrite(unsigned const p, unsigned const data, unsigned long const /*cc*/) {
+ switch (p >> 13 & 3) {
case 0:
- enableRam = (data & 0xF) == 0xA;
+ enableRam_ = (data & 0xF) == 0xA;
setRambank();
break;
case 1:
- rombank = P < 0x3000 ? (rombank & 0x100) | data
- : (data << 8 & 0x100) | (rombank & 0xFF);
+ rombank_ = p < 0x3000
+ ? (rombank_ & 0x100) | data
+ : (data << 8 & 0x100) | (rombank_ & 0xFF);
setRombank();
break;
case 2:
- rambank = data & 0xF;
+ rambank_ = data & 0xF;
setRambank();
break;
case 3:
@@ -465,29 +445,39 @@ public:
}
}
- virtual void saveState(SaveState::Mem &ss) const {
- ss.rombank = rombank;
- ss.rambank = rambank;
- ss.enableRam = enableRam;
- }
-
- virtual void loadState(const SaveState::Mem &ss) {
- rombank = ss.rombank;
- rambank = ss.rambank;
- enableRam = ss.enableRam;
+ virtual void loadState(SaveState::Mem const &ss) {
+ rombank_ = ss.rombank;
+ rambank_ = ss.rambank;
+ enableRam_ = ss.enableRam;
setRambank();
setRombank();
}
+private:
+ MemPtrs &memptrs_;
+ unsigned short rombank_;
+ unsigned char rambank_;
+ bool enableRam_;
+
+ static unsigned adjustedRombank(unsigned bank) { return bank; }
+
+ void setRambank() const {
+ memptrs_.setRambank(enableRam_ ? MemPtrs::read_en | MemPtrs::write_en : 0,
+ rambank_ & (rambanks(memptrs_) - 1));
+ }
+
+ void setRombank() const { memptrs_.setRombank(adjustedRombank(rombank_) & (rombanks(memptrs_) - 1)); }
+
+public:
virtual void SyncState(NewState *ns, bool isReader)
{
- NSS(rombank);
- NSS(rambank);
- NSS(enableRam);
+ NSS(rombank_);
+ NSS(rambank_);
+ NSS(enableRam_);
}
};
-static bool hasRtc(const unsigned headerByte0x147) {
+static bool hasRtc(unsigned headerByte0x147) {
switch (headerByte0x147) {
case 0x0F:
case 0x10: return true;
@@ -497,20 +487,25 @@ static bool hasRtc(const unsigned headerByte0x147) {
}
+Cartridge::Cartridge()
+: rtc_(time_)
+{
+}
+
void Cartridge::setStatePtrs(SaveState &state) {
- state.mem.vram.set(memptrs.vramdata(), memptrs.vramdataend() - memptrs.vramdata());
- state.mem.sram.set(memptrs.rambankdata(), memptrs.rambankdataend() - memptrs.rambankdata());
- state.mem.wram.set(memptrs.wramdata(0), memptrs.wramdataend() - memptrs.wramdata(0));
+ state.mem.vram.set(memptrs_.vramdata(), memptrs_.vramdataend() - memptrs_.vramdata());
+ state.mem.sram.set(memptrs_.rambankdata(), memptrs_.rambankdataend() - memptrs_.rambankdata());
+ state.mem.wram.set(memptrs_.wramdata(0), memptrs_.wramdataend() - memptrs_.wramdata(0));
}
-void Cartridge::loadState(const SaveState &state) {
- rtc.loadState(state);
- mbc->loadState(state.mem);
+void Cartridge::loadState(SaveState const &state) {
+ rtc_.loadState(state);
+ mbc_->loadState(state.mem);
}
-static void enforce8bit(unsigned char *data, unsigned long sz) {
+static void enforce8bit(unsigned char *data, std::size_t size) {
if (static_cast(0x100))
- while (sz--)
+ while (size--)
*data++ &= 0xFF;
}
@@ -525,56 +520,74 @@ static unsigned pow2ceil(unsigned n) {
return n;
}
-int Cartridge::loadROM(const char *romfiledata, unsigned romfilelength, const bool forceDmg, const bool multicartCompat) {
- //const std::auto_ptr rom(newFileInstance(romfile));
+static bool isMbc2(unsigned char h147) { return h147 == 5 || h147 == 6; }
- //if (rom->fail())
- // return -1;
-
+static unsigned numRambanksFromH14x(unsigned char h147, unsigned char h149) {
+ switch (h149) {
+ case 0x00: return isMbc2(h147) ? 1 : 0;
+ case 0x01:
+ case 0x02: return 1;
+ }
+
+ return 4;
+}
+
+static bool presumedMulti64Mbc1(unsigned char const header[], unsigned rombanks) {
+ return header[0x147] == 1 && header[0x149] == 0 && rombanks == 64;
+}
+
+LoadRes Cartridge::loadROM(char const *romfiledata, unsigned romfilelength, bool const forceDmg, bool const multicartCompat) {
+ enum Cartridgetype { type_plain,
+ type_mbc1,
+ type_mbc2,
+ type_mbc3,
+ type_mbc5,
+ type_huc1 };
+ Cartridgetype type = type_plain;
unsigned rambanks = 1;
unsigned rombanks = 2;
bool cgb = false;
- enum Cartridgetype { PLAIN, MBC1, MBC2, MBC3, MBC5, HUC1 } type = PLAIN;
{
unsigned char header[0x150];
- //rom->read(reinterpret_cast(header), sizeof header);
if (romfilelength >= sizeof header)
std::memcpy(header, romfiledata, sizeof header);
else
- return -1;
+ return LOADRES_IO_ERROR;
switch (header[0x0147]) {
- case 0x00: std::puts("Plain ROM loaded."); type = PLAIN; break;
- case 0x01: std::puts("MBC1 ROM loaded."); type = MBC1; break;
- case 0x02: std::puts("MBC1 ROM+RAM loaded."); type = MBC1; break;
- case 0x03: std::puts("MBC1 ROM+RAM+BATTERY loaded."); type = MBC1; break;
- case 0x05: std::puts("MBC2 ROM loaded."); type = MBC2; break;
- case 0x06: std::puts("MBC2 ROM+BATTERY loaded."); type = MBC2; break;
- case 0x08: std::puts("Plain ROM with additional RAM loaded."); type = PLAIN; break;
- case 0x09: std::puts("Plain ROM with additional RAM and Battery loaded."); type = PLAIN; break;
- case 0x0B: std::puts("MM01 ROM not supported."); return -1;
- case 0x0C: std::puts("MM01 ROM not supported."); return -1;
- case 0x0D: std::puts("MM01 ROM not supported."); return -1;
- case 0x0F: std::puts("MBC3 ROM+TIMER+BATTERY loaded."); type = MBC3; break;
- case 0x10: std::puts("MBC3 ROM+TIMER+RAM+BATTERY loaded."); type = MBC3; break;
- case 0x11: std::puts("MBC3 ROM loaded."); type = MBC3; break;
- case 0x12: std::puts("MBC3 ROM+RAM loaded."); type = MBC3; break;
- case 0x13: std::puts("MBC3 ROM+RAM+BATTERY loaded."); type = MBC3; break;
- case 0x15: std::puts("MBC4 ROM not supported."); return -1;
- case 0x16: std::puts("MBC4 ROM not supported."); return -1;
- case 0x17: std::puts("MBC4 ROM not supported."); return -1;
- case 0x19: std::puts("MBC5 ROM loaded."); type = MBC5; break;
- case 0x1A: std::puts("MBC5 ROM+RAM loaded."); type = MBC5; break;
- case 0x1B: std::puts("MBC5 ROM+RAM+BATTERY loaded."); type = MBC5; break;
- case 0x1C: std::puts("MBC5+RUMBLE ROM not supported."); type = MBC5; break;
- case 0x1D: std::puts("MBC5+RUMBLE+RAM ROM not suported."); type = MBC5; break;
- case 0x1E: std::puts("MBC5+RUMBLE+RAM+BATTERY ROM not supported."); type = MBC5; break;
- case 0xFC: std::puts("Pocket Camera ROM not supported."); return -1;
- case 0xFD: std::puts("Bandai TAMA5 ROM not supported."); return -1;
- case 0xFE: std::puts("HuC3 ROM not supported."); return -1;
- case 0xFF: std::puts("HuC1 ROM+RAM+BATTERY loaded."); type = HUC1; break;
- default: std::puts("Wrong data-format, corrupt or unsupported ROM."); return -1;
+ case 0x00: type = type_plain; break;
+ case 0x01:
+ case 0x02:
+ case 0x03: type = type_mbc1; break;
+ case 0x05:
+ case 0x06: type = type_mbc2; break;
+ case 0x08:
+ case 0x09: type = type_plain; break;
+ case 0x0B:
+ case 0x0C:
+ case 0x0D: return LOADRES_UNSUPPORTED_MBC_MMM01;
+ case 0x0F:
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13: type = type_mbc3; break;
+ case 0x15:
+ case 0x16:
+ case 0x17: return LOADRES_UNSUPPORTED_MBC_MBC4;
+ case 0x19:
+ case 0x1A:
+ case 0x1B:
+ case 0x1C:
+ case 0x1D:
+ case 0x1E: type = type_mbc5; break;
+ case 0x20: return LOADRES_UNSUPPORTED_MBC_MBC6;
+ case 0x22: return LOADRES_UNSUPPORTED_MBC_MBC7;
+ case 0xFC: return LOADRES_UNSUPPORTED_MBC_POCKET_CAMERA;
+ case 0xFD: return LOADRES_UNSUPPORTED_MBC_TAMA5;
+ case 0xFE: return LOADRES_UNSUPPORTED_MBC_HUC3;
+ case 0xFF: type = type_huc1; break;
+ default: return LOADRES_BAD_FILE_OR_UNKNOWN_MBC;
}
/*switch (header[0x0148]) {
@@ -591,73 +604,45 @@ int Cartridge::loadROM(const char *romfiledata, unsigned romfilelength, const bo
case 0x53: rombanks = 80; break;
case 0x54: rombanks = 96; break;
default: return -1;
- }
+ }*/
- std::printf("rombanks: %u\n", rombanks);*/
-
- switch (header[0x0149]) {
- case 0x00: /*std::puts("No RAM");*/ rambanks = type == MBC2; break;
- case 0x01: /*std::puts("2kB RAM");*/ /*rambankrom=1; break;*/
- case 0x02: /*std::puts("8kB RAM");*/
- rambanks = 1;
- break;
- case 0x03: /*std::puts("32kB RAM");*/
- rambanks = 4;
- break;
- case 0x04: /*std::puts("128kB RAM");*/
- rambanks = 16;
- break;
- case 0x05: /*std::puts("undocumented kB RAM");*/
- rambanks = 16;
- break;
- default: /*std::puts("Wrong data-format, corrupt or unsupported ROM loaded.");*/
- rambanks = 16;
- break;
- }
-
+ rambanks = numRambanksFromH14x(header[0x147], header[0x149]);
cgb = !forceDmg;
- std::printf("cgb: %d\n", cgb);
}
-
- std::printf("rambanks: %u\n", rambanks);
-
- const std::size_t filesize = romfilelength; //rom->size();
+ std::size_t const filesize = romfilelength;
rombanks = std::max(pow2ceil(filesize / 0x4000), 2u);
- std::printf("rombanks: %u\n", static_cast(filesize / 0x4000));
-
- mbc.reset();
- memptrs.reset(rombanks, rambanks, cgb ? 8 : 2);
- rtc.set(false, 0);
- //rom->rewind();
- //rom->read(reinterpret_cast(memptrs.romdata()), (filesize / 0x4000) * 0x4000ul);
- std::memcpy(memptrs.romdata(), romfiledata, (filesize / 0x4000) * 0x4000ul);
- std::memset(memptrs.romdata() + (filesize / 0x4000) * 0x4000ul, 0xFF, (rombanks - filesize / 0x4000) * 0x4000ul);
- enforce8bit(memptrs.romdata(), rombanks * 0x4000ul);
-
- //if (rom->fail())
- // return -1;
-
+ mbc_.reset();
+ memptrs_.reset(rombanks, rambanks, cgb ? 8 : 2);
+ rtc_.set(false, 0);
+
+ std::memcpy(memptrs_.romdata(), romfiledata, (filesize / 0x4000) * 0x4000ul);
+ std::memset(memptrs_.romdata() + filesize / 0x4000 * 0x4000ul,
+ 0xFF,
+ (rombanks - filesize / 0x4000) * 0x4000ul);
+ enforce8bit(memptrs_.romdata(), rombanks * 0x4000ul);
+
switch (type) {
- case PLAIN: mbc.reset(new Mbc0(memptrs)); break;
- case MBC1:
- if (!rambanks && rombanks == 64 && multicartCompat) {
- std::puts("Multi-ROM \"MBC1\" presumed");
- mbc.reset(new Mbc1Multi64(memptrs));
+ case type_plain: mbc_.reset(new Mbc0(memptrs_)); break;
+ case type_mbc1:
+ if (multicartCompat && presumedMulti64Mbc1(memptrs_.romdata(), rombanks)) {
+ mbc_.reset(new Mbc1Multi64(memptrs_));
} else
- mbc.reset(new Mbc1(memptrs));
+ mbc_.reset(new Mbc1(memptrs_));
break;
- case MBC2: mbc.reset(new Mbc2(memptrs)); break;
- case MBC3: mbc.reset(new Mbc3(memptrs, hasRtc(memptrs.romdata()[0x147]) ? &rtc : 0)); break;
- case MBC5: mbc.reset(new Mbc5(memptrs)); break;
- case HUC1: mbc.reset(new HuC1(memptrs)); break;
+ case type_mbc2: mbc_.reset(new Mbc2(memptrs_)); break;
+ case type_mbc3:
+ mbc_.reset(new Mbc3(memptrs_, hasRtc(memptrs_.romdata()[0x147]) ? &rtc_ : 0));
+ break;
+ case type_mbc5: mbc_.reset(new Mbc5(memptrs_)); break;
+ case type_huc1: mbc_.reset(new HuC1(memptrs_)); break;
}
- return 0;
+ return LOADRES_OK;
}
-static bool hasBattery(const unsigned char headerByte0x147) {
+static bool hasBattery(unsigned char headerByte0x147) {
switch (headerByte0x147) {
case 0x03:
case 0x06:
@@ -672,42 +657,57 @@ static bool hasBattery(const unsigned char headerByte0x147) {
}
}
-void Cartridge::loadSavedata(const char *data) {
- if (hasBattery(memptrs.romdata()[0x147])) {
- int length = memptrs.rambankdataend() - memptrs.rambankdata();
- std::memcpy(memptrs.rambankdata(), data, length);
+void Cartridge::loadSavedata(char const *data, unsigned long const cc) {
+ if (hasBattery(memptrs_.romdata()[0x147])) {
+ int length = memptrs_.rambankdataend() - memptrs_.rambankdata();
+ std::memcpy(memptrs_.rambankdata(), data, length);
data += length;
- enforce8bit(memptrs.rambankdata(), length);
+ enforce8bit(memptrs_.rambankdata(), length);
}
- if (hasRtc(memptrs.romdata()[0x147])) {
- unsigned long basetime;
- std::memcpy(&basetime, data, 4);
- rtc.setBaseTime(basetime);
+ if (hasRtc(memptrs_.romdata()[0x147])) {
+ timeval basetime;
+ basetime.tv_sec = (*data++);
+ basetime.tv_sec = basetime.tv_sec << 8 | (*data++);
+ basetime.tv_sec = basetime.tv_sec << 8 | (*data++);
+ basetime.tv_sec = basetime.tv_sec << 8 | (*data++);
+ basetime.tv_usec = (*data++);
+ basetime.tv_usec = basetime.tv_usec << 8 | (*data++);
+ basetime.tv_usec = basetime.tv_usec << 8 | (*data++);
+ basetime.tv_usec = basetime.tv_usec << 8 | (*data++);
+
+ time_.setBaseTime(basetime, cc);
}
}
int Cartridge::saveSavedataLength() {
int ret = 0;
- if (hasBattery(memptrs.romdata()[0x147])) {
- ret = memptrs.rambankdataend() - memptrs.rambankdata();
+ if (hasBattery(memptrs_.romdata()[0x147])) {
+ ret = memptrs_.rambankdataend() - memptrs_.rambankdata();
}
- if (hasRtc(memptrs.romdata()[0x147])) {
- ret += 4;
+ if (hasRtc(memptrs_.romdata()[0x147])) {
+ ret += 8;
}
return ret;
}
-void Cartridge::saveSavedata(char *dest) {
- if (hasBattery(memptrs.romdata()[0x147])) {
- int length = memptrs.rambankdataend() - memptrs.rambankdata();
- std::memcpy(dest, memptrs.rambankdata(), length);
+void Cartridge::saveSavedata(char *dest, unsigned long const cc) {
+ if (hasBattery(memptrs_.romdata()[0x147])) {
+ int length = memptrs_.rambankdataend() - memptrs_.rambankdata();
+ std::memcpy(dest, memptrs_.rambankdata(), length);
dest += length;
}
- if (hasRtc(memptrs.romdata()[0x147])) {
- const unsigned long basetime = rtc.getBaseTime();
- std::memcpy(dest, &basetime, 4);
+ if (hasRtc(memptrs_.romdata()[0x147])) {
+ timeval basetime = time_.baseTime(cc);
+ *dest++ = (basetime.tv_sec >> 24 & 0xFF);
+ *dest++ = (basetime.tv_sec >> 16 & 0xFF);
+ *dest++ = (basetime.tv_sec >> 8 & 0xFF);
+ *dest++ = (basetime.tv_sec & 0xFF);
+ *dest++ = (basetime.tv_usec >> 24 & 0xFF);
+ *dest++ = (basetime.tv_usec >> 16 & 0xFF);
+ *dest++ = (basetime.tv_usec >> 8 & 0xFF);
+ *dest++ = (basetime.tv_usec & 0xFF);
}
}
@@ -718,20 +718,20 @@ bool Cartridge::getMemoryArea(int which, unsigned char **data, int *length) cons
switch (which)
{
case 0:
- *data = memptrs.vramdata();
- *length = memptrs.vramdataend() - memptrs.vramdata();
+ *data = memptrs_.vramdata();
+ *length = memptrs_.vramdataend() - memptrs_.vramdata();
return true;
case 1:
- *data = memptrs.romdata();
- *length = memptrs.romdataend() - memptrs.romdata();
+ *data = memptrs_.romdata();
+ *length = memptrs_.romdataend() - memptrs_.romdata();
return true;
case 2:
- *data = memptrs.wramdata(0);
- *length = memptrs.wramdataend() - memptrs.wramdata(0);
+ *data = memptrs_.wramdata(0);
+ *length = memptrs_.wramdataend() - memptrs_.wramdata(0);
return true;
case 3:
- *data = memptrs.rambankdata();
- *length = memptrs.rambankdataend() - memptrs.rambankdata();
+ *data = memptrs_.rambankdata();
+ *length = memptrs_.rambankdataend() - memptrs_.rambankdata();
return true;
default:
@@ -742,9 +742,10 @@ bool Cartridge::getMemoryArea(int which, unsigned char **data, int *length) cons
SYNCFUNC(Cartridge)
{
- SSS(memptrs);
- SSS(rtc);
- TSS(mbc);
+ SSS(memptrs_);
+ SSS(time_);
+ SSS(rtc_);
+ TSS(mbc_);
}
}
diff --git a/libgambatte/src/mem/cartridge.h b/libgambatte/src/mem/cartridge.h
index 511c4438ae..e07baa4aa8 100644
--- a/libgambatte/src/mem/cartridge.h
+++ b/libgambatte/src/mem/cartridge.h
@@ -1,25 +1,27 @@
-/***************************************************************************
- * Copyright (C) 2007-2010 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2007-2010 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#ifndef CARTRIDGE_H
#define CARTRIDGE_H
+#include "loadres.h"
#include "memptrs.h"
+#include "time.h"
#include "rtc.h"
#include "savestate.h"
#include
@@ -29,26 +31,12 @@
namespace gambatte {
- //DOOM
-//enum eAddressMappingType
-//{
-// eAddressMappingType_ROM,
-// eAddressMappingType_RAM
-//};
-//
-//struct AddressMapping
-//{
-// int32_t address;
-// eAddressMappingType type;
-//};
-
class Mbc {
public:
virtual ~Mbc() {}
- virtual void romWrite(unsigned P, unsigned data) = 0;
- virtual void loadState(const SaveState::Mem &ss) = 0;
+ virtual void romWrite(unsigned P, unsigned data, unsigned long cycleCounter) = 0;
+ virtual void loadState(SaveState::Mem const &ss) = 0;
virtual bool isAddressWithinAreaRombankCanBeMappedTo(unsigned address, unsigned rombank) const = 0;
- //virtual void mapAddress(AddressMapping* mapping, unsigned address) const = 0; //DOOM
templatevoid SyncState(NewState *ns)
{
@@ -59,52 +47,47 @@ public:
};
class Cartridge {
- MemPtrs memptrs;
- Rtc rtc;
- std::auto_ptr mbc;
-
public:
+ Cartridge();
void setStatePtrs(SaveState &);
- void loadState(const SaveState &);
-
- bool loaded() const { return mbc.get(); }
-
- const unsigned char * rmem(unsigned area) const { return memptrs.rmem(area); }
- unsigned char * wmem(unsigned area) const { return memptrs.wmem(area); }
- unsigned char * vramdata() const { return memptrs.vramdata(); }
- unsigned char * romdata(unsigned area) const { return memptrs.romdata(area); }
- unsigned char * wramdata(unsigned area) const { return memptrs.wramdata(area); }
- const unsigned char * rdisabledRam() const { return memptrs.rdisabledRam(); }
- const unsigned char * rsrambankptr() const { return memptrs.rsrambankptr(); }
- unsigned char * wsrambankptr() const { return memptrs.wsrambankptr(); }
- unsigned char * vrambankptr() const { return memptrs.vrambankptr(); }
- OamDmaSrc oamDmaSrc() const { return memptrs.oamDmaSrc(); }
- unsigned curRomBank() const { return memptrs.curRomBank(); }
-
- void setVrambank(unsigned bank) { memptrs.setVrambank(bank); }
- void setWrambank(unsigned bank) { memptrs.setWrambank(bank); }
- void setOamDmaSrc(OamDmaSrc oamDmaSrc) { memptrs.setOamDmaSrc(oamDmaSrc); }
-
- void mbcWrite(unsigned addr, unsigned data) { mbc->romWrite(addr, data); }
-
- bool isCgb() const { return gambatte::isCgb(memptrs); }
-
- void rtcWrite(unsigned data) { rtc.write(data); }
- unsigned char rtcRead() const { return *rtc.getActive(); }
-
- void loadSavedata(const char *data);
+ void loadState(SaveState const &);
+ bool loaded() const { return mbc_.get(); }
+ unsigned char const * rmem(unsigned area) const { return memptrs_.rmem(area); }
+ unsigned char * wmem(unsigned area) const { return memptrs_.wmem(area); }
+ unsigned char * vramdata() const { return memptrs_.vramdata(); }
+ unsigned char * romdata(unsigned area) const { return memptrs_.romdata(area); }
+ unsigned char * wramdata(unsigned area) const { return memptrs_.wramdata(area); }
+ unsigned char const * rdisabledRam() const { return memptrs_.rdisabledRam(); }
+ unsigned char const * rsrambankptr() const { return memptrs_.rsrambankptr(); }
+ unsigned char * wsrambankptr() const { return memptrs_.wsrambankptr(); }
+ unsigned char * vrambankptr() const { return memptrs_.vrambankptr(); }
+ OamDmaSrc oamDmaSrc() const { return memptrs_.oamDmaSrc(); }
+ void setVrambank(unsigned bank) { memptrs_.setVrambank(bank); }
+ void setWrambank(unsigned bank) { memptrs_.setWrambank(bank); }
+ void setOamDmaSrc(OamDmaSrc oamDmaSrc) { memptrs_.setOamDmaSrc(oamDmaSrc); }
+ unsigned curRomBank() const { return memptrs_.curRomBank(); }
+ void mbcWrite(unsigned addr, unsigned data, unsigned long const cc) { mbc_->romWrite(addr, data, cc); }
+ bool isCgb() const { return gambatte::isCgb(memptrs_); }
+ void resetCc(unsigned long const oldCc, unsigned long const newCc) { time_.resetCc(oldCc, newCc); }
+ void speedChange(unsigned long const cc) { time_.speedChange(cc); }
+ void setTimeMode(bool useCycles, unsigned long const cc) { time_.setTimeMode(useCycles, cc); }
+ void setRtcDivisorOffset(long const rtcDivisorOffset) { time_.setRtcDivisorOffset(rtcDivisorOffset); }
+ void rtcWrite(unsigned data, unsigned long const cc) { rtc_.write(data, cc); }
+ unsigned char rtcRead() const { return *rtc_.activeData(); }
+ void loadSavedata(char const *data, unsigned long cycleCounter);
int saveSavedataLength();
- void saveSavedata(char *dest);
-
+ void saveSavedata(char *dest, unsigned long cycleCounter);
bool getMemoryArea(int which, unsigned char **data, int *length) const;
+ LoadRes loadROM(char const *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat);
+ char const * romTitle() const { return reinterpret_cast(memptrs_.romdata() + 0x134); }
- int loadROM(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat);
- const char * romTitle() const { return reinterpret_cast(memptrs.romdata() + 0x134); }
-
- void setRTCCallback(std::uint32_t (*callback)()) {
- rtc.setRTCCallback(callback);
- }
+private:
+ MemPtrs memptrs_;
+ Time time_;
+ Rtc rtc_;
+ std::unique_ptr mbc_;
+public:
templatevoid SyncState(NewState *ns);
};
diff --git a/libgambatte/src/mem/memptrs.cpp b/libgambatte/src/mem/memptrs.cpp
index bd166e86cf..65b5125bbf 100644
--- a/libgambatte/src/mem/memptrs.cpp
+++ b/libgambatte/src/mem/memptrs.cpp
@@ -1,21 +1,21 @@
-/***************************************************************************
- * Copyright (C) 2007-2010 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2007-2010 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#include "memptrs.h"
#include
#include
@@ -23,10 +23,19 @@
namespace gambatte {
MemPtrs::MemPtrs()
-: rmem_(), wmem_(), romdata_(), wramdata_(), vrambankptr_(0), rsrambankptr_(0),
- wsrambankptr_(0), memchunk_(0), rambankdata_(0), wramdataend_(0), oamDmaSrc_(OAM_DMA_SRC_OFF),
- curRomBank_(1),
- memchunk_len(0)
+: rmem_()
+, wmem_()
+, romdata_()
+, wramdata_()
+, vrambankptr_(0)
+, rsrambankptr_(0)
+, wsrambankptr_(0)
+, memchunk_(0)
+, rambankdata_(0)
+, wramdataend_(0)
+, oamDmaSrc_(oam_dma_src_off)
+, curRomBank_(1)
+, memchunk_len(0)
{
}
@@ -34,9 +43,15 @@ MemPtrs::~MemPtrs() {
delete []memchunk_;
}
-void MemPtrs::reset(const unsigned rombanks, const unsigned rambanks, const unsigned wrambanks) {
+void MemPtrs::reset(unsigned const rombanks, unsigned const rambanks, unsigned const wrambanks) {
delete []memchunk_;
- memchunk_len = 0x4000 + rombanks * 0x4000ul + 0x4000 + rambanks * 0x2000ul + wrambanks * 0x1000ul + 0x4000;
+ memchunk_len =
+ 0x4000
+ + rombanks * 0x4000ul
+ + 0x4000
+ + rambanks * 0x2000ul
+ + wrambanks * 0x1000ul
+ + 0x4000;
memchunk_ = new unsigned char[memchunk_len];
romdata_[0] = romdata();
@@ -45,8 +60,8 @@ void MemPtrs::reset(const unsigned rombanks, const unsigned rambanks, const unsi
wramdataend_ = wramdata_[0] + wrambanks * 0x1000ul;
std::memset(rdisabledRamw(), 0xFF, 0x2000);
-
- oamDmaSrc_ = OAM_DMA_SRC_OFF;
+
+ oamDmaSrc_ = oam_dma_src_off;
rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0];
rmem_[0xC] = wmem_[0xC] = wramdata_[0] - 0xC000;
rmem_[0xE] = wmem_[0xE] = wramdata_[0] - 0xE000;
@@ -60,39 +75,43 @@ void MemPtrs::reset(const unsigned rombanks, const unsigned rambanks, const unsi
memchunk_savelen = wramdataend() - memchunk_ - memchunk_saveoffs;
}
-void MemPtrs::setRombank0(const unsigned bank) {
+void MemPtrs::setRombank0(unsigned bank) {
romdata_[0] = romdata() + bank * 0x4000ul;
rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0];
disconnectOamDmaAreas();
}
-void MemPtrs::setRombank(const unsigned bank) {
+void MemPtrs::setRombank(unsigned bank) {
curRomBank_ = bank;
romdata_[1] = romdata() + bank * 0x4000ul - 0x4000;
rmem_[0x7] = rmem_[0x6] = rmem_[0x5] = rmem_[0x4] = romdata_[1];
disconnectOamDmaAreas();
}
-void MemPtrs::setRambank(const unsigned flags, const unsigned rambank) {
- unsigned char *const srambankptr = flags & RTC_EN
- ? 0
- : (rambankdata() != rambankdataend()
- ? rambankdata_ + rambank * 0x2000ul - 0xA000 : wdisabledRam() - 0xA000);
+void MemPtrs::setRambank(unsigned const flags, unsigned const rambank) {
+ unsigned char *srambankptr = 0;
+ if (!(flags & rtc_en)) {
+ srambankptr = rambankdata() != rambankdataend()
+ ? rambankdata_ + rambank * 0x2000ul - 0xA000
+ : wdisabledRam() - 0xA000;
+ }
- rsrambankptr_ = (flags & READ_EN) && srambankptr != wdisabledRam() - 0xA000 ? srambankptr : rdisabledRamw() - 0xA000;
- wsrambankptr_ = flags & WRITE_EN ? srambankptr : wdisabledRam() - 0xA000;
+ rsrambankptr_ = (flags & read_en) && srambankptr != wdisabledRam() - 0xA000
+ ? srambankptr
+ : rdisabledRamw() - 0xA000;
+ wsrambankptr_ = flags & write_en ? srambankptr : wdisabledRam() - 0xA000;
rmem_[0xB] = rmem_[0xA] = rsrambankptr_;
wmem_[0xB] = wmem_[0xA] = wsrambankptr_;
disconnectOamDmaAreas();
}
-void MemPtrs::setWrambank(const unsigned bank) {
- wramdata_[1] = wramdata_[0] + ((bank & 0x07) ? (bank & 0x07) : 1) * 0x1000;
+void MemPtrs::setWrambank(unsigned bank) {
+ wramdata_[1] = wramdata_[0] + (bank & 0x07 ? bank & 0x07 : 1) * 0x1000;
rmem_[0xD] = wmem_[0xD] = wramdata_[1] - 0xD000;
disconnectOamDmaAreas();
}
-void MemPtrs::setOamDmaSrc(const OamDmaSrc oamDmaSrc) {
+void MemPtrs::setOamDmaSrc(OamDmaSrc oamDmaSrc) {
rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0];
rmem_[0x7] = rmem_[0x6] = rmem_[0x5] = rmem_[0x4] = romdata_[1];
rmem_[0xB] = rmem_[0xA] = rsrambankptr_;
@@ -100,7 +119,7 @@ void MemPtrs::setOamDmaSrc(const OamDmaSrc oamDmaSrc) {
rmem_[0xC] = wmem_[0xC] = wramdata_[0] - 0xC000;
rmem_[0xD] = wmem_[0xD] = wramdata_[1] - 0xD000;
rmem_[0xE] = wmem_[0xE] = wramdata_[0] - 0xE000;
-
+
oamDmaSrc_ = oamDmaSrc;
disconnectOamDmaAreas();
}
@@ -108,37 +127,37 @@ void MemPtrs::setOamDmaSrc(const OamDmaSrc oamDmaSrc) {
void MemPtrs::disconnectOamDmaAreas() {
if (isCgb(*this)) {
switch (oamDmaSrc_) {
- case OAM_DMA_SRC_ROM: // fall through
- case OAM_DMA_SRC_SRAM:
- case OAM_DMA_SRC_INVALID:
+ case oam_dma_src_rom: // fall through
+ case oam_dma_src_sram:
+ case oam_dma_src_invalid:
std::fill(rmem_, rmem_ + 8, static_cast(0));
rmem_[0xB] = rmem_[0xA] = 0;
wmem_[0xB] = wmem_[0xA] = 0;
break;
- case OAM_DMA_SRC_VRAM:
+ case oam_dma_src_vram:
break;
- case OAM_DMA_SRC_WRAM:
+ case oam_dma_src_wram:
rmem_[0xE] = rmem_[0xD] = rmem_[0xC] = 0;
wmem_[0xE] = wmem_[0xD] = wmem_[0xC] = 0;
break;
- case OAM_DMA_SRC_OFF:
+ case oam_dma_src_off:
break;
}
} else {
switch (oamDmaSrc_) {
- case OAM_DMA_SRC_ROM: // fall through
- case OAM_DMA_SRC_SRAM:
- case OAM_DMA_SRC_WRAM:
- case OAM_DMA_SRC_INVALID:
+ case oam_dma_src_rom: // fall through
+ case oam_dma_src_sram:
+ case oam_dma_src_wram:
+ case oam_dma_src_invalid:
std::fill(rmem_, rmem_ + 8, static_cast(0));
rmem_[0xB] = rmem_[0xA] = 0;
wmem_[0xB] = wmem_[0xA] = 0;
rmem_[0xE] = rmem_[0xD] = rmem_[0xC] = 0;
wmem_[0xE] = wmem_[0xD] = wmem_[0xC] = 0;
break;
- case OAM_DMA_SRC_VRAM:
+ case oam_dma_src_vram:
break;
- case OAM_DMA_SRC_OFF:
+ case oam_dma_src_off:
break;
}
}
@@ -150,24 +169,10 @@ void MemPtrs::disconnectOamDmaAreas() {
SYNCFUNC(MemPtrs)
{
- /*
- int memchunk_len_old = memchunk_len;
- int memchunk_saveoffs_old = memchunk_saveoffs;
- int memchunk_savelen_old = memchunk_savelen;
- */
-
NSS(memchunk_len);
NSS(memchunk_saveoffs);
NSS(memchunk_savelen);
- /*
- if (isReader)
- {
- if (memchunk_len != memchunk_len_old || memchunk_saveoffs != memchunk_saveoffs_old || memchunk_savelen != memchunk_savelen_old)
- __debugbreak();
- }
- */
-
PSS(memchunk_ + memchunk_saveoffs, memchunk_savelen);
MSS(rmem_[0x0]);
@@ -202,11 +207,6 @@ SYNCFUNC(MemPtrs)
MSS(wmem_[0xe]);
MSS(rmem_[0xf]);
MSS(wmem_[0xf]);
- //for (int i = 0; i < 0x10; i++)
- //{
- // MSS(rmem_[i]);
- // MSS(wmem_[i]);
- //}
MSS(romdata_[0]);
MSS(romdata_[1]);
MSS(wramdata_[0]);
diff --git a/libgambatte/src/mem/memptrs.h b/libgambatte/src/mem/memptrs.h
index 68fd2b0006..d41a265394 100644
--- a/libgambatte/src/mem/memptrs.h
+++ b/libgambatte/src/mem/memptrs.h
@@ -1,21 +1,21 @@
-/***************************************************************************
- * Copyright (C) 2007-2010 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2007-2010 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#ifndef MEMPTRS_H
#define MEMPTRS_H
@@ -23,43 +23,22 @@
namespace gambatte {
-enum OamDmaSrc { OAM_DMA_SRC_ROM, OAM_DMA_SRC_SRAM, OAM_DMA_SRC_VRAM,
- OAM_DMA_SRC_WRAM, OAM_DMA_SRC_INVALID, OAM_DMA_SRC_OFF };
+enum OamDmaSrc { oam_dma_src_rom,
+ oam_dma_src_sram,
+ oam_dma_src_vram,
+ oam_dma_src_wram,
+ oam_dma_src_invalid,
+ oam_dma_src_off, };
class MemPtrs {
- const unsigned char *rmem_[0x10];
- unsigned char *wmem_[0x10];
-
- unsigned char *romdata_[2];
- unsigned char *wramdata_[2];
- unsigned char *vrambankptr_;
- unsigned char *rsrambankptr_;
- unsigned char *wsrambankptr_;
- unsigned char *memchunk_;
- unsigned char *rambankdata_;
- unsigned char *wramdataend_;
-
- OamDmaSrc oamDmaSrc_;
-
- unsigned curRomBank_;
-
- int memchunk_len;
- int memchunk_saveoffs;
- int memchunk_savelen;
-
- MemPtrs(const MemPtrs &);
- MemPtrs & operator=(const MemPtrs &);
- void disconnectOamDmaAreas();
- unsigned char * rdisabledRamw() const { return wramdataend_ ; }
- unsigned char * wdisabledRam() const { return wramdataend_ + 0x2000; }
public:
- enum RamFlag { READ_EN = 1, WRITE_EN = 2, RTC_EN = 4 };
-
+ enum RamFlag { read_en = 1, write_en = 2, rtc_en = 4 };
+
MemPtrs();
~MemPtrs();
void reset(unsigned rombanks, unsigned rambanks, unsigned wrambanks);
-
- const unsigned char * rmem(unsigned area) const { return rmem_[area]; }
+
+ unsigned char const * rmem(unsigned area) const { return rmem_[area]; }
unsigned char * wmem(unsigned area) const { return wmem_[area]; }
unsigned char * vramdata() const { return rambankdata_ - 0x4000; }
unsigned char * vramdataend() const { return rambankdata_; }
@@ -70,8 +49,8 @@ public:
unsigned char * wramdataend() const { return wramdataend_; }
unsigned char * rambankdata() const { return rambankdata_; }
unsigned char * rambankdataend() const { return wramdata_[0]; }
- const unsigned char * rdisabledRam() const { return rdisabledRamw(); }
- const unsigned char * rsrambankptr() const { return rsrambankptr_; }
+ unsigned char const * rdisabledRam() const { return rdisabledRamw(); }
+ unsigned char const * rsrambankptr() const { return rsrambankptr_; }
unsigned char * wsrambankptr() const { return wsrambankptr_; }
unsigned char * vrambankptr() const { return vrambankptr_; }
OamDmaSrc oamDmaSrc() const { return oamDmaSrc_; }
@@ -84,10 +63,36 @@ public:
void setWrambank(unsigned bank);
void setOamDmaSrc(OamDmaSrc oamDmaSrc);
+private:
+ unsigned char const *rmem_[0x10];
+ unsigned char *wmem_[0x10];
+ unsigned char *romdata_[2];
+ unsigned char *wramdata_[2];
+ unsigned char *vrambankptr_;
+ unsigned char *rsrambankptr_;
+ unsigned char *wsrambankptr_;
+ unsigned char *memchunk_;
+ unsigned char *rambankdata_;
+ unsigned char *wramdataend_;
+ OamDmaSrc oamDmaSrc_;
+
+ unsigned curRomBank_;
+
+ int memchunk_len;
+ int memchunk_saveoffs;
+ int memchunk_savelen;
+
+ MemPtrs(MemPtrs const &);
+ MemPtrs & operator=(MemPtrs const &);
+ void disconnectOamDmaAreas();
+ unsigned char * rdisabledRamw() const { return wramdataend_ ; }
+ unsigned char * wdisabledRam() const { return wramdataend_ + 0x2000; }
+
+public:
templatevoid SyncState(NewState *ns);
};
-inline bool isCgb(const MemPtrs &memptrs) {
+inline bool isCgb(MemPtrs const &memptrs) {
return memptrs.wramdataend() - memptrs.wramdata(0) == 0x8000;
}
diff --git a/libgambatte/src/mem/rtc.cpp b/libgambatte/src/mem/rtc.cpp
index ae97d0876c..5b79c04d7b 100644
--- a/libgambatte/src/mem/rtc.cpp
+++ b/libgambatte/src/mem/rtc.cpp
@@ -1,177 +1,178 @@
-/***************************************************************************
- * Copyright (C) 2007 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2007 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#include "rtc.h"
#include "../savestate.h"
#include
namespace gambatte {
-Rtc::Rtc()
-: activeData(NULL),
- activeSet(NULL),
- baseTime(0),
- haltTime(0),
- index(5),
- dataDh(0),
- dataDl(0),
- dataH(0),
- dataM(0),
- dataS(0),
- enabled(false),
- lastLatchData(false),
- timeCB(0)
+Rtc::Rtc(Time &time)
+: time_(time)
+, activeData_(0)
+, activeSet_(0)
+, haltTime_(0)
+, index_(5)
+, dataDh_(0)
+, dataDl_(0)
+, dataH_(0)
+, dataM_(0)
+, dataS_(0)
+, enabled_(false)
+, lastLatchData_(false)
{
}
-void Rtc::doLatch() {
- std::uint32_t tmp = ((dataDh & 0x40) ? haltTime : timeCB()) - baseTime;
-
- while (tmp > 0x1FF * 86400) {
- baseTime += 0x1FF * 86400;
- tmp -= 0x1FF * 86400;
- dataDh |= 0x80;
+void Rtc::doLatch(unsigned long const cc) {
+ std::uint32_t tmp = time(cc);
+
+ if (tmp >= 0x200 * 86400) {
+ tmp %= 0x200 * 86400;
+ time_.set(tmp, cc);
+ dataDh_ |= 0x80;
}
-
- dataDl = (tmp / 86400) & 0xFF;
- dataDh &= 0xFE;
- dataDh |= ((tmp / 86400) & 0x100) >> 8;
+
+ dataDl_ = (tmp / 86400) & 0xFF;
+ dataDh_ &= 0xFE;
+ dataDh_ |= ((tmp / 86400) & 0x100) >> 8;
tmp %= 86400;
-
- dataH = tmp / 3600;
+
+ dataH_ = tmp / 3600;
tmp %= 3600;
-
- dataM = tmp / 60;
+
+ dataM_ = tmp / 60;
tmp %= 60;
-
- dataS = tmp;
+
+ dataS_ = tmp;
}
void Rtc::doSwapActive() {
- if (!enabled || index > 4) {
- activeData = NULL;
- activeSet = NULL;
- } else switch (index) {
+ if (!enabled_ || index_ > 4) {
+ activeData_ = 0;
+ activeSet_ = 0;
+ } else switch (index_) {
case 0x00:
- activeData = &dataS;
- activeSet = &Rtc::setS;
+ activeData_ = &dataS_;
+ activeSet_ = &Rtc::setS;
break;
case 0x01:
- activeData = &dataM;
- activeSet = &Rtc::setM;
+ activeData_ = &dataM_;
+ activeSet_ = &Rtc::setM;
break;
case 0x02:
- activeData = &dataH;
- activeSet = &Rtc::setH;
+ activeData_ = &dataH_;
+ activeSet_ = &Rtc::setH;
break;
case 0x03:
- activeData = &dataDl;
- activeSet = &Rtc::setDl;
+ activeData_ = &dataDl_;
+ activeSet_ = &Rtc::setDl;
break;
case 0x04:
- activeData = &dataDh;
- activeSet = &Rtc::setDh;
+ activeData_ = &dataDh_;
+ activeSet_ = &Rtc::setDh;
break;
}
}
-void Rtc::loadState(const SaveState &state) {
- baseTime = state.rtc.baseTime;
- haltTime = state.rtc.haltTime;
- dataDh = state.rtc.dataDh;
- dataDl = state.rtc.dataDl;
- dataH = state.rtc.dataH;
- dataM = state.rtc.dataM;
- dataS = state.rtc.dataS;
- lastLatchData = state.rtc.lastLatchData;
-
+void Rtc::loadState(SaveState const &state) {
+ haltTime_ = state.rtc.haltTime;
+ dataDh_ = state.rtc.dataDh;
+ dataDl_ = state.rtc.dataDl;
+ dataH_ = state.rtc.dataH;
+ dataM_ = state.rtc.dataM;
+ dataS_ = state.rtc.dataS;
+ lastLatchData_ = state.rtc.lastLatchData;
doSwapActive();
}
-void Rtc::setDh(const unsigned new_dh) {
- const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
- const std::uint32_t old_highdays = ((unixtime - baseTime) / 86400) & 0x100;
- baseTime += old_highdays * 86400;
- baseTime -= ((new_dh & 0x1) << 8) * 86400;
-
- if ((dataDh ^ new_dh) & 0x40) {
- if (new_dh & 0x40)
- haltTime = timeCB();
+void Rtc::setDh(unsigned const newDh, unsigned const long cc) {
+ std::uint32_t seconds = time(cc);
+ std::uint32_t const oldHighdays = (seconds / 86400) & 0x100;
+ seconds -= oldHighdays * 86400;
+ seconds += ((newDh & 0x1) << 8) * 86400;
+ time_.set(seconds, cc);
+
+ if ((dataDh_ ^ newDh) & 0x40) {
+ if (newDh & 0x40)
+ haltTime_ = seconds;
else
- baseTime += timeCB() - haltTime;
+ time_.set(haltTime_, cc);
}
}
-void Rtc::setDl(const unsigned new_lowdays) {
- const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
- const std::uint32_t old_lowdays = ((unixtime - baseTime) / 86400) & 0xFF;
- baseTime += old_lowdays * 86400;
- baseTime -= new_lowdays * 86400;
+void Rtc::setDl(unsigned const newLowdays, unsigned const long cc) {
+ std::uint32_t seconds = time(cc);
+ std::uint32_t const oldLowdays = (seconds / 86400) & 0xFF;
+ seconds -= oldLowdays * 86400;
+ seconds += newLowdays * 86400;
+ time_.set(seconds, cc);
}
-void Rtc::setH(const unsigned new_hours) {
- const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
- const std::uint32_t old_hours = ((unixtime - baseTime) / 3600) % 24;
- baseTime += old_hours * 3600;
- baseTime -= new_hours * 3600;
+void Rtc::setH(unsigned const newHours, unsigned const long cc) {
+ std::uint32_t seconds = time(cc);
+ std::uint32_t const oldHours = (seconds / 3600) % 24;
+ seconds -= oldHours * 3600;
+ seconds += newHours * 3600;
+ time_.set(seconds, cc);
}
-void Rtc::setM(const unsigned new_minutes) {
- const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
- const std::uint32_t old_minutes = ((unixtime - baseTime) / 60) % 60;
- baseTime += old_minutes * 60;
- baseTime -= new_minutes * 60;
+void Rtc::setM(unsigned const newMinutes, unsigned const long cc) {
+ std::uint32_t seconds = time(cc);
+ std::uint32_t const oldMinutes = (seconds / 60) % 60;
+ seconds -= oldMinutes * 60;
+ seconds += newMinutes * 60;
+ time_.set(seconds, cc);
}
-void Rtc::setS(const unsigned new_seconds) {
- const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
- baseTime += (unixtime - baseTime) % 60;
- baseTime -= new_seconds;
+void Rtc::setS(unsigned const newSeconds, unsigned const long cc) {
+ std::uint32_t seconds = time(cc);
+ seconds -= seconds % 60;
+ seconds += newSeconds;
+ time_.reset(seconds, cc);
}
SYNCFUNC(Rtc)
{
- EBS(activeData, 0);
- EVS(activeData, &dataS, 1);
- EVS(activeData, &dataM, 2);
- EVS(activeData, &dataH, 3);
- EVS(activeData, &dataDl, 4);
- EVS(activeData, &dataDh, 5);
- EES(activeData, NULL);
+ EBS(activeData_, 0);
+ EVS(activeData_, &dataS_, 1);
+ EVS(activeData_, &dataM_, 2);
+ EVS(activeData_, &dataH_, 3);
+ EVS(activeData_, &dataDl_, 4);
+ EVS(activeData_, &dataDh_, 5);
+ EES(activeData_, NULL);
- EBS(activeSet, 0);
- EVS(activeSet, &Rtc::setS, 1);
- EVS(activeSet, &Rtc::setM, 2);
- EVS(activeSet, &Rtc::setH, 3);
- EVS(activeSet, &Rtc::setDl, 4);
- EVS(activeSet, &Rtc::setDh, 5);
- EES(activeSet, NULL);
+ EBS(activeSet_, 0);
+ EVS(activeSet_, &Rtc::setS, 1);
+ EVS(activeSet_, &Rtc::setM, 2);
+ EVS(activeSet_, &Rtc::setH, 3);
+ EVS(activeSet_, &Rtc::setDl, 4);
+ EVS(activeSet_, &Rtc::setDh, 5);
+ EES(activeSet_, NULL);
- NSS(baseTime);
- NSS(haltTime);
- NSS(index);
- NSS(dataDh);
- NSS(dataDl);
- NSS(dataH);
- NSS(dataM);
- NSS(dataS);
- NSS(enabled);
- NSS(lastLatchData);
+ NSS(haltTime_);
+ NSS(index_);
+ NSS(dataDh_);
+ NSS(dataDl_);
+ NSS(dataH_);
+ NSS(dataM_);
+ NSS(dataS_);
+ NSS(enabled_);
+ NSS(lastLatchData_);
}
}
diff --git a/libgambatte/src/mem/rtc.h b/libgambatte/src/mem/rtc.h
index cdbd7e66d0..853027ed58 100644
--- a/libgambatte/src/mem/rtc.h
+++ b/libgambatte/src/mem/rtc.h
@@ -1,25 +1,26 @@
-/***************************************************************************
- * Copyright (C) 2007 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2007 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#ifndef RTC_H
#define RTC_H
#include
+#include "time.h"
#include "newstate.h"
namespace gambatte {
@@ -27,69 +28,59 @@ namespace gambatte {
struct SaveState;
class Rtc {
-private:
- unsigned char *activeData;
- void (Rtc::*activeSet)(unsigned);
- std::uint32_t baseTime;
- std::uint32_t haltTime;
- unsigned char index;
- unsigned char dataDh;
- unsigned char dataDl;
- unsigned char dataH;
- unsigned char dataM;
- unsigned char dataS;
- bool enabled;
- bool lastLatchData;
- std::uint32_t (*timeCB)();
-
- void doLatch();
- void doSwapActive();
- void setDh(unsigned new_dh);
- void setDl(unsigned new_lowdays);
- void setH(unsigned new_hours);
- void setM(unsigned new_minutes);
- void setS(unsigned new_seconds);
-
public:
- Rtc();
-
- const unsigned char* getActive() const { return activeData; }
- std::uint32_t getBaseTime() const { return baseTime; }
-
- void setBaseTime(const std::uint32_t baseTime) {
- this->baseTime = baseTime;
-// doLatch();
+ Rtc(Time &time);
+ unsigned char const * activeData() const { return activeData_; }
+
+ void latch(unsigned data, unsigned long const cc) {
+ if (!lastLatchData_ && data == 1)
+ doLatch(cc);
+
+ lastLatchData_ = data;
}
-
- void latch(const unsigned data) {
- if (!lastLatchData && data == 1)
- doLatch();
-
- lastLatchData = data;
- }
-
- void loadState(const SaveState &state);
-
- void set(const bool enabled, unsigned bank) {
+
+ void loadState(SaveState const &state);
+
+ void set(bool enabled, unsigned bank) {
bank &= 0xF;
bank -= 8;
-
- this->enabled = enabled;
- this->index = bank;
-
+
+ enabled_ = enabled;
+ index_ = bank;
doSwapActive();
}
-
- void write(const unsigned data) {
-// if (activeSet)
- (this->*activeSet)(data);
- *activeData = data;
+
+ void write(unsigned data, unsigned long const cc) {
+ (this->*activeSet_)(data, cc);
+ *activeData_ = data;
}
- void setRTCCallback(std::uint32_t (*callback)()) {
- timeCB = callback;
- }
+private:
+ Time &time_;
+ unsigned char *activeData_;
+ void (Rtc::*activeSet_)(unsigned, unsigned long);
+ std::uint32_t haltTime_;
+ unsigned char index_;
+ unsigned char dataDh_;
+ unsigned char dataDl_;
+ unsigned char dataH_;
+ unsigned char dataM_;
+ unsigned char dataS_;
+ bool enabled_;
+ bool lastLatchData_;
+ void doLatch(unsigned long cycleCounter);
+ void doSwapActive();
+ void setDh(unsigned newDh, unsigned long cycleCounter);
+ void setDl(unsigned newLowdays, unsigned long cycleCounter);
+ void setH(unsigned newHours, unsigned long cycleCounter);
+ void setM(unsigned newMinutes, unsigned long cycleCounter);
+ void setS(unsigned newSeconds, unsigned long cycleCounter);
+
+ std::uint32_t time(unsigned long const cc) {
+ return dataDh_ & 0x40 ? haltTime_ : time_.get(cc);
+ }
+public:
templatevoid SyncState(NewState *ns);
};
diff --git a/libgambatte/src/mem/time.cpp b/libgambatte/src/mem/time.cpp
new file mode 100644
index 0000000000..87ffb7e10c
--- /dev/null
+++ b/libgambatte/src/mem/time.cpp
@@ -0,0 +1,145 @@
+//
+// Copyright (C) 2007 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
+#include "time.h"
+#include "../savestate.h"
+
+namespace gambatte {
+
+static timeval operator-(timeval l, timeval r) {
+ timeval t;
+ t.tv_sec = l.tv_sec - r.tv_sec;
+ t.tv_usec = l.tv_usec - r.tv_usec;
+ if (t.tv_usec < 0) {
+ t.tv_sec--;
+ t.tv_usec += 1000000;
+ }
+ return t;
+}
+
+Time::Time()
+: useCycles_(true)
+, rtcDivisor_(0x400000)
+{
+}
+
+void Time::loadState(SaveState const &state) {
+ seconds_ = state.time.seconds;
+ lastTime_.tv_sec = state.time.lastTimeSec;
+ lastTime_.tv_usec = state.time.lastTimeUsec;
+ lastCycles_ = state.time.lastCycles;
+ ds_ = state.ppu.isCgb & state.mem.ioamhram.get()[0x14D] >> 7;
+}
+
+std::uint32_t Time::get(unsigned long const cc) {
+ update(cc);
+ return seconds_;
+}
+
+void Time::set(std::uint32_t seconds, unsigned long const cc) {
+ update(cc);
+ seconds_ = seconds;
+}
+
+void Time::reset(std::uint32_t seconds, unsigned long const cc) {
+ set(seconds, cc);
+ lastTime_ = now();
+ lastCycles_ = cc;
+}
+
+void Time::resetCc(unsigned long const oldCc, unsigned long const newCc) {
+ update(oldCc);
+ lastCycles_ -= oldCc - newCc;
+}
+
+void Time::speedChange(unsigned long const cc) {
+ update(cc);
+
+ if (useCycles_) {
+ unsigned long diff = cc - lastCycles_;
+ lastCycles_ = cc - (ds_ ? diff >> 1 : diff << 1);
+ }
+
+ ds_ = !ds_;
+}
+
+timeval Time::baseTime(unsigned long const cc) {
+ if (useCycles_)
+ timeFromCycles(cc);
+
+ timeval baseTime = lastTime_;
+ baseTime.tv_sec -= seconds_;
+ return baseTime;
+}
+
+void Time::setBaseTime(timeval baseTime, unsigned long const cc) {
+ seconds_ = (now() - baseTime).tv_sec;
+ lastTime_ = baseTime;
+ lastTime_.tv_sec += seconds_;
+
+ if (useCycles_)
+ cyclesFromTime(cc);
+}
+
+void Time::setTimeMode(bool useCycles, unsigned long const cc) {
+ if (useCycles != useCycles_) {
+ if (useCycles_)
+ timeFromCycles(cc);
+ else
+ cyclesFromTime(cc);
+
+ useCycles_ = useCycles;
+ }
+}
+
+void Time::update(unsigned long const cc) {
+ if (useCycles_) {
+ std::uint32_t diff = (cc - lastCycles_) / (rtcDivisor_ << ds_);
+ seconds_ += diff;
+ lastCycles_ += diff * (rtcDivisor_ << ds_);
+ } else {
+ std::uint32_t diff = (now() - lastTime_).tv_sec;
+ seconds_ += diff;
+ lastTime_.tv_sec += diff;
+ }
+}
+
+void Time::cyclesFromTime(unsigned long const cc) {
+ update(cc);
+ timeval diff = now() - lastTime_;
+ lastCycles_ = cc - diff.tv_usec * ((rtcDivisor_ << ds_) / 1000000.0f);
+}
+
+void Time::timeFromCycles(unsigned long const cc) {
+ update(cc);
+ unsigned long diff = cc - lastCycles_;
+ timeval usec = { 0, (long)(diff / ((rtcDivisor_ << ds_) / 1000000.0f)) };
+ lastTime_ = now() - usec;
+}
+
+SYNCFUNC(Time)
+{
+ NSS(seconds_);
+ NSS(lastTime_.tv_sec);
+ NSS(lastTime_.tv_usec);
+ NSS(lastCycles_);
+ NSS(useCycles_);
+ NSS(ds_);
+}
+
+}
diff --git a/libgambatte/src/mem/time.h b/libgambatte/src/mem/time.h
new file mode 100644
index 0000000000..3b720bea78
--- /dev/null
+++ b/libgambatte/src/mem/time.h
@@ -0,0 +1,80 @@
+//
+// Copyright (C) 2007 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
+#ifndef TIME_H
+#define TIME_H
+
+#include
+#include
+#include
+#include "newstate.h"
+
+namespace gambatte {
+
+struct SaveState;
+
+struct timeval {
+ std::uint32_t tv_sec;
+ std::uint32_t tv_usec;
+};
+
+class Time {
+public:
+ static timeval now() {
+ long long micros = std::chrono::duration_cast(
+ std::chrono::high_resolution_clock::now().time_since_epoch())
+ .count();
+ timeval t;
+ t.tv_usec = micros % 1000000;
+ t.tv_sec = micros / 1000000;
+ return t;
+ }
+
+ Time();
+ void loadState(SaveState const &state);
+
+ std::uint32_t get(unsigned long cycleCounter);
+ void set(std::uint32_t seconds, unsigned long cycleCounter);
+ void reset(std::uint32_t seconds, unsigned long cycleCounter);
+ void resetCc(unsigned long oldCc, unsigned long newCc);
+ void speedChange(unsigned long cycleCounter);
+
+ timeval baseTime(unsigned long cycleCounter);
+ void setBaseTime(timeval baseTime, unsigned long cycleCounter);
+ void setTimeMode(bool useCycles, unsigned long cycleCounter);
+ void setRtcDivisorOffset(long const rtcDivisorOffset) { rtcDivisor_ = 0x400000L + rtcDivisorOffset; }
+
+private:
+ std::uint32_t seconds_;
+ timeval lastTime_;
+ unsigned long lastCycles_;
+ bool useCycles_;
+ unsigned long rtcDivisor_;
+ bool ds_;
+
+ void update(unsigned long cycleCounter);
+ void cyclesFromTime(unsigned long cycleCounter);
+ void timeFromCycles(unsigned long cycleCounter);
+
+public:
+ templatevoid SyncState(NewState *ns);
+};
+
+}
+
+#endif
diff --git a/libgambatte/src/memory.cpp b/libgambatte/src/memory.cpp
index 0b92460ca5..6ddce9da05 100644
--- a/libgambatte/src/memory.cpp
+++ b/libgambatte/src/memory.cpp
@@ -1,505 +1,531 @@
-/***************************************************************************
- * Copyright (C) 2007 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2007 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#include "memory.h"
-#include "video.h"
-#include "sound.h"
#include "savestate.h"
+#include "sound.h"
+#include "video.h"
#include
namespace gambatte {
-Memory::Memory(const Interrupter &interrupter_in, unsigned short &sp, unsigned short &pc)
-: readCallback(0),
- writeCallback(0),
- execCallback(0),
- cdCallback(0),
- linkCallback(0),
- getInput(0),
- divLastUpdate(0),
- lastOamDmaUpdate(DISABLED_TIME),
- display(ioamhram, 0, VideoInterruptRequester(&intreq)),
- interrupter(interrupter_in),
- dmaSource(0),
- dmaDestination(0),
- oamDmaPos(0xFE),
- serialCnt(0),
- blanklcd(false),
- LINKCABLE(false),
- linkClockTrigger(false),
- SP(sp),
- PC(pc)
+Memory::Memory(unsigned short &sp, unsigned short &pc)
+: readCallback_(0)
+, writeCallback_(0)
+, execCallback_(0)
+, cdCallback_(0)
+, linkCallback_(0)
+, bios_(0)
+, getInput_(0)
+, divLastUpdate_(0)
+, lastOamDmaUpdate_(disabled_time)
+, lcd_(ioamhram_, 0, VideoInterruptRequester(intreq_))
+, dmaSource_(0)
+, dmaDestination_(0)
+, oamDmaPos_(0xFE)
+, serialCnt_(0)
+, blanklcd_(false)
+, LINKCABLE_(false)
+, linkClockTrigger_(false)
+, sp_(sp)
+, pc_(pc)
{
- intreq.setEventTime(144*456ul);
- intreq.setEventTime(0);
+ intreq_.setEventTime(144 * 456ul);
+ intreq_.setEventTime(0);
+}
+
+Memory::~Memory() {
+ delete []bios_;
}
void Memory::setStatePtrs(SaveState &state) {
- state.mem.ioamhram.set(ioamhram, sizeof ioamhram);
+ state.mem.ioamhram.set(ioamhram_, sizeof ioamhram_);
- cart.setStatePtrs(state);
- display.setStatePtrs(state);
- sound.setStatePtrs(state);
+ cart_.setStatePtrs(state);
+ lcd_.setStatePtrs(state);
+ psg_.setStatePtrs(state);
}
-static inline int serialCntFrom(const unsigned long cyclesUntilDone, const bool cgbFast) {
+static int serialCntFrom(unsigned long cyclesUntilDone, bool cgbFast) {
return cgbFast ? (cyclesUntilDone + 0xF) >> 4 : (cyclesUntilDone + 0x1FF) >> 9;
}
-void Memory::loadState(const SaveState &state) {
- biosMode = state.mem.biosMode;
- cgbSwitching = state.mem.cgbSwitching;
- agbMode = state.mem.agbMode;
+void Memory::loadState(SaveState const &state) {
+ biosMode_ = state.mem.biosMode;
+ cgbSwitching_ = state.mem.cgbSwitching;
+ agbMode_ = state.mem.agbMode;
gbIsCgb_ = state.mem.gbIsCgb;
- sound.loadState(state);
- display.loadState(state, state.mem.oamDmaPos < 0xA0 ? cart.rdisabledRam() : ioamhram);
- tima.loadState(state, TimaInterruptRequester(intreq));
- cart.loadState(state);
- intreq.loadState(state);
+ stopped_ = state.mem.stopped;
+ psg_.loadState(state);
+ lcd_.loadState(state, state.mem.oamDmaPos < 0xA0 ? cart_.rdisabledRam() : ioamhram_);
+ tima_.loadState(state, TimaInterruptRequester(intreq_));
+ cart_.loadState(state);
+ intreq_.loadState(state);
- divLastUpdate = state.mem.divLastUpdate;
- intreq.setEventTime(state.mem.nextSerialtime > state.cpu.cycleCounter ? state.mem.nextSerialtime : state.cpu.cycleCounter);
- intreq.setEventTime(state.mem.unhaltTime);
- lastOamDmaUpdate = state.mem.lastOamDmaUpdate;
- dmaSource = state.mem.dmaSource;
- dmaDestination = state.mem.dmaDestination;
- oamDmaPos = state.mem.oamDmaPos;
- serialCnt = intreq.eventTime(SERIAL) != DISABLED_TIME
- ? serialCntFrom(intreq.eventTime(SERIAL) - state.cpu.cycleCounter, ioamhram[0x102] & isCgb() * 2)
- : 8;
+ divLastUpdate_ = state.mem.divLastUpdate;
+ intreq_.setEventTime(state.mem.nextSerialtime > state.cpu.cycleCounter
+ ? state.mem.nextSerialtime
+ : state.cpu.cycleCounter);
+ intreq_.setEventTime(state.mem.unhaltTime);
+ halttime_ = state.mem.halttime;
+ lastOamDmaUpdate_ = state.mem.lastOamDmaUpdate;
+ dmaSource_ = state.mem.dmaSource;
+ dmaDestination_ = state.mem.dmaDestination;
+ oamDmaPos_ = state.mem.oamDmaPos;
+ serialCnt_ = intreq_.eventTime(intevent_serial) != disabled_time
+ ? serialCntFrom(intreq_.eventTime(intevent_serial) - state.cpu.cycleCounter,
+ ioamhram_[0x102] & isCgb() * 2)
+ : 8;
- cart.setVrambank(ioamhram[0x14F] & isCgb());
- cart.setOamDmaSrc(OAM_DMA_SRC_OFF);
- cart.setWrambank(isCgb() && (ioamhram[0x170] & 0x07) ? ioamhram[0x170] & 0x07 : 1);
+ cart_.setVrambank(ioamhram_[0x14F] & isCgb());
+ cart_.setOamDmaSrc(oam_dma_src_off);
+ cart_.setWrambank(isCgb() && (ioamhram_[0x170] & 0x07) ? ioamhram_[0x170] & 0x07 : 1);
- if (lastOamDmaUpdate != DISABLED_TIME) {
+ if (lastOamDmaUpdate_ != disabled_time) {
oamDmaInitSetup();
- const unsigned oamEventPos = oamDmaPos < 0xA0 ? 0xA0 : 0x100;
-
- intreq.setEventTime(lastOamDmaUpdate + (oamEventPos - oamDmaPos) * 4);
+ unsigned oamEventPos = oamDmaPos_ < 0xA0 ? 0xA0 : 0x100;
+ intreq_.setEventTime(
+ lastOamDmaUpdate_ + (oamEventPos - oamDmaPos_) * 4);
}
- intreq.setEventTime((ioamhram[0x140] & 0x80) ? display.nextMode1IrqTime() : state.cpu.cycleCounter);
- blanklcd = false;
-
+ intreq_.setEventTime(ioamhram_[0x140] & lcdc_en
+ ? lcd_.nextMode1IrqTime()
+ : state.cpu.cycleCounter);
+ blanklcd_ = false;
+
if (!isCgb())
- std::memset(cart.vramdata() + 0x2000, 0, 0x2000);
+ std::memset(cart_.vramdata() + 0x2000, 0, 0x2000);
}
-void Memory::setEndtime(const unsigned long cycleCounter, const unsigned long inc) {
- if (intreq.eventTime(BLIT) <= cycleCounter)
- intreq.setEventTime(intreq.eventTime(BLIT) + (70224 << isDoubleSpeed()));
-
- intreq.setEventTime(cycleCounter + (inc << isDoubleSpeed()));
+void Memory::setEndtime(unsigned long cc, unsigned long inc) {
+ if (intreq_.eventTime(intevent_blit) <= cc) {
+ intreq_.setEventTime(intreq_.eventTime(intevent_blit)
+ + (70224 << isDoubleSpeed()));
+ }
+
+ intreq_.setEventTime(cc + (inc << isDoubleSpeed()));
}
-void Memory::updateSerial(const unsigned long cc) {
- if (!LINKCABLE) {
- if (intreq.eventTime(SERIAL) != DISABLED_TIME) {
- if (intreq.eventTime(SERIAL) <= cc) {
- ioamhram[0x101] = (((ioamhram[0x101] + 1) << serialCnt) - 1) & 0xFF;
- ioamhram[0x102] &= 0x7F;
- intreq.setEventTime(DISABLED_TIME);
- intreq.flagIrq(8);
+void Memory::updateSerial(unsigned long const cc) {
+ if (!LINKCABLE_) {
+ if (intreq_.eventTime(intevent_serial) != disabled_time) {
+ if (intreq_.eventTime(intevent_serial) <= cc) {
+ ioamhram_[0x101] = (((ioamhram_[0x101] + 1) << serialCnt_) - 1) & 0xFF;
+ ioamhram_[0x102] &= 0x7F;
+ intreq_.setEventTime(disabled_time);
+ intreq_.flagIrq(8);
} else {
- const int targetCnt = serialCntFrom(intreq.eventTime(SERIAL) - cc, ioamhram[0x102] & isCgb() * 2);
- ioamhram[0x101] = (((ioamhram[0x101] + 1) << (serialCnt - targetCnt)) - 1) & 0xFF;
- serialCnt = targetCnt;
+ int const targetCnt = serialCntFrom(intreq_.eventTime(intevent_serial) - cc,
+ ioamhram_[0x102] & isCgb() * 2);
+ ioamhram_[0x101] = (((ioamhram_[0x101] + 1) << (serialCnt_ - targetCnt)) - 1) & 0xFF;
+ serialCnt_ = targetCnt;
}
}
- }
- else {
- if (intreq.eventTime(SERIAL) != DISABLED_TIME) {
- if (intreq.eventTime(SERIAL) <= cc) {
- linkClockTrigger = true;
- intreq.setEventTime(DISABLED_TIME);
- if (linkCallback)
- linkCallback();
+ } else {
+ if (intreq_.eventTime(intevent_serial) != disabled_time) {
+ if (intreq_.eventTime(intevent_serial) <= cc) {
+ linkClockTrigger_ = true;
+ intreq_.setEventTime(disabled_time);
+ if (linkCallback_)
+ linkCallback_();
}
}
}
}
-void Memory::updateTimaIrq(const unsigned long cc) {
- while (intreq.eventTime(TIMA) <= cc)
- tima.doIrqEvent(TimaInterruptRequester(intreq));
+void Memory::updateTimaIrq(unsigned long cc) {
+ while (intreq_.eventTime(intevent_tima) <= cc)
+ tima_.doIrqEvent(TimaInterruptRequester(intreq_));
}
-void Memory::updateIrqs(const unsigned long cc) {
+void Memory::updateIrqs(unsigned long cc) {
updateSerial(cc);
updateTimaIrq(cc);
- display.update(cc);
+ lcd_.update(cc);
}
-unsigned long Memory::event(unsigned long cycleCounter) {
- if (lastOamDmaUpdate != DISABLED_TIME)
- updateOamDma(cycleCounter);
+unsigned long Memory::event(unsigned long cc) {
+ if (lastOamDmaUpdate_ != disabled_time)
+ updateOamDma(cc);
- switch (intreq.minEventId()) {
- case UNHALT:
- nontrivial_ff_write(0xFF04, 0, cycleCounter);
- PC = (PC + 1) & 0xFFFF;
- cycleCounter += 4;
- intreq.unhalt();
- intreq.setEventTime(DISABLED_TIME);
+ switch (intreq_.minEventId()) {
+ case intevent_unhalt:
+ intreq_.unhalt();
+ intreq_.setEventTime(disabled_time);
+ nontrivial_ff_write(0xFF04, 0, cc);
+ pc_ = (pc_ + 1) & 0xFFFF;
+ cc += 4;
break;
- case END:
- intreq.setEventTime(DISABLED_TIME - 1);
+ case intevent_end:
+ intreq_.setEventTime(disabled_time - 1);
- while (cycleCounter >= intreq.minEventTime() && intreq.eventTime(END) != DISABLED_TIME)
- cycleCounter = event(cycleCounter);
-
- intreq.setEventTime(DISABLED_TIME);
+ while (cc >= intreq_.minEventTime()
+ && intreq_.eventTime(intevent_end) != disabled_time) {
+ cc = event(cc);
+ }
+
+ intreq_.setEventTime(disabled_time);
break;
- case BLIT:
+ case intevent_blit:
{
- const bool lcden = ioamhram[0x140] >> 7 & 1;
- unsigned long blitTime = intreq.eventTime(BLIT);
-
- if (lcden | blanklcd) {
- display.updateScreen(blanklcd, cycleCounter);
- intreq.setEventTime(DISABLED_TIME);
- intreq.setEventTime(DISABLED_TIME);
-
- while (cycleCounter >= intreq.minEventTime())
- cycleCounter = event(cycleCounter);
+ bool const lcden = ioamhram_[0x140] & lcdc_en;
+ unsigned long blitTime = intreq_.eventTime(intevent_blit);
+
+ if (lcden | blanklcd_) {
+ lcd_.updateScreen(blanklcd_, cc);
+ intreq_.setEventTime(disabled_time);
+ intreq_.setEventTime(disabled_time);
+
+ while (cc >= intreq_.minEventTime())
+ cc = event(cc);
} else
blitTime += 70224 << isDoubleSpeed();
-
- blanklcd = lcden ^ 1;
- intreq.setEventTime(blitTime);
+
+ blanklcd_ = lcden ^ 1;
+ intreq_.setEventTime(blitTime);
}
break;
- case SERIAL:
- updateSerial(cycleCounter);
+ case intevent_serial:
+ updateSerial(cc);
break;
- case OAM:
- intreq.setEventTime(lastOamDmaUpdate == DISABLED_TIME ?
- static_cast(DISABLED_TIME) : intreq.eventTime(OAM) + 0xA0 * 4);
+ case intevent_oam:
+ intreq_.setEventTime(lastOamDmaUpdate_ == disabled_time
+ ? static_cast(disabled_time)
+ : intreq_.eventTime(intevent_oam) + 0xA0 * 4);
break;
- case DMA:
+ case intevent_dma:
{
- const bool doubleSpeed = isDoubleSpeed();
- unsigned dmaSrc = dmaSource;
- unsigned dmaDest = dmaDestination;
- unsigned dmaLength = ((ioamhram[0x155] & 0x7F) + 0x1) * 0x10;
- unsigned length = hdmaReqFlagged(intreq) ? 0x10 : dmaLength;
-
- ackDmaReq(&intreq);
+ bool const doubleSpeed = isDoubleSpeed();
+ unsigned dmaSrc = dmaSource_;
+ unsigned dmaDest = dmaDestination_;
+ unsigned dmaLength = ((ioamhram_[0x155] & 0x7F) + 0x1) * 0x10;
+ unsigned length = hdmaReqFlagged(intreq_) ? 0x10 : dmaLength;
+
+ ackDmaReq(intreq_);
if ((static_cast(dmaDest) + length) & 0x10000) {
length = 0x10000 - dmaDest;
- ioamhram[0x155] |= 0x80;
+ ioamhram_[0x155] |= 0x80;
}
dmaLength -= length;
- if (!(ioamhram[0x140] & 0x80))
+ if (!(ioamhram_[0x140] & lcdc_en))
dmaLength = 0;
{
- unsigned long lOamDmaUpdate = lastOamDmaUpdate;
- lastOamDmaUpdate = DISABLED_TIME;
+ unsigned long lOamDmaUpdate = lastOamDmaUpdate_;
+ lastOamDmaUpdate_ = disabled_time;
while (length--) {
- const unsigned src = dmaSrc++ & 0xFFFF;
- const unsigned data = ((src & 0xE000) == 0x8000 || src > 0xFDFF) ? 0xFF : read(src, cycleCounter);
+ unsigned const src = dmaSrc++ & 0xFFFF;
+ unsigned const data = (src & 0xE000) == 0x8000 || src > 0xFDFF
+ ? 0xFF
+ : read(src, cc);
- cycleCounter += 2 << doubleSpeed;
+ cc += 2 << doubleSpeed;
- if (cycleCounter - 3 > lOamDmaUpdate) {
- oamDmaPos = (oamDmaPos + 1) & 0xFF;
+ if (cc - 3 > lOamDmaUpdate) {
+ oamDmaPos_ = (oamDmaPos_ + 1) & 0xFF;
lOamDmaUpdate += 4;
- if (oamDmaPos < 0xA0) {
- if (oamDmaPos == 0)
+ if (oamDmaPos_ < 0xA0) {
+ if (oamDmaPos_ == 0)
startOamDma(lOamDmaUpdate - 1);
- ioamhram[src & 0xFF] = data;
- } else if (oamDmaPos == 0xA0) {
+ ioamhram_[src & 0xFF] = data;
+ } else if (oamDmaPos_ == 0xA0) {
endOamDma(lOamDmaUpdate - 1);
- lOamDmaUpdate = DISABLED_TIME;
+ lOamDmaUpdate = disabled_time;
}
}
- nontrivial_write(0x8000 | (dmaDest++ & 0x1FFF), data, cycleCounter);
+ nontrivial_write(0x8000 | (dmaDest++ & 0x1FFF), data, cc);
}
- lastOamDmaUpdate = lOamDmaUpdate;
+ lastOamDmaUpdate_ = lOamDmaUpdate;
}
- cycleCounter += 4;
+ cc += 4;
- dmaSource = dmaSrc;
- dmaDestination = dmaDest;
- ioamhram[0x155] = ((dmaLength / 0x10 - 0x1) & 0xFF) | (ioamhram[0x155] & 0x80);
+ dmaSource_ = dmaSrc;
+ dmaDestination_ = dmaDest;
+ ioamhram_[0x155] = ((dmaLength / 0x10 - 0x1) & 0xFF) | (ioamhram_[0x155] & 0x80);
- if ((ioamhram[0x155] & 0x80) && display.hdmaIsEnabled()) {
- if (lastOamDmaUpdate != DISABLED_TIME)
- updateOamDma(cycleCounter);
-
- display.disableHdma(cycleCounter);
+ if ((ioamhram_[0x155] & 0x80) && lcd_.hdmaIsEnabled()) {
+ if (lastOamDmaUpdate_ != disabled_time)
+ updateOamDma(cc);
+
+ lcd_.disableHdma(cc);
}
}
break;
- case TIMA:
- tima.doIrqEvent(TimaInterruptRequester(intreq));
+ case intevent_tima:
+ tima_.doIrqEvent(TimaInterruptRequester(intreq_));
break;
- case VIDEO:
- display.update(cycleCounter);
+ case intevent_video:
+ lcd_.update(cc);
break;
- case INTERRUPTS:
- if (stopped) {
- intreq.setEventTime(DISABLED_TIME);
+ case intevent_interrupts:
+ if (stopped_) {
+ intreq_.setEventTime(disabled_time);
break;
}
+
if (halted()) {
- if (gbIsCgb_ || (!gbIsCgb_ && cycleCounter <= halttime + 4))
- cycleCounter += 4;
-
- intreq.unhalt();
- intreq.setEventTime(DISABLED_TIME);
+ if (gbIsCgb_ || (!gbIsCgb_ && cc <= halttime_ + 4))
+ cc += 4;
+
+ intreq_.unhalt();
+ intreq_.setEventTime(disabled_time);
}
-
+
if (ime()) {
+ cc += 12;
+
+ sp_ = (sp_ - 1) & 0xFFFF;
+ write(sp_, pc_ >> 8, cc);
+
+ cc += 4;
+
+ updateIrqs(cc);
+ unsigned const pendingIrqs = intreq_.pendingIrqs();
+
+ sp_ = (sp_ - 1) & 0xFFFF;
+ write(sp_, pc_ & 0xFF, cc);
+
+ cc += 2;
+
+ unsigned const n = pendingIrqs & -pendingIrqs;
unsigned address;
-
- cycleCounter += 12;
- display.update(cycleCounter);
- SP = (SP - 2) & 0xFFFF;
- write(SP + 1, PC >> 8, cycleCounter);
- unsigned ie = intreq.iereg();
-
- cycleCounter += 4;
- display.update(cycleCounter);
- write(SP, PC & 0xFF, cycleCounter);
- const unsigned pendingIrqs = ie & intreq.ifreg();
-
- cycleCounter += 4;
- display.update(cycleCounter);
- const unsigned n = pendingIrqs & -pendingIrqs;
-
if (n == 0) {
address = 0;
- }
- else if (n < 8) {
- static const unsigned char lut[] = { 0x40, 0x48, 0x48, 0x50 };
+ } else if (n <= 4) {
+ static unsigned char const lut[] = { 0x40, 0x48, 0x48, 0x50 };
address = lut[n-1];
} else
address = 0x50 + n;
-
- intreq.ackIrq(n);
- PC = address;
+
+ updateIrqs(cc);
+ intreq_.ackIrq(n);
+
+ cc += 2;
+
+ pc_ = address;
}
-
+
break;
}
- return cycleCounter;
+ return cc;
}
-unsigned long Memory::stop(unsigned long cycleCounter) {
- cycleCounter += 4;
-
- if (ioamhram[0x14D] & isCgb()) {
- sound.generate_samples(cycleCounter, isDoubleSpeed());
-
- display.speedChange(cycleCounter);
- ioamhram[0x14D] ^= 0x81;
+unsigned long Memory::stop(unsigned long cc) {
+ cc += 4;
- intreq.setEventTime((ioamhram[0x140] & 0x80) ? display.nextMode1IrqTime() : cycleCounter + (70224 << isDoubleSpeed()));
-
- if (intreq.eventTime(END) > cycleCounter) {
- intreq.setEventTime(cycleCounter + (isDoubleSpeed() ?
- (intreq.eventTime(END) - cycleCounter) << 1 : (intreq.eventTime(END) - cycleCounter) >> 1));
+ if (ioamhram_[0x14D] & isCgb()) {
+ psg_.generateSamples(cc + 4, isDoubleSpeed());
+ lcd_.speedChange((cc + 7) & ~7);
+ cart_.speedChange(cc);
+ ioamhram_[0x14D] ^= 0x81;
+ intreq_.setEventTime(ioamhram_[0x140] & lcdc_en
+ ? lcd_.nextMode1IrqTime()
+ : cc + (70224 << isDoubleSpeed()));
+
+ if (intreq_.eventTime(intevent_end) > cc) {
+ intreq_.setEventTime(cc
+ + ( isDoubleSpeed()
+ ? (intreq_.eventTime(intevent_end) - cc) << 1
+ : (intreq_.eventTime(intevent_end) - cc) >> 1));
}
- // when switching speed, it seems that the CPU spontaneously restarts soon?
- // otherwise, the cpu should be allowed to stay halted as long as needed
- // so only execute this line when switching speed
- intreq.halt();
- intreq.setEventTime(cycleCounter + 0x20000);
+ intreq_.halt();
+ intreq_.setEventTime(cc + 0x20000);
}
else {
- stopped = true;
- intreq.halt();
+ stopped_ = true;
+ intreq_.halt();
}
- return cycleCounter;
+ return cc;
}
-static void decCycles(unsigned long &counter, const unsigned long dec) {
- if (counter != DISABLED_TIME)
+static void decCycles(unsigned long &counter, unsigned long dec) {
+ if (counter != disabled_time)
counter -= dec;
}
-void Memory::decEventCycles(const MemEventId eventId, const unsigned long dec) {
- if (intreq.eventTime(eventId) != DISABLED_TIME)
- intreq.setEventTime(eventId, intreq.eventTime(eventId) - dec);
+void Memory::decEventCycles(IntEventId eventId, unsigned long dec) {
+ if (intreq_.eventTime(eventId) != disabled_time)
+ intreq_.setEventTime(eventId, intreq_.eventTime(eventId) - dec);
}
-unsigned long Memory::resetCounters(unsigned long cycleCounter) {
- if (lastOamDmaUpdate != DISABLED_TIME)
- updateOamDma(cycleCounter);
+unsigned long Memory::resetCounters(unsigned long cc) {
+ if (lastOamDmaUpdate_ != disabled_time)
+ updateOamDma(cc);
- updateIrqs(cycleCounter);
-
- const unsigned long oldCC = cycleCounter;
+ updateIrqs(cc);
{
- const unsigned long divinc = (cycleCounter - divLastUpdate) >> 8;
- ioamhram[0x104] = (ioamhram[0x104] + divinc) & 0xFF;
- divLastUpdate += divinc << 8;
+ unsigned long divinc = (cc - divLastUpdate_) >> 8;
+ ioamhram_[0x104] = (ioamhram_[0x104] + divinc) & 0xFF;
+ divLastUpdate_ += divinc << 8;
}
- const unsigned long dec = cycleCounter < 0x10000 ? 0 : (cycleCounter & ~0x7FFFul) - 0x8000;
+ unsigned long const dec = cc < 0x10000
+ ? 0
+ : (cc & ~0x7FFFul) - 0x8000;
+ decCycles(divLastUpdate_, dec);
+ decCycles(lastOamDmaUpdate_, dec);
+ decEventCycles(intevent_serial, dec);
+ decEventCycles(intevent_oam, dec);
+ decEventCycles(intevent_blit, dec);
+ decEventCycles(intevent_end, dec);
+ decEventCycles(intevent_unhalt, dec);
- decCycles(divLastUpdate, dec);
- decCycles(lastOamDmaUpdate, dec);
- decEventCycles(SERIAL, dec);
- decEventCycles(OAM, dec);
- decEventCycles(BLIT, dec);
- decEventCycles(END, dec);
- decEventCycles(UNHALT, dec);
-
- cycleCounter -= dec;
-
- intreq.resetCc(oldCC, cycleCounter);
- tima.resetCc(oldCC, cycleCounter, TimaInterruptRequester(intreq));
- display.resetCc(oldCC, cycleCounter);
- sound.resetCounter(cycleCounter, oldCC, isDoubleSpeed());
-
- return cycleCounter;
+ unsigned long const oldCC = cc;
+ cc -= dec;
+ intreq_.resetCc(oldCC, cc);
+ cart_.resetCc(oldCC, cc);
+ tima_.resetCc(oldCC, cc, TimaInterruptRequester(intreq_));
+ lcd_.resetCc(oldCC, cc);
+ psg_.resetCounter(cc, oldCC, isDoubleSpeed());
+ return cc;
}
void Memory::updateInput() {
unsigned state = 0xF;
- if ((ioamhram[0x100] & 0x30) != 0x30 && getInput) {
- unsigned input = (*getInput)();
+ if ((ioamhram_[0x100] & 0x30) != 0x30 && getInput_) {
+ unsigned input = (*getInput_)();
unsigned dpad_state = ~input >> 4;
unsigned button_state = ~input;
- if (!(ioamhram[0x100] & 0x10))
+ if (!(ioamhram_[0x100] & 0x10))
state &= dpad_state;
- if (!(ioamhram[0x100] & 0x20))
+ if (!(ioamhram_[0x100] & 0x20))
state &= button_state;
+
+ if (state != 0xF && (ioamhram_[0x100] & 0xF) == 0xF)
+ intreq_.flagIrq(0x10);
}
- if (state != 0xF && (ioamhram[0x100] & 0xF) == 0xF)
- intreq.flagIrq(0x10);
-
- ioamhram[0x100] = (ioamhram[0x100] & -0x10u) | state;
+ ioamhram_[0x100] = (ioamhram_[0x100] & -0x10u) | state;
}
-void Memory::updateOamDma(const unsigned long cycleCounter) {
- const unsigned char *const oamDmaSrc = oamDmaSrcPtr();
- unsigned cycles = (cycleCounter - lastOamDmaUpdate) >> 2;
+void Memory::updateOamDma(unsigned long const cc) {
+ unsigned char const *const oamDmaSrc = oamDmaSrcPtr();
+ unsigned cycles = (cc - lastOamDmaUpdate_) >> 2;
while (cycles--) {
- oamDmaPos = (oamDmaPos + 1) & 0xFF;
- lastOamDmaUpdate += 4;
+ oamDmaPos_ = (oamDmaPos_ + 1) & 0xFF;
+ lastOamDmaUpdate_ += 4;
- if (oamDmaPos < 0xA0) {
- if (oamDmaPos == 0)
- startOamDma(lastOamDmaUpdate - 1);
+ if (oamDmaPos_ < 0xA0) {
+ if (oamDmaPos_ == 0)
+ startOamDma(lastOamDmaUpdate_ - 1);
- ioamhram[oamDmaPos] = oamDmaSrc ? oamDmaSrc[oamDmaPos] : cart.rtcRead();
- } else if (oamDmaPos == 0xA0) {
- endOamDma(lastOamDmaUpdate - 1);
- lastOamDmaUpdate = DISABLED_TIME;
+ ioamhram_[oamDmaPos_] = oamDmaSrc ? oamDmaSrc[oamDmaPos_] : cart_.rtcRead();
+ } else if (oamDmaPos_ == 0xA0) {
+ endOamDma(lastOamDmaUpdate_ - 1);
+ lastOamDmaUpdate_ = disabled_time;
break;
}
}
}
void Memory::oamDmaInitSetup() {
- if (ioamhram[0x146] < 0xA0) {
- cart.setOamDmaSrc(ioamhram[0x146] < 0x80 ? OAM_DMA_SRC_ROM : OAM_DMA_SRC_VRAM);
- } else if (ioamhram[0x146] < 0xFE - isCgb() * 0x1E) {
- cart.setOamDmaSrc(ioamhram[0x146] < 0xC0 ? OAM_DMA_SRC_SRAM : OAM_DMA_SRC_WRAM);
+ if (ioamhram_[0x146] < 0xA0) {
+ cart_.setOamDmaSrc(ioamhram_[0x146] < 0x80 ? oam_dma_src_rom : oam_dma_src_vram);
+ } else if (ioamhram_[0x146] < 0xFE - isCgb() * 0x1E) {
+ cart_.setOamDmaSrc(ioamhram_[0x146] < 0xC0 ? oam_dma_src_sram : oam_dma_src_wram);
} else
- cart.setOamDmaSrc(OAM_DMA_SRC_INVALID);
+ cart_.setOamDmaSrc(oam_dma_src_invalid);
}
-static const unsigned char * oamDmaSrcZero() {
+static unsigned char const * oamDmaSrcZero() {
static unsigned char zeroMem[0xA0];
return zeroMem;
}
-const unsigned char * Memory::oamDmaSrcPtr() const {
- switch (cart.oamDmaSrc()) {
- case OAM_DMA_SRC_ROM: return cart.romdata(ioamhram[0x146] >> 6) + (ioamhram[0x146] << 8);
- case OAM_DMA_SRC_SRAM: return cart.rsrambankptr() ? cart.rsrambankptr() + (ioamhram[0x146] << 8) : 0;
- case OAM_DMA_SRC_VRAM: return cart.vrambankptr() + (ioamhram[0x146] << 8);
- case OAM_DMA_SRC_WRAM: return cart.wramdata(ioamhram[0x146] >> 4 & 1) + (ioamhram[0x146] << 8 & 0xFFF);
- case OAM_DMA_SRC_INVALID:
- case OAM_DMA_SRC_OFF: break;
+unsigned char const * Memory::oamDmaSrcPtr() const {
+ switch (cart_.oamDmaSrc()) {
+ case oam_dma_src_rom:
+ return cart_.romdata(ioamhram_[0x146] >> 6) + (ioamhram_[0x146] << 8);
+ case oam_dma_src_sram:
+ return cart_.rsrambankptr() ? cart_.rsrambankptr() + (ioamhram_[0x146] << 8) : 0;
+ case oam_dma_src_vram:
+ return cart_.vrambankptr() + (ioamhram_[0x146] << 8);
+ case oam_dma_src_wram:
+ return cart_.wramdata(ioamhram_[0x146] >> 4 & 1) + (ioamhram_[0x146] << 8 & 0xFFF);
+ case oam_dma_src_invalid:
+ case oam_dma_src_off:
+ break;
}
-
- return ioamhram[0x146] == 0xFF && !isCgb() ? oamDmaSrcZero() : cart.rdisabledRam();
+
+ return ioamhram_[0x146] == 0xFF && !isCgb() ? oamDmaSrcZero() : cart_.rdisabledRam();
}
-void Memory::startOamDma(const unsigned long cycleCounter) {
- display.oamChange(cart.rdisabledRam(), cycleCounter);
+void Memory::startOamDma(unsigned long cc) {
+ lcd_.oamChange(cart_.rdisabledRam(), cc);
}
-void Memory::endOamDma(const unsigned long cycleCounter) {
- oamDmaPos = 0xFE;
- cart.setOamDmaSrc(OAM_DMA_SRC_OFF);
- display.oamChange(ioamhram, cycleCounter);
+void Memory::endOamDma(unsigned long cc) {
+ oamDmaPos_ = 0xFE;
+ cart_.setOamDmaSrc(oam_dma_src_off);
+ lcd_.oamChange(ioamhram_, cc);
}
-unsigned Memory::nontrivial_ff_read(const unsigned P, const unsigned long cycleCounter) {
- if (lastOamDmaUpdate != DISABLED_TIME)
- updateOamDma(cycleCounter);
+unsigned Memory::nontrivial_ff_read(unsigned const p, unsigned long const cc) {
+ if (lastOamDmaUpdate_ != disabled_time)
+ updateOamDma(cc);
- switch (P & 0x7F) {
+ switch (p) {
case 0x00:
updateInput();
break;
case 0x01:
case 0x02:
- updateSerial(cycleCounter);
+ updateSerial(cc);
break;
case 0x04:
{
- const unsigned long divcycles = (cycleCounter - divLastUpdate) >> 8;
- ioamhram[0x104] = (ioamhram[0x104] + divcycles) & 0xFF;
- divLastUpdate += divcycles << 8;
+ unsigned long divcycles = (cc - divLastUpdate_) >> 8;
+ ioamhram_[0x104] = (ioamhram_[0x104] + divcycles) & 0xFF;
+ divLastUpdate_ += divcycles << 8;
}
break;
case 0x05:
- ioamhram[0x105] = tima.tima(cycleCounter);
+ ioamhram_[0x105] = tima_.tima(cc);
break;
case 0x0F:
- updateIrqs(cycleCounter);
- ioamhram[0x10F] = intreq.ifreg();
+ updateIrqs(cc);
+ ioamhram_[0x10F] = intreq_.ifreg();
break;
case 0x26:
- if (ioamhram[0x126] & 0x80) {
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- ioamhram[0x126] = 0xF0 | sound.getStatus();
+ if (ioamhram_[0x126] & 0x80) {
+ psg_.generateSamples(cc, isDoubleSpeed());
+ ioamhram_[0x126] = 0xF0 | psg_.getStatus();
} else
- ioamhram[0x126] = 0x70;
+ ioamhram_[0x126] = 0x70;
break;
case 0x30:
@@ -518,26 +544,27 @@ unsigned Memory::nontrivial_ff_read(const unsigned P, const unsigned long cycleC
case 0x3D:
case 0x3E:
case 0x3F:
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- return sound.waveRamRead(P & 0xF);
+ psg_.generateSamples(cc, isDoubleSpeed());
+ return psg_.waveRamRead(p & 0xF);
case 0x41:
- return ioamhram[0x141] | display.getStat(ioamhram[0x145], cycleCounter);
+ return ioamhram_[0x141] | lcd_.getStat(ioamhram_[0x145], cc);
case 0x44:
- return display.getLyReg(cycleCounter/*+4*/);
+ return lcd_.getLyReg(cc);
case 0x69:
- return display.cgbBgColorRead(ioamhram[0x168] & 0x3F, cycleCounter);
+ return lcd_.cgbBgColorRead(ioamhram_[0x168] & 0x3F, cc);
case 0x6B:
- return display.cgbSpColorRead(ioamhram[0x16A] & 0x3F, cycleCounter);
- default: break;
+ return lcd_.cgbSpColorRead(ioamhram_[0x16A] & 0x3F, cc);
+ default:
+ break;
}
- return ioamhram[P - 0xFE00];
+ return ioamhram_[p + 0x100];
}
-static bool isInOamDmaConflictArea(const OamDmaSrc oamDmaSrc, const unsigned addr, const bool cgb) {
+static bool isInOamDmaConflictArea(OamDmaSrc const oamDmaSrc, unsigned const p, bool const cgb) {
struct Area { unsigned short areaUpper, exceptAreaLower, exceptAreaWidth, pad; };
-
- static const Area cgbAreas[] = {
+
+ static Area const cgbAreas[] = {
{ 0xC000, 0x8000, 0x2000, 0 },
{ 0xC000, 0x8000, 0x2000, 0 },
{ 0xA000, 0x0000, 0x8000, 0 },
@@ -545,8 +572,8 @@ static bool isInOamDmaConflictArea(const OamDmaSrc oamDmaSrc, const unsigned add
{ 0xC000, 0x8000, 0x2000, 0 },
{ 0x0000, 0x0000, 0x0000, 0 }
};
-
- static const Area dmgAreas[] = {
+
+ static Area const dmgAreas[] = {
{ 0xFE00, 0x8000, 0x2000, 0 },
{ 0xFE00, 0x8000, 0x2000, 0 },
{ 0xA000, 0x0000, 0x8000, 0 },
@@ -554,257 +581,298 @@ static bool isInOamDmaConflictArea(const OamDmaSrc oamDmaSrc, const unsigned add
{ 0xFE00, 0x8000, 0x2000, 0 },
{ 0x0000, 0x0000, 0x0000, 0 }
};
-
- const Area *const a = cgb ? cgbAreas : dmgAreas;
- return addr < a[oamDmaSrc].areaUpper && addr - a[oamDmaSrc].exceptAreaLower >= a[oamDmaSrc].exceptAreaWidth;
+ Area const *a = cgb ? cgbAreas : dmgAreas;
+ return p < a[oamDmaSrc].areaUpper
+ && p - a[oamDmaSrc].exceptAreaLower >= a[oamDmaSrc].exceptAreaWidth;
}
-unsigned Memory::nontrivial_read(const unsigned P, const unsigned long cycleCounter) {
- if (P < 0xFF80) {
- if (lastOamDmaUpdate != DISABLED_TIME) {
- updateOamDma(cycleCounter);
-
- if (isInOamDmaConflictArea(cart.oamDmaSrc(), P, isCgb()) && oamDmaPos < 0xA0)
- return ioamhram[oamDmaPos];
+unsigned Memory::nontrivial_read(unsigned const p, unsigned long const cc) {
+ if (p < 0xFF80) {
+ if (lastOamDmaUpdate_ != disabled_time) {
+ updateOamDma(cc);
+
+ if (isInOamDmaConflictArea(cart_.oamDmaSrc(), p, isCgb()) && oamDmaPos_ < 0xA0)
+ return ioamhram_[oamDmaPos_];
}
- if (P < 0xC000) {
- if (P < 0x8000)
- return cart.romdata(P >> 14)[P];
+ if (p < 0xC000) {
+ if (p < 0x8000)
+ return cart_.romdata(p >> 14)[p];
- if (P < 0xA000) {
- if (!display.vramAccessible(cycleCounter))
+ if (p < 0xA000) {
+ if (!lcd_.vramAccessible(cc))
return 0xFF;
- return cart.vrambankptr()[P];
+ return cart_.vrambankptr()[p];
}
- if (cart.rsrambankptr())
- return cart.rsrambankptr()[P];
+ if (cart_.rsrambankptr())
+ return cart_.rsrambankptr()[p];
- return cart.rtcRead();
+ return cart_.rtcRead();
}
- if (P < 0xFE00)
- return cart.wramdata(P >> 12 & 1)[P & 0xFFF];
+ if (p < 0xFE00)
+ return cart_.wramdata(p >> 12 & 1)[p & 0xFFF];
- if (P >= 0xFF00)
- return nontrivial_ff_read(P, cycleCounter);
+ long const ffp = long(p) - 0xFF00;
+ if (ffp >= 0)
+ return nontrivial_ff_read(ffp, cc);
- if (!display.oamReadable(cycleCounter) || oamDmaPos < 0xA0)
+ if (!lcd_.oamReadable(cc) || oamDmaPos_ < 0xA0)
return 0xFF;
}
- return ioamhram[P - 0xFE00];
+ return ioamhram_[p - 0xFE00];
}
-unsigned Memory::nontrivial_peek(const unsigned P) {
- if (P < 0xC000) {
- if (P < 0x8000)
- return cart.romdata(P >> 14)[P];
+unsigned Memory::nontrivial_peek(unsigned const p) {
+ if (p < 0xC000) {
+ if (p < 0x8000)
+ return cart_.romdata(p >> 14)[p];
- if (P < 0xA000) {
- return cart.vrambankptr()[P];
+ if (p < 0xA000) {
+ return cart_.vrambankptr()[p];
}
- if (cart.rsrambankptr())
- return cart.rsrambankptr()[P];
+ if (cart_.rsrambankptr())
+ return cart_.rsrambankptr()[p];
- return cart.rtcRead(); // verified side-effect free
+ return cart_.rtcRead(); // verified side-effect free
}
- if (P < 0xFE00)
- return cart.wramdata(P >> 12 & 1)[P & 0xFFF];
- if (P >= 0xFF00 && P < 0xFF80)
- return nontrivial_ff_peek(P);
- return ioamhram[P - 0xFE00];
+ if (p < 0xFE00)
+ return cart_.wramdata(p >> 12 & 1)[p & 0xFFF];
+ if (p >= 0xFF00 && p < 0xFF80)
+ return nontrivial_ff_peek(p);
+ return ioamhram_[p - 0xFE00];
}
-unsigned Memory::nontrivial_ff_peek(const unsigned P) {
+unsigned Memory::nontrivial_ff_peek(unsigned const p) {
// some regs may be somewhat wrong with this
- return ioamhram[P - 0xFE00];
+ return ioamhram_[p - 0xFE00];
}
-void Memory::nontrivial_ff_write(const unsigned P, unsigned data, const unsigned long cycleCounter) {
- if (lastOamDmaUpdate != DISABLED_TIME)
- updateOamDma(cycleCounter);
+void Memory::nontrivial_ff_write(unsigned const p, unsigned data, unsigned long const cc) {
+ if (lastOamDmaUpdate_ != disabled_time)
+ updateOamDma(cc);
- switch (P & 0xFF) {
+ switch (p & 0xFF) {
case 0x00:
- if ((data ^ ioamhram[0x100]) & 0x30) {
- ioamhram[0x100] = (ioamhram[0x100] & ~0x30u) | (data & 0x30);
+ if ((data ^ ioamhram_[0x100]) & 0x30) {
+ ioamhram_[0x100] = (ioamhram_[0x100] & ~0x30u) | (data & 0x30);
updateInput();
}
+
return;
case 0x01:
- updateSerial(cycleCounter);
+ updateSerial(cc);
break;
case 0x02:
- updateSerial(cycleCounter);
+ updateSerial(cc);
+ serialCnt_ = 8;
- serialCnt = 8;
- intreq.setEventTime((data & 0x81) == 0x81
- ? (data & isCgb() * 2 ? (cycleCounter & ~0x7ul) + 0x10 * 8 : (cycleCounter & ~0xFFul) + 0x200 * 8)
- : static_cast(DISABLED_TIME));
+ if ((data & 0x81) == 0x81) {
+ intreq_.setEventTime(data & isCgb() * 2
+ ? (cc & ~0x07ul) + 0x010 * 8
+ : (cc & ~0xFFul) + 0x200 * 8);
+ } else
+ intreq_.setEventTime(disabled_time);
data |= 0x7E - isCgb() * 2;
break;
case 0x04:
- ioamhram[0x104] = 0;
- divLastUpdate = cycleCounter;
- tima.resTac(cycleCounter, TimaInterruptRequester(intreq));
+ ioamhram_[0x104] = 0;
+ divLastUpdate_ = cc;
+ tima_.resTac(cc, TimaInterruptRequester(intreq_));
return;
case 0x05:
- tima.setTima(data, cycleCounter, TimaInterruptRequester(intreq));
+ tima_.setTima(data, cc, TimaInterruptRequester(intreq_));
break;
case 0x06:
- tima.setTma(data, cycleCounter, TimaInterruptRequester(intreq));
+ tima_.setTma(data, cc, TimaInterruptRequester(intreq_));
break;
case 0x07:
data |= 0xF8;
- tima.setTac(data, cycleCounter, TimaInterruptRequester(intreq), gbIsCgb_);
+ tima_.setTac(data, cc, TimaInterruptRequester(intreq_), agbMode_);
break;
case 0x0F:
- updateIrqs(cycleCounter);
- intreq.setIfreg(0xE0 | data);
+ updateIrqs(cc);
+ intreq_.setIfreg(0xE0 | data);
return;
case 0x10:
- if (!sound.isEnabled()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr10(data);
+ if (!psg_.isEnabled())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr10(data);
data |= 0x80;
break;
case 0x11:
- if (!sound.isEnabled()) {
+ if (!psg_.isEnabled()) {
if (isCgb())
return;
data &= 0x3F;
}
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr11(data);
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr11(data);
data |= 0x3F;
break;
case 0x12:
- if (!sound.isEnabled()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr12(data);
+ if (!psg_.isEnabled())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr12(data);
break;
case 0x13:
- if (!sound.isEnabled()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr13(data);
+ if (!psg_.isEnabled())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr13(data);
return;
case 0x14:
- if (!sound.isEnabled()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr14(data);
+ if (!psg_.isEnabled())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr14(data);
data |= 0xBF;
break;
case 0x16:
- if (!sound.isEnabled()) {
+ if (!psg_.isEnabled()) {
if (isCgb())
return;
data &= 0x3F;
}
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr21(data);
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr21(data);
data |= 0x3F;
break;
case 0x17:
- if (!sound.isEnabled()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr22(data);
+ if (!psg_.isEnabled())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr22(data);
break;
case 0x18:
- if (!sound.isEnabled()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr23(data);
+ if (!psg_.isEnabled())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr23(data);
return;
case 0x19:
- if (!sound.isEnabled()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr24(data);
+ if (!psg_.isEnabled())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr24(data);
data |= 0xBF;
break;
case 0x1A:
- if (!sound.isEnabled()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr30(data);
+ if (!psg_.isEnabled())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr30(data);
data |= 0x7F;
break;
case 0x1B:
- if (!sound.isEnabled() && isCgb()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr31(data);
+ if (!psg_.isEnabled() && isCgb())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr31(data);
return;
case 0x1C:
- if (!sound.isEnabled()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr32(data);
+ if (!psg_.isEnabled())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr32(data);
data |= 0x9F;
break;
case 0x1D:
- if (!sound.isEnabled()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr33(data);
+ if (!psg_.isEnabled())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr33(data);
return;
case 0x1E:
- if (!sound.isEnabled()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr34(data);
+ if (!psg_.isEnabled())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr34(data);
data |= 0xBF;
break;
case 0x20:
- if (!sound.isEnabled() && isCgb()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr41(data);
+ if (!psg_.isEnabled() && isCgb())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr41(data);
return;
case 0x21:
- if (!sound.isEnabled()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr42(data);
+ if (!psg_.isEnabled())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr42(data);
break;
case 0x22:
- if (!sound.isEnabled()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr43(data);
+ if (!psg_.isEnabled())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr43(data);
break;
case 0x23:
- if (!sound.isEnabled()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_nr44(data);
+ if (!psg_.isEnabled())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setNr44(data);
data |= 0xBF;
break;
case 0x24:
- if (!sound.isEnabled()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.set_so_volume(data);
+ if (!psg_.isEnabled())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.setSoVolume(data);
break;
case 0x25:
- if (!sound.isEnabled()) return;
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.map_so(data);
+ if (!psg_.isEnabled())
+ return;
+
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.mapSo(data);
break;
case 0x26:
- if ((ioamhram[0x126] ^ data) & 0x80) {
- sound.generate_samples(cycleCounter, isDoubleSpeed());
+ if ((ioamhram_[0x126] ^ data) & 0x80) {
+ psg_.generateSamples(cc, isDoubleSpeed());
if (!(data & 0x80)) {
- for (unsigned i = 0xFF10; i < 0xFF26; ++i)
- ff_write(i, 0, cycleCounter);
+ for (unsigned i = 0x10; i < 0x26; ++i)
+ ff_write(i, 0, cc);
- sound.setEnabled(false);
+ psg_.setEnabled(false);
} else {
- sound.reset();
- sound.setEnabled(true);
+ psg_.reset();
+ psg_.setEnabled(true);
}
}
- data = (data & 0x80) | (ioamhram[0x126] & 0x7F);
+ data = (data & 0x80) | (ioamhram_[0x126] & 0x7F);
break;
case 0x30:
case 0x31:
@@ -822,178 +890,179 @@ void Memory::nontrivial_ff_write(const unsigned P, unsigned data, const unsigned
case 0x3D:
case 0x3E:
case 0x3F:
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- sound.waveRamWrite(P & 0xF, data);
+ psg_.generateSamples(cc, isDoubleSpeed());
+ psg_.waveRamWrite(p & 0xF, data);
break;
case 0x40:
- if (ioamhram[0x140] != data) {
- if ((ioamhram[0x140] ^ data) & 0x80) {
- const unsigned lyc = display.getStat(ioamhram[0x145], cycleCounter) & 4;
- const bool hdmaEnabled = display.hdmaIsEnabled();
-
- display.lcdcChange(data, cycleCounter);
- ioamhram[0x144] = 0;
- ioamhram[0x141] &= 0xF8;
+ if (ioamhram_[0x140] != data) {
+ if ((ioamhram_[0x140] ^ data) & lcdc_en) {
+ unsigned const lyc = lcd_.getStat(ioamhram_[0x145], cc)
+ & lcdstat_lycflag;
+ bool const hdmaEnabled = lcd_.hdmaIsEnabled();
- if (data & 0x80) {
- intreq.setEventTime(display.nextMode1IrqTime() + (blanklcd ? 0 : 70224 << isDoubleSpeed()));
+ lcd_.lcdcChange(data, cc);
+ ioamhram_[0x144] = 0;
+ ioamhram_[0x141] &= 0xF8;
+
+ if (data & lcdc_en) {
+ intreq_.setEventTime(blanklcd_
+ ? lcd_.nextMode1IrqTime()
+ : lcd_.nextMode1IrqTime()
+ + (70224 << isDoubleSpeed()));
} else {
- ioamhram[0x141] |= lyc;
- intreq.setEventTime(cycleCounter + (456 * 4 << isDoubleSpeed()));
+ ioamhram_[0x141] |= lyc;
+ intreq_.setEventTime(
+ cc + (456 * 4 << isDoubleSpeed()));
if (hdmaEnabled)
- flagHdmaReq(&intreq);
+ flagHdmaReq(intreq_);
}
} else
- display.lcdcChange(data, cycleCounter);
+ lcd_.lcdcChange(data, cc);
- ioamhram[0x140] = data;
+ ioamhram_[0x140] = data;
}
return;
case 0x41:
- display.lcdstatChange(data, cycleCounter);
- data = (ioamhram[0x141] & 0x87) | (data & 0x78);
+ lcd_.lcdstatChange(data, cc);
+ data = (ioamhram_[0x141] & 0x87) | (data & 0x78);
break;
case 0x42:
- display.scyChange(data, cycleCounter);
+ lcd_.scyChange(data, cc);
break;
case 0x43:
- display.scxChange(data, cycleCounter);
+ lcd_.scxChange(data, cc);
break;
case 0x45:
- display.lycRegChange(data, cycleCounter);
+ lcd_.lycRegChange(data, cc);
break;
case 0x46:
- if (lastOamDmaUpdate != DISABLED_TIME)
- endOamDma(cycleCounter);
+ if (lastOamDmaUpdate_ != disabled_time)
+ endOamDma(cc);
- lastOamDmaUpdate = cycleCounter;
- intreq.setEventTime(cycleCounter + 8);
- ioamhram[0x146] = data;
+ lastOamDmaUpdate_ = cc;
+ intreq_.setEventTime(cc + 8);
+ ioamhram_[0x146] = data;
oamDmaInitSetup();
return;
case 0x47:
if (!isCgb())
- display.dmgBgPaletteChange(data, cycleCounter);
+ lcd_.dmgBgPaletteChange(data, cc);
break;
case 0x48:
if (!isCgb())
- display.dmgSpPalette1Change(data, cycleCounter);
+ lcd_.dmgSpPalette1Change(data, cc);
break;
case 0x49:
if (!isCgb())
- display.dmgSpPalette2Change(data, cycleCounter);
+ lcd_.dmgSpPalette2Change(data, cc);
break;
case 0x4A:
- display.wyChange(data, cycleCounter);
+ lcd_.wyChange(data, cc);
break;
case 0x4B:
- display.wxChange(data, cycleCounter);
- break;
- case 0x4C:
- if (biosMode) {
- //flagClockReq(&intreq);
- }
+ lcd_.wxChange(data, cc);
break;
case 0x4D:
if (isCgb())
- ioamhram[0x14D] = (ioamhram[0x14D] & ~1u) | (data & 1); return;
+ ioamhram_[0x14D] = (ioamhram_[0x14D] & ~1u) | (data & 1);
+
+ return;
case 0x4F:
if (isCgb()) {
- cart.setVrambank(data & 1);
- ioamhram[0x14F] = 0xFE | data;
+ cart_.setVrambank(data & 1);
+ ioamhram_[0x14F] = 0xFE | data;
}
return;
case 0x50:
- biosMode = false;
- if (cgbSwitching) {
- display.copyCgbPalettesToDmg();
- display.setCgb(false);
- cgbSwitching = false;
+ biosMode_ = false;
+ if(cgbSwitching_) {
+ lcd_.copyCgbPalettesToDmg();
+ lcd_.setCgb(false);
}
return;
case 0x51:
- dmaSource = data << 8 | (dmaSource & 0xFF);
+ dmaSource_ = data << 8 | (dmaSource_ & 0xFF);
return;
case 0x52:
- dmaSource = (dmaSource & 0xFF00) | (data & 0xF0);
+ dmaSource_ = (dmaSource_ & 0xFF00) | (data & 0xF0);
return;
case 0x53:
- dmaDestination = data << 8 | (dmaDestination & 0xFF);
+ dmaDestination_ = data << 8 | (dmaDestination_ & 0xFF);
return;
case 0x54:
- dmaDestination = (dmaDestination & 0xFF00) | (data & 0xF0);
+ dmaDestination_ = (dmaDestination_ & 0xFF00) | (data & 0xF0);
return;
case 0x55:
if (isCgb()) {
- ioamhram[0x155] = data & 0x7F;
+ ioamhram_[0x155] = data & 0x7F;
- if (display.hdmaIsEnabled()) {
+ if (lcd_.hdmaIsEnabled()) {
if (!(data & 0x80)) {
- ioamhram[0x155] |= 0x80;
- display.disableHdma(cycleCounter);
+ ioamhram_[0x155] |= 0x80;
+ lcd_.disableHdma(cc);
}
} else {
if (data & 0x80) {
- if (ioamhram[0x140] & 0x80) {
- display.enableHdma(cycleCounter);
+ if (ioamhram_[0x140] & lcdc_en) {
+ lcd_.enableHdma(cc);
} else
- flagHdmaReq(&intreq);
+ flagHdmaReq(intreq_);
} else
- flagGdmaReq(&intreq);
+ flagGdmaReq(intreq_);
}
}
return;
case 0x56:
if (isCgb())
- ioamhram[0x156] = data | 0x3E;
+ ioamhram_[0x156] = data | 0x3E;
return;
case 0x68:
if (isCgb())
- ioamhram[0x168] = data | 0x40;
+ ioamhram_[0x168] = data | 0x40;
return;
case 0x69:
if (isCgb()) {
- const unsigned index = ioamhram[0x168] & 0x3F;
-
- display.cgbBgColorChange(index, data, cycleCounter);
-
- ioamhram[0x168] = (ioamhram[0x168] & ~0x3F) | ((index + (ioamhram[0x168] >> 7)) & 0x3F);
+ unsigned index = ioamhram_[0x168] & 0x3F;
+ lcd_.cgbBgColorChange(index, data, cc);
+ ioamhram_[0x168] = (ioamhram_[0x168] & ~0x3F)
+ | ((index + (ioamhram_[0x168] >> 7)) & 0x3F);
}
return;
case 0x6A:
if (isCgb())
- ioamhram[0x16A] = data | 0x40;
+ ioamhram_[0x16A] = data | 0x40;
return;
case 0x6B:
if (isCgb()) {
- const unsigned index = ioamhram[0x16A] & 0x3F;
-
- display.cgbSpColorChange(index, data, cycleCounter);
-
- ioamhram[0x16A] = (ioamhram[0x16A] & ~0x3F) | ((index + (ioamhram[0x16A] >> 7)) & 0x3F);
+ unsigned index = ioamhram_[0x16A] & 0x3F;
+ lcd_.cgbSpColorChange(index, data, cc);
+ ioamhram_[0x16A] = (ioamhram_[0x16A] & ~0x3F)
+ | ((index + (ioamhram_[0x16A] >> 7)) & 0x3F);
}
return;
case 0x6C:
- ioamhram[0x16C] = data | 0xFE;
- cgbSwitching = true;
+ if (isCgb()) {
+ ioamhram_[0x16C] = data | 0xFE;
+ cgbSwitching_ = true;
+ }
return;
case 0x70:
if (isCgb()) {
- cart.setWrambank((data & 0x07) ? (data & 0x07) : 1);
- ioamhram[0x170] = data | 0xF8;
+ cart_.setWrambank(data & 0x07 ? data & 0x07 : 1);
+ ioamhram_[0x170] = data | 0xF8;
}
return;
@@ -1006,77 +1075,74 @@ void Memory::nontrivial_ff_write(const unsigned P, unsigned data, const unsigned
return;
case 0x75:
if (isCgb())
- ioamhram[0x175] = data | 0x8F;
+ ioamhram_[0x175] = data | 0x8F;
return;
case 0xFF:
- intreq.setIereg(data);
+ intreq_.setIereg(data);
break;
default:
return;
}
- ioamhram[P - 0xFE00] = data;
+ ioamhram_[p + 0x100] = data;
}
-void Memory::nontrivial_write(const unsigned P, const unsigned data, const unsigned long cycleCounter) {
- if (lastOamDmaUpdate != DISABLED_TIME) {
- updateOamDma(cycleCounter);
-
- if (isInOamDmaConflictArea(cart.oamDmaSrc(), P, isCgb()) && oamDmaPos < 0xA0) {
- ioamhram[oamDmaPos] = data;
+void Memory::nontrivial_write(unsigned const p, unsigned const data, unsigned long const cc) {
+ if (lastOamDmaUpdate_ != disabled_time) {
+ updateOamDma(cc);
+
+ if (isInOamDmaConflictArea(cart_.oamDmaSrc(), p, isCgb()) && oamDmaPos_ < 0xA0) {
+ ioamhram_[oamDmaPos_] = data;
return;
}
}
- if (P < 0xFE00) {
- if (P < 0xA000) {
- if (P < 0x8000) {
- cart.mbcWrite(P, data);
- } else if (display.vramAccessible(cycleCounter)) {
- display.vramChange(cycleCounter);
- cart.vrambankptr()[P] = data;
+ if (p < 0xFE00) {
+ if (p < 0xA000) {
+ if (p < 0x8000) {
+ cart_.mbcWrite(p, data, cc);
+ } else if (lcd_.vramAccessible(cc)) {
+ lcd_.vramChange(cc);
+ cart_.vrambankptr()[p] = data;
}
- } else if (P < 0xC000) {
- if (cart.wsrambankptr())
- cart.wsrambankptr()[P] = data;
+ } else if (p < 0xC000) {
+ if (cart_.wsrambankptr())
+ cart_.wsrambankptr()[p] = data;
else
- cart.rtcWrite(data);
+ cart_.rtcWrite(data, cc);
} else
- cart.wramdata(P >> 12 & 1)[P & 0xFFF] = data;
- } else if (P - 0xFF80u >= 0x7Fu) {
- if (P < 0xFF00) {
- if (display.oamWritable(cycleCounter) && oamDmaPos >= 0xA0 && (P < 0xFEA0 || isCgb())) {
- display.oamChange(cycleCounter);
- ioamhram[P - 0xFE00] = data;
+ cart_.wramdata(p >> 12 & 1)[p & 0xFFF] = data;
+ } else if (p - 0xFF80u >= 0x7Fu) {
+ long const ffp = long(p) - 0xFF00;
+ if (ffp < 0) {
+ if (lcd_.oamWritable(cc) && oamDmaPos_ >= 0xA0 && (p < 0xFEA0 || isCgb())) {
+ lcd_.oamChange(cc);
+ ioamhram_[p - 0xFE00] = data;
}
} else
- nontrivial_ff_write(P, data, cycleCounter);
+ nontrivial_ff_write(ffp, data, cc);
} else
- ioamhram[P - 0xFE00] = data;
+ ioamhram_[p - 0xFE00] = data;
}
-int Memory::loadROM(const char *romfiledata, unsigned romfilelength, const bool forceDmg, const bool multicartCompat) {
- if (const int fail = cart.loadROM(romfiledata, romfilelength, forceDmg, multicartCompat))
+LoadRes Memory::loadROM(char const *romfiledata, unsigned romfilelength, const bool forceDmg, const bool multicartCompat) {
+ if (LoadRes const fail = cart_.loadROM(romfiledata, romfilelength, forceDmg, multicartCompat))
return fail;
- sound.init(cart.isCgb());
- display.reset(ioamhram, cart.vramdata(), cart.isCgb());
+ psg_.init(cart_.isCgb());
+ lcd_.reset(ioamhram_, cart_.vramdata(), cart_.isCgb());
- return 0;
+ return LOADRES_OK;
}
-unsigned Memory::fillSoundBuffer(const unsigned long cycleCounter) {
- sound.generate_samples(cycleCounter, isDoubleSpeed());
- return sound.fillBuffer();
-}
-
-void Memory::setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned long rgb32) {
- display.setDmgPaletteColor(palNum, colorNum, rgb32);
+std::size_t Memory::fillSoundBuffer(unsigned long cc) {
+ psg_.generateSamples(cc, isDoubleSpeed());
+ return psg_.fillBuffer();
}
void Memory::setCgbPalette(unsigned *lut) {
- display.setCgbPalette(lut);
+ lcd_.setCgbPalette(lut);
}
bool Memory::getMemoryArea(int which, unsigned char **data, int *length) {
@@ -1086,46 +1152,46 @@ bool Memory::getMemoryArea(int which, unsigned char **data, int *length) {
switch (which)
{
case 4: // oam
- *data = &ioamhram[0];
+ *data = &ioamhram_[0];
*length = 160;
return true;
case 5: // hram
- *data = &ioamhram[384];
+ *data = &ioamhram_[384];
*length = 128;
return true;
case 6: // bgpal
- *data = (unsigned char *)display.bgPalette();
+ *data = (unsigned char *)lcd_.bgPalette();
*length = 32;
return true;
case 7: // sppal
- *data = (unsigned char *)display.spPalette();
+ *data = (unsigned char *)lcd_.spPalette();
*length = 32;
return true;
default: // pass to cartridge
- return cart.getMemoryArea(which, data, length);
+ return cart_.getMemoryArea(which, data, length);
}
}
-int Memory::LinkStatus(int which)
+int Memory::linkStatus(int which)
{
switch (which)
{
case 256: // ClockSignaled
- return linkClockTrigger;
+ return linkClockTrigger_;
case 257: // AckClockSignal
- linkClockTrigger = false;
+ linkClockTrigger_ = false;
return 0;
case 258: // GetOut
- return ioamhram[0x101] & 0xff;
+ return ioamhram_[0x101] & 0xff;
case 259: // connect link cable
- LINKCABLE = true;
+ LINKCABLE_ = true;
return 0;
default: // ShiftIn
- if (ioamhram[0x102] & 0x80) // was enabled
+ if (ioamhram_[0x102] & 0x80) // was enabled
{
- ioamhram[0x101] = which;
- ioamhram[0x102] &= 0x7F;
- intreq.flagIrq(8);
+ ioamhram_[0x101] = which;
+ ioamhram_[0x102] &= 0x7F;
+ intreq_.flagIrq(8);
}
return 0;
}
@@ -1135,31 +1201,27 @@ int Memory::LinkStatus(int which)
SYNCFUNC(Memory)
{
- SSS(cart);
- NSS(ioamhram);
- NSS(divLastUpdate);
- NSS(lastOamDmaUpdate);
- NSS(biosMode);
- NSS(cgbSwitching);
- NSS(agbMode);
+ SSS(cart_);
+ NSS(ioamhram_);
+ NSS(divLastUpdate_);
+ NSS(lastOamDmaUpdate_);
+ SSS(intreq_);
+ SSS(tima_);
+ SSS(lcd_);
+ SSS(psg_);
+ NSS(dmaSource_);
+ NSS(dmaDestination_);
+ NSS(oamDmaPos_);
+ NSS(serialCnt_);
+ NSS(blanklcd_);
+ NSS(biosMode_);
+ NSS(cgbSwitching_);
+ NSS(agbMode_);
NSS(gbIsCgb_);
- NSS(stopped);
- NSS(halttime);
-
- SSS(intreq);
- SSS(tima);
- SSS(display);
- SSS(sound);
- //SSS(interrupter); // no state
-
- NSS(dmaSource);
- NSS(dmaDestination);
- NSS(oamDmaPos);
- NSS(serialCnt);
- NSS(blanklcd);
-
- NSS(LINKCABLE);
- NSS(linkClockTrigger);
+ NSS(halttime_);
+ NSS(stopped_);
+ NSS(LINKCABLE_);
+ NSS(linkClockTrigger_);
}
}
diff --git a/libgambatte/src/memory.h b/libgambatte/src/memory.h
index 3ea2eec6ac..7d7dcc1d73 100644
--- a/libgambatte/src/memory.h
+++ b/libgambatte/src/memory.h
@@ -1,145 +1,93 @@
-/***************************************************************************
- * Copyright (C) 2007 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
+//
+// Copyright (C) 2007 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#ifndef MEMORY_H
#define MEMORY_H
static unsigned char const agbOverride[0xD] = { 0xFF, 0x00, 0xCD, 0x03, 0x35, 0xAA, 0x31, 0x90, 0x94, 0x00, 0x00, 0x00, 0x00 };
#include "mem/cartridge.h"
-#include "video.h"
#include "sound.h"
-#include "interrupter.h"
#include "tima.h"
+#include "video.h"
#include "newstate.h"
#include "gambatte.h"
namespace gambatte {
-class InputGetter;
+
class FilterInfo;
class Memory {
- Cartridge cart;
- unsigned char ioamhram[0x200];
- unsigned char cgbBios[0x900];
- unsigned char dmgBios[0x100];
- bool biosMode;
- bool cgbSwitching;
- bool agbMode;
- bool gbIsCgb_;
- bool stopped;
- unsigned short &SP;
- unsigned short &PC;
- unsigned long basetime;
- unsigned long halttime;
-
- MemoryCallback readCallback;
- MemoryCallback writeCallback;
- MemoryCallback execCallback;
- CDCallback cdCallback;
- void(*linkCallback)();
-
- unsigned (*getInput)();
- unsigned long divLastUpdate;
- unsigned long lastOamDmaUpdate;
-
- InterruptRequester intreq;
- Tima tima;
- LCD display;
- PSG sound;
- Interrupter interrupter;
-
- unsigned short dmaSource;
- unsigned short dmaDestination;
- unsigned char oamDmaPos;
- unsigned char serialCnt;
- bool blanklcd;
-
- bool LINKCABLE;
- bool linkClockTrigger;
-
- void decEventCycles(MemEventId eventId, unsigned long dec);
-
- void oamDmaInitSetup();
- void updateOamDma(unsigned long cycleCounter);
- void startOamDma(unsigned long cycleCounter);
- void endOamDma(unsigned long cycleCounter);
- const unsigned char * oamDmaSrcPtr() const;
-
- unsigned nontrivial_ff_read(unsigned P, unsigned long cycleCounter);
- unsigned nontrivial_read(unsigned P, unsigned long cycleCounter);
- void nontrivial_ff_write(unsigned P, unsigned data, unsigned long cycleCounter);
- void nontrivial_write(unsigned P, unsigned data, unsigned long cycleCounter);
-
- unsigned nontrivial_peek(unsigned P);
- unsigned nontrivial_ff_peek(unsigned P);
-
- void updateSerial(unsigned long cc);
- void updateTimaIrq(unsigned long cc);
- void updateIrqs(unsigned long cc);
-
- bool isDoubleSpeed() const { return display.isDoubleSpeed(); }
-
public:
- explicit Memory(const Interrupter &interrupter, unsigned short &sp, unsigned short &pc);
-
- bool loaded() const { return cart.loaded(); }
- unsigned curRomBank() const { return cart.curRomBank(); }
- const char * romTitle() const { return cart.romTitle(); }
-
- int debugGetLY() const { return display.debugGetLY(); }
+ explicit Memory(unsigned short &sp, unsigned short &pc);
+ ~Memory();
+ bool loaded() const { return cart_.loaded(); }
+ unsigned curRomBank() const { return cart_.curRomBank(); }
+ char const * romTitle() const { return cart_.romTitle(); }
+ int debugGetLY() const { return lcd_.debugGetLY(); }
void setStatePtrs(SaveState &state);
- void loadState(const SaveState &state/*, unsigned long oldCc*/);
- void loadSavedata(const char *data) { cart.loadSavedata(data); }
- int saveSavedataLength() {return cart.saveSavedataLength(); }
- void saveSavedata(char *dest) { cart.saveSavedata(dest); }
+ void loadState(SaveState const &state);
+ void loadSavedata(char const *data, unsigned long const cc) { cart_.loadSavedata(data, cc); }
+ int saveSavedataLength() {return cart_.saveSavedataLength(); }
+ void saveSavedata(char *dest, unsigned long const cc) { cart_.saveSavedata(dest, cc); }
void updateInput();
- unsigned char* cgbBiosBuffer() { return (unsigned char*)cgbBios; }
- unsigned char* dmgBiosBuffer() { return (unsigned char*)dmgBios; }
+ void setBios(char const *buffer, std::size_t size) {
+ delete []bios_;
+ bios_ = new unsigned char[size];
+ memcpy(bios_, buffer, size);
+ biosSize_ = size;
+ }
bool gbIsCgb() { return gbIsCgb_; }
- bool getMemoryArea(int which, unsigned char **data, int *length); // { return cart.getMemoryArea(which, data, length); }
+ bool getMemoryArea(int which, unsigned char **data, int *length);
unsigned long stop(unsigned long cycleCounter);
- bool isCgb() const { return display.isCgb(); }
- bool ime() const { return intreq.ime(); }
- bool halted() const { return intreq.halted(); }
- unsigned long nextEventTime() const { return intreq.minEventTime(); }
+ bool isCgb() const { return lcd_.isCgb(); }
+ bool ime() const { return intreq_.ime(); }
+ bool halted() const { return intreq_.halted(); }
+ unsigned long nextEventTime() const { return intreq_.minEventTime(); }
+ void setLayers(unsigned mask) { lcd_.setLayers(mask); }
+ bool isActive() const { return intreq_.eventTime(intevent_end) != disabled_time; }
- void setLayers(unsigned mask) { display.setLayers(mask); }
-
- bool isActive() const { return intreq.eventTime(END) != DISABLED_TIME; }
-
- long cyclesSinceBlit(const unsigned long cc) const {
- return cc < intreq.eventTime(BLIT) ? -1 : static_cast((cc - intreq.eventTime(BLIT)) >> isDoubleSpeed());
+ long cyclesSinceBlit(unsigned long cc) const {
+ if (cc < intreq_.eventTime(intevent_blit))
+ return -1;
+
+ return (cc - intreq_.eventTime(intevent_blit)) >> isDoubleSpeed();
}
- void halt(unsigned long cycleCounter) { halttime = cycleCounter; intreq.halt(); }
- void ei(unsigned long cycleCounter) { if (!ime()) { intreq.ei(cycleCounter); } }
+ void halt(unsigned long cycleCounter) { halttime_ = cycleCounter; intreq_.halt(); }
+ void ei(unsigned long cycleCounter) { if (!ime()) { intreq_.ei(cycleCounter); } }
+ void di() { intreq_.di(); }
- void di() { intreq.di(); }
+ unsigned readBios(unsigned p) {
+ if(agbMode_ && p >= 0xF3 && p < 0x100) {
+ return (agbOverride[p-0xF3] + bios_[p]) & 0xFF;
+ }
+ return bios_[p];
+ }
- unsigned ff_read(const unsigned P, const unsigned long cycleCounter) {
- if (readCallback)
- readCallback(P, (cycleCounter - basetime) >> 1);
- return P < 0xFF80 ? nontrivial_ff_read(P, cycleCounter) : ioamhram[P - 0xFE00];
+ unsigned ff_read(unsigned p, unsigned long cc) {
+ if (readCallback_)
+ readCallback_(p, (cc - basetime_) >> 1);
+ return p < 0x80 ? nontrivial_ff_read(p, cc) : ioamhram_[p + 0x100];
}
struct CDMapResult
@@ -148,30 +96,30 @@ public:
unsigned addr;
};
- CDMapResult CDMap(const unsigned P) const
+ CDMapResult CDMap(const unsigned p) const
{
- if(P<0x4000)
+ if(p < 0x4000)
{
- CDMapResult ret = { eCDLog_AddrType_ROM, P };
+ CDMapResult ret = { eCDLog_AddrType_ROM, p };
return ret;
}
- else if(P<0x8000)
+ else if(p < 0x8000)
{
- unsigned bank = cart.rmem(P>>12) - cart.rmem(0);
- unsigned addr = P+bank;
+ unsigned bank = cart_.rmem(p >> 12) - cart_.rmem(0);
+ unsigned addr = p + bank;
CDMapResult ret = { eCDLog_AddrType_ROM, addr };
return ret;
}
- else if(P<0xA000) {}
- else if(P<0xC000)
+ else if(p < 0xA000) {}
+ else if(p < 0xC000)
{
- if(cart.wsrambankptr())
+ if(cart_.wsrambankptr())
{
//not bankable. but. we're not sure how much might be here
unsigned char *data;
int length;
- bool has = cart.getMemoryArea(3,&data,&length);
- unsigned addr = P&(length-1);
+ bool has = cart_.getMemoryArea(3,&data,&length);
+ unsigned addr = p & (length-1);
if(has && length!=0)
{
CDMapResult ret = { eCDLog_AddrType_CartRAM, addr };
@@ -179,15 +127,15 @@ public:
}
}
}
- else if(P<0xE000)
+ else if(p < 0xE000)
{
- unsigned bank = cart.wramdata(P >> 12 & 1) - cart.wramdata(0);
- unsigned addr = (P&0xFFF)+bank;
+ unsigned bank = cart_.wramdata(p >> 12 & 1) - cart_.wramdata(0);
+ unsigned addr = (p & 0xFFF) + bank;
CDMapResult ret = { eCDLog_AddrType_WRAM, addr };
return ret;
}
- else if(P<0xFF80) {}
- else
+ else if(p < 0xFF80) {}
+ else
{
////this is just for debugging, really, it's pretty useless
//CDMapResult ret = { eCDLog_AddrType_HRAM, (P-0xFF80) };
@@ -198,154 +146,183 @@ public:
return ret;
}
-
- unsigned readBios(const unsigned P) {
- if (gbIsCgb_) {
- if (agbMode && P >= 0xF3 && P < 0x100) {
- return (agbOverride[P - 0xF3] + cgbBios[P]) & 0xFF;
- }
- return cgbBios[P];
+ unsigned read(unsigned p, unsigned long cc) {
+ if (readCallback_)
+ readCallback_(p, (cc - basetime_) >> 1);
+ if(biosMode_) {
+ if (p < biosSize_ && !(p >= 0x100 && p < 0x200))
+ return readBios(p);
}
- return dmgBios[P];
- }
-
- unsigned read(const unsigned P, const unsigned long cycleCounter) {
- if (readCallback)
- readCallback(P, (cycleCounter - basetime) >> 1);
- bool biosRange = ((!gbIsCgb_ && P < 0x100) || (gbIsCgb_ && P < 0x900 && (P < 0x100 || P >= 0x200)));
- if(biosMode) {
- if (biosRange)
- return readBios(P);
- }
- else
- {
- if(cdCallback)
- {
- CDMapResult map = CDMap(P);
- if(map.type != eCDLog_AddrType_None)
- cdCallback(map.addr,map.type,eCDLog_Flags_Data);
- }
- }
- return cart.rmem(P >> 12) ? cart.rmem(P >> 12)[P] : nontrivial_read(P, cycleCounter);
- }
-
- unsigned read_excb(const unsigned P, const unsigned long cycleCounter, bool first) {
- if (execCallback)
- execCallback(P, (cycleCounter - basetime) >> 1);
- bool biosRange = ((!gbIsCgb_ && P < 0x100) || (gbIsCgb_ && P < 0x900 && (P < 0x100 || P >= 0x200)));
- if (biosMode) {
- if(biosRange)
- return readBios(P);
- }
- else
- {
- if(cdCallback)
- {
- CDMapResult map = CDMap(P);
- if(map.type != eCDLog_AddrType_None)
- cdCallback(map.addr,map.type,first?eCDLog_Flags_ExecFirst : eCDLog_Flags_ExecOperand);
- }
- }
- return cart.rmem(P >> 12) ? cart.rmem(P >> 12)[P] : nontrivial_read(P, cycleCounter);
- }
-
- unsigned peek(const unsigned P) {
- if (biosMode && ((!gbIsCgb_ && P < 0x100) || (gbIsCgb_ && P < 0x900 && (P < 0x100 || P >= 0x200)))) {
- return readBios(P);
- }
- return cart.rmem(P >> 12) ? cart.rmem(P >> 12)[P] : nontrivial_peek(P);
- }
-
- void write_nocb(const unsigned P, const unsigned data, const unsigned long cycleCounter) {
- if (cart.wmem(P >> 12)) {
- cart.wmem(P >> 12)[P] = data;
- } else
- nontrivial_write(P, data, cycleCounter);
- }
-
- void write(const unsigned P, const unsigned data, const unsigned long cycleCounter) {
- if (cart.wmem(P >> 12)) {
- cart.wmem(P >> 12)[P] = data;
- } else
- nontrivial_write(P, data, cycleCounter);
- if (writeCallback)
- writeCallback(P, (cycleCounter - basetime) >> 1);
- if(cdCallback && !biosMode)
- {
- CDMapResult map = CDMap(P);
+ else if(cdCallback_) {
+ CDMapResult map = CDMap(p);
if(map.type != eCDLog_AddrType_None)
- cdCallback(map.addr,map.type,eCDLog_Flags_Data);
+ cdCallback_(map.addr, map.type, eCDLog_Flags_Data);
+ }
+ return cart_.rmem(p >> 12) ? cart_.rmem(p >> 12)[p] : nontrivial_read(p, cc);
+ }
+
+ unsigned read_excb(unsigned p, unsigned long cc, bool first) {
+ if (execCallback_)
+ execCallback_(p, (cc - basetime_) >> 1);
+ if (biosMode_) {
+ if(p < biosSize_ && !(p >= 0x100 && p < 0x200))
+ return readBios(p);
+ }
+ else if(cdCallback_) {
+ CDMapResult map = CDMap(p);
+ if(map.type != eCDLog_AddrType_None)
+ cdCallback_(map.addr, map.type, first ? eCDLog_Flags_ExecFirst : eCDLog_Flags_ExecOperand);
+ }
+ return cart_.rmem(p >> 12) ? cart_.rmem(p >> 12)[p] : nontrivial_read(p, cc);
+ }
+
+ unsigned peek(unsigned p) {
+ if (biosMode_ && p < biosSize_ && !(p >= 0x100 && p < 0x200)) {
+ return readBios(p);
+ }
+ return cart_.rmem(p >> 12) ? cart_.rmem(p >> 12)[p] : nontrivial_peek(p);
+ }
+
+ void write_nocb(unsigned p, unsigned data, unsigned long cc) {
+ if (cart_.wmem(p >> 12)) {
+ cart_.wmem(p >> 12)[p] = data;
+ } else
+ nontrivial_write(p, data, cc);
+ }
+
+ void write(unsigned p, unsigned data, unsigned long cc) {
+ if (cart_.wmem(p >> 12)) {
+ cart_.wmem(p >> 12)[p] = data;
+ } else
+ nontrivial_write(p, data, cc);
+ if (writeCallback_)
+ writeCallback_(p, (cc - basetime_) >> 1);
+ if(cdCallback_ && !biosMode_) {
+ CDMapResult map = CDMap(p);
+ if(map.type != eCDLog_AddrType_None)
+ cdCallback_(map.addr, map.type, eCDLog_Flags_Data);
}
}
-
- void ff_write(const unsigned P, const unsigned data, const unsigned long cycleCounter) {
- if (P - 0xFF80u < 0x7Fu) {
- ioamhram[P - 0xFE00] = data;
+
+ void ff_write(unsigned p, unsigned data, unsigned long cc) {
+ if (p - 0x80u < 0x7Fu) {
+ ioamhram_[p + 0x100] = data;
} else
- nontrivial_ff_write(P, data, cycleCounter);
- if (writeCallback)
- writeCallback(P, (cycleCounter - basetime) >> 1);
- if(cdCallback && !biosMode)
+ nontrivial_ff_write(p, data, cc);
+ if (writeCallback_)
+ writeCallback_(0xff00 + p, (cc - basetime_) >> 1);
+ if(cdCallback_ && !biosMode_)
{
- CDMapResult map = CDMap(P);
+ CDMapResult map = CDMap(0xff00 + p);
if(map.type != eCDLog_AddrType_None)
- cdCallback(map.addr,map.type,eCDLog_Flags_Data);
+ cdCallback_(map.addr, map.type, eCDLog_Flags_Data);
}
}
unsigned long event(unsigned long cycleCounter);
unsigned long resetCounters(unsigned long cycleCounter);
-
- int loadROM(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat);
+ LoadRes loadROM(char const *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat);
void setInputGetter(unsigned (*getInput)()) {
- this->getInput = getInput;
+ getInput_ = getInput;
}
void setReadCallback(MemoryCallback callback) {
- this->readCallback = callback;
+ this->readCallback_ = callback;
}
void setWriteCallback(MemoryCallback callback) {
- this->writeCallback = callback;
+ this->writeCallback_ = callback;
}
void setExecCallback(MemoryCallback callback) {
- this->execCallback = callback;
+ this->execCallback_ = callback;
}
void setCDCallback(CDCallback cdc) {
- this->cdCallback = cdc;
+ this->cdCallback_ = cdc;
}
void setScanlineCallback(void (*callback)(), int sl) {
- display.setScanlineCallback(callback, sl);
- }
-
- void setRTCCallback(std::uint32_t (*callback)()) {
- cart.setRTCCallback(callback);
+ lcd_.setScanlineCallback(callback, sl);
}
void setLinkCallback(void(*callback)()) {
- this->linkCallback = callback;
+ this->linkCallback_ = callback;
}
- void setBasetime(unsigned long cc) { basetime = cc; }
void setEndtime(unsigned long cc, unsigned long inc);
-
- void setSoundBuffer(uint_least32_t *const buf) { sound.setBuffer(buf); }
- unsigned fillSoundBuffer(unsigned long cc);
-
- void setVideoBuffer(uint_least32_t *const videoBuf, const int pitch) {
- display.setVideoBuffer(videoBuf, pitch);
+ void setBasetime(unsigned long cc) { basetime_ = cc; }
+
+ void setSoundBuffer(uint_least32_t *buf) { psg_.setBuffer(buf); }
+ std::size_t fillSoundBuffer(unsigned long cc);
+
+ void setVideoBuffer(uint_least32_t *videoBuf, std::ptrdiff_t pitch) {
+ lcd_.setVideoBuffer(videoBuf, pitch);
}
-
- void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned long rgb32);
+
+ void setDmgPaletteColor(int palNum, int colorNum, unsigned long rgb32) {
+ lcd_.setDmgPaletteColor(palNum, colorNum, rgb32);
+ }
+
void setCgbPalette(unsigned *lut);
-
- void blackScreen() {
- display.blackScreen();
+ void setTimeMode(bool useCycles, unsigned long const cc) {
+ cart_.setTimeMode(useCycles, cc);
}
+ void setRtcDivisorOffset(long const rtcDivisorOffset) { cart_.setRtcDivisorOffset(rtcDivisorOffset); }
- int LinkStatus(int which);
+ int linkStatus(int which);
+private:
+ Cartridge cart_;
+ unsigned char ioamhram_[0x200];
+ unsigned char *bios_;
+ std::size_t biosSize_;
+ unsigned (*getInput_)();
+ unsigned long divLastUpdate_;
+ unsigned long lastOamDmaUpdate_;
+ InterruptRequester intreq_;
+ Tima tima_;
+ LCD lcd_;
+ PSG psg_;
+ unsigned short dmaSource_;
+ unsigned short dmaDestination_;
+ unsigned char oamDmaPos_;
+ unsigned char serialCnt_;
+ bool blanklcd_;
+ bool biosMode_;
+ bool cgbSwitching_;
+ bool agbMode_;
+ bool gbIsCgb_;
+ unsigned short &sp_;
+ unsigned short &pc_;
+ unsigned long basetime_;
+ unsigned long halttime_;
+ bool stopped_;
+
+ MemoryCallback readCallback_;
+ MemoryCallback writeCallback_;
+ MemoryCallback execCallback_;
+ CDCallback cdCallback_;
+ void(*linkCallback_)();
+ bool LINKCABLE_;
+ bool linkClockTrigger_;
+
+ void decEventCycles(IntEventId eventId, unsigned long dec);
+ void oamDmaInitSetup();
+ void updateOamDma(unsigned long cycleCounter);
+ void startOamDma(unsigned long cycleCounter);
+ void endOamDma(unsigned long cycleCounter);
+ unsigned char const * oamDmaSrcPtr() const;
+ unsigned nontrivial_ff_read(unsigned p, unsigned long cycleCounter);
+ unsigned nontrivial_read(unsigned p, unsigned long cycleCounter);
+ void nontrivial_ff_write(unsigned p, unsigned data, unsigned long cycleCounter);
+ void nontrivial_write(unsigned p, unsigned data, unsigned long cycleCounter);
+ unsigned nontrivial_peek(unsigned p);
+ unsigned nontrivial_ff_peek(unsigned p);
+ void updateSerial(unsigned long cc);
+ void updateTimaIrq(unsigned long cc);
+ void updateIrqs(unsigned long cc);
+ bool isDoubleSpeed() const { return lcd_.isDoubleSpeed(); }
+
+public:
templatevoid SyncState(NewState *ns);
};
diff --git a/libgambatte/src/minkeeper.h b/libgambatte/src/minkeeper.h
index ad2d6f79d2..322d746d7c 100644
--- a/libgambatte/src/minkeeper.h
+++ b/libgambatte/src/minkeeper.h
@@ -1,157 +1,168 @@
-/***************************************************************************
- * Copyright (C) 2009 by Sindre Aamås *
- * aamas@stud.ntnu.no *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License version 2 as *
- * published by the Free Software Foundation. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License version 2 for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * version 2 along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
-***************************************************************************/
+//
+// Copyright (C) 2009 by sinamas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License version 2 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// version 2 along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
#ifndef MINKEEPER_H
#define MINKEEPER_H
#include
#include "newstate.h"
-namespace MinKeeperUtil {
-template struct CeiledLog2 { enum { R = 1 + CeiledLog2<(n + 1) / 2>::R }; };
-template<> struct CeiledLog2<1> { enum { R = 0 }; };
+namespace min_keeper_detail {
-template struct RoundedDiv2n { enum { R = RoundedDiv2n<(v + 1) / 2, n - 1>::R }; };
-template struct RoundedDiv2n { enum { R = v }; };
+template struct CeiledLog2 { enum { r = 1 + CeiledLog2<(n + 1) / 2>::r }; };
+template<> struct CeiledLog2<1> { enum { r = 0 }; };
+
+template struct CeiledDiv2n { enum { r = CeiledDiv2n<(v + 1) / 2, n - 1>::r }; };
+template struct CeiledDiv2n { enum { r = v }; };
+// alternatively: template struct CeiledDiv2n { enum { r = (v + (1 << n) - 1) >> n }; };
+
+template class T, int n> struct Sum { enum { r = T::r + Sum::r }; };
+template class T> struct Sum { enum { r = 0 }; };
-template class T, int n> struct Sum { enum { R = T::R + Sum::R }; };
-template class T> struct Sum { enum { R = 0 }; };
}
// Keeps track of minimum value identified by id as values change.
-// Higher ids prioritized (as min value) if values are equal. Can easily be reversed by swapping < for <=.
+// Higher ids prioritized (as min value) if values are equal. (Can be inverted by swapping < for <=).
// Higher ids can be faster to change when the number of ids isn't a power of 2.
-// Thus the ones that change more frequently should have higher ids if priority allows it.
+// Thus, the ones that change more frequently should have higher ids if priority allows for it.
template
class MinKeeper {
- enum { LEVELS = MinKeeperUtil::CeiledLog2::R };
- template struct Num { enum { R = MinKeeperUtil::RoundedDiv2n::R }; };
- template struct Sum { enum { R = MinKeeperUtil::Sum::R }; };
-
- template
- struct UpdateValue {
- enum { P = Sum::R + id };
- enum { C0 = Sum::R + id * 2 };
-
- static void updateValue(MinKeeper &m) {
- // GCC 4.3 generates better code with the ternary operator on i386.
- m.a[P] = (id * 2 + 1 == Num::R || m.values[m.a[C0]] < m.values[m.a[C0 + 1]]) ? m.a[C0] : m.a[C0 + 1];
- UpdateValue::updateValue(m);
- }
- };
-
- template
- struct UpdateValue {
- static void updateValue(MinKeeper &m) {
- m.minValue_ = m.values[m.a[0]];
- }
- };
-
- class UpdateValueLut {
- template struct FillLut {
- static void fillLut(UpdateValueLut & l) {
- l.lut_[id] = updateValue;
- FillLut::fillLut(l);
- }
- };
-
- template struct FillLut<-1,dummy> {
- static void fillLut(UpdateValueLut &) {}
- };
-
- void (*lut_[Num::R])(MinKeeper&);
-
- public:
- UpdateValueLut() { FillLut::R-1,0>::fillLut(*this); }
- void call(int id, MinKeeper &mk) const { lut_[id](mk); }
- };
-
- static UpdateValueLut updateValueLut;
- unsigned long values[ids];
- unsigned long minValue_;
- int a[Sum::R];
-
- template static void updateValue(MinKeeper &m);
-
public:
- explicit MinKeeper(unsigned long initValue = 0xFFFFFFFF);
-
- int min() const { return a[0]; }
+ explicit MinKeeper(unsigned long initValue);
+ int min() const { return a_[0]; }
unsigned long minValue() const { return minValue_; }
-
+
template
- void setValue(const unsigned long cnt) {
- values[id] = cnt;
+ void setValue(unsigned long cnt) {
+ values_[id] = cnt;
updateValue(*this);
}
-
- void setValue(const int id, const unsigned long cnt) {
- values[id] = cnt;
+
+ void setValue(int id, unsigned long cnt) {
+ values_[id] = cnt;
updateValueLut.call(id >> 1, *this);
}
-
- unsigned long value(const int id) const { return values[id]; }
+ unsigned long value(int id) const { return values_[id]; }
+
+private:
+ enum { height = min_keeper_detail::CeiledLog2::r };
+ template struct Num { enum { r = min_keeper_detail::CeiledDiv2n::r }; };
+ template struct Sum { enum { r = min_keeper_detail::Sum::r }; };
+
+ template
+ struct UpdateValue {
+ enum { p = Sum::r + id
+ , c0 = Sum