diff --git a/Library/DispatcherExtensions.cs b/Library/DispatcherExtensions.cs
index 645dc1c..0c3fdc0 100644
--- a/Library/DispatcherExtensions.cs
+++ b/Library/DispatcherExtensions.cs
@@ -5,7 +5,7 @@ namespace Jellyfish.Library
{
public static class DispatcherExtensions
{
- public static void CheckBeginInvoke(this Dispatcher dispatcher, Action action)
+ public static void Post(this Dispatcher dispatcher, Action action)
{
if (dispatcher == null)
{
@@ -16,18 +16,10 @@ public static void CheckBeginInvoke(this Dispatcher dispatcher, Action action)
throw new ArgumentNullException("action");
}
- if (dispatcher.CheckAccess())
- {
- action();
- }
- else
- {
- dispatcher.BeginInvoke(action);
- }
+ new DispatcherSynchronizationContext(dispatcher).Post(state => action(), null);
}
-#if WINDOWS
- public static void CheckInvoke(this Dispatcher dispatcher, Action action)
+ public static void Send(this Dispatcher dispatcher, Action action)
{
if (dispatcher == null)
{
@@ -38,15 +30,7 @@ public static void CheckInvoke(this Dispatcher dispatcher, Action action)
throw new ArgumentNullException("action");
}
- if (dispatcher.CheckAccess())
- {
- action();
- }
- else
- {
- dispatcher.Invoke(action);
- }
+ new DispatcherSynchronizationContext(dispatcher).Send(state => action(), null);
}
-#endif
}
}
diff --git a/Library/Silverlight/Jellyfish.Library.Silverlight.csproj b/Library/Silverlight/Jellyfish.Library.Silverlight.csproj
index 2050bde..02ab22d 100644
--- a/Library/Silverlight/Jellyfish.Library.Silverlight.csproj
+++ b/Library/Silverlight/Jellyfish.Library.Silverlight.csproj
@@ -65,9 +65,6 @@
-
- True
-
@@ -101,9 +98,6 @@
WaveFormat.cs
-
- XmlSerializerHelpers.cs
-
diff --git a/Library/Silverlight/Phone/Jellyfish.Library.Silverlight.Phone.csproj b/Library/Silverlight/Phone/Jellyfish.Library.Silverlight.Phone.csproj
index cfc137b..e65f7dc 100644
--- a/Library/Silverlight/Phone/Jellyfish.Library.Silverlight.Phone.csproj
+++ b/Library/Silverlight/Phone/Jellyfish.Library.Silverlight.Phone.csproj
@@ -60,7 +60,6 @@
-
@@ -75,6 +74,9 @@
IEnumerableExtensions.cs
+
+ Lazy.cs
+
MathHelpers.cs
@@ -90,9 +92,6 @@
WaveFormat.cs
-
- XmlSerializerHelpers.cs
-
ApplicationBase.cs
diff --git a/Library/Silverlight/Phone/Properties/AssemblyInfo.cs b/Library/Silverlight/Phone/Properties/AssemblyInfo.cs
index 9d84b33..02e6eca 100644
--- a/Library/Silverlight/Phone/Properties/AssemblyInfo.cs
+++ b/Library/Silverlight/Phone/Properties/AssemblyInfo.cs
@@ -11,9 +11,9 @@
[assembly: AssemblyCopyright("Copyright © 2009-2010 Digital Jellyfish Design Ltd")]
[assembly: AssemblyComment("Developed by Sean Fausett")]
-[assembly: AssemblyVersion("0.1.3.0")]
-[assembly: AssemblyFileVersion("0.1.3.0")]
-[assembly: AssemblyInformationalVersion("0.1.3.0")]
+[assembly: AssemblyVersion("0.2.0.0")]
+[assembly: AssemblyFileVersion("0.2.0.0")]
+[assembly: AssemblyInformationalVersion("0.2.0.0")]
[assembly: CLSCompliant(false)]
[assembly: ComVisible(false)]
diff --git a/Library/Silverlight/Properties/AssemblyInfo.cs b/Library/Silverlight/Properties/AssemblyInfo.cs
index dfc4fb9..972e989 100644
--- a/Library/Silverlight/Properties/AssemblyInfo.cs
+++ b/Library/Silverlight/Properties/AssemblyInfo.cs
@@ -11,9 +11,9 @@
[assembly: AssemblyCopyright("Copyright © 2009-2010 Digital Jellyfish Design Ltd")]
[assembly: AssemblyComment("Developed by Sean Fausett")]
-[assembly: AssemblyVersion("0.1.3.0")]
-[assembly: AssemblyFileVersion("0.1.3.0")]
-[assembly: AssemblyInformationalVersion("0.1.3.0")]
+[assembly: AssemblyVersion("0.2.0.0")]
+[assembly: AssemblyFileVersion("0.2.0.0")]
+[assembly: AssemblyInformationalVersion("0.2.0.0")]
[assembly: CLSCompliant(false)]
[assembly: ComVisible(false)]
diff --git a/Library/Wpf/Jellyfish.Library.Wpf.csproj b/Library/Wpf/Jellyfish.Library.Wpf.csproj
index b45dad7..01c4529 100644
--- a/Library/Wpf/Jellyfish.Library.Wpf.csproj
+++ b/Library/Wpf/Jellyfish.Library.Wpf.csproj
@@ -51,7 +51,6 @@
-
@@ -107,9 +106,6 @@
WaveFormat.cs
-
- XmlSerializerHelpers.cs
-
diff --git a/Library/Wpf/Properties/AssemblyInfo.cs b/Library/Wpf/Properties/AssemblyInfo.cs
index 55be616..0b8d668 100644
--- a/Library/Wpf/Properties/AssemblyInfo.cs
+++ b/Library/Wpf/Properties/AssemblyInfo.cs
@@ -11,9 +11,9 @@
[assembly: AssemblyCopyright("Copyright © 2009-2010 Digital Jellyfish Design Ltd")]
[assembly: AssemblyComment("Developed by Sean Fausett")]
-[assembly: AssemblyVersion("0.1.3.0")]
-[assembly: AssemblyFileVersion("0.1.3.0")]
-[assembly: AssemblyInformationalVersion("0.1.3.0")]
+[assembly: AssemblyVersion("0.2.0.0")]
+[assembly: AssemblyFileVersion("0.2.0.0")]
+[assembly: AssemblyInformationalVersion("0.2.0.0")]
[assembly: CLSCompliant(false)]
[assembly: ComVisible(false)]
diff --git a/Library/Xna/GameBase.cs b/Library/Xna/GameBase.cs
index 6bfb2d4..c33147e 100644
--- a/Library/Xna/GameBase.cs
+++ b/Library/Xna/GameBase.cs
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
+using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
@@ -21,9 +22,12 @@ public GameBase(string name)
Content.RootDirectory = "Content";
GraphicsDeviceManager = new GraphicsDeviceManager(this);
#if WINDOWS_PHONE
+ GraphicsDeviceManager.IsFullScreen = true;
TargetElapsedTime = TimeSpan.FromTicks(333333); // 30 fps
#elif XBOX
Components.Add(new GamerServicesComponent(this));
+#else
+ SynchronizationContext = new System.Windows.Forms.WindowsFormsSynchronizationContext();
#endif
GraphicsDeviceService = (IGraphicsDeviceService)Services.GetService(typeof(IGraphicsDeviceService));
@@ -48,5 +52,8 @@ protected override void Update(GameTime gameTime)
public string Name { get; private set; }
public GraphicsDeviceManager GraphicsDeviceManager { get; private set; }
public IGraphicsDeviceService GraphicsDeviceService { get; private set; }
+#if WINDOWS
+ public SynchronizationContext SynchronizationContext { get; private set; }
+#endif
}
}
diff --git a/Library/Xna/Jellyfish.Library.Xna.Phone.csproj b/Library/Xna/Jellyfish.Library.Xna.Phone.csproj
index 39fb189..c577a79 100644
--- a/Library/Xna/Jellyfish.Library.Xna.Phone.csproj
+++ b/Library/Xna/Jellyfish.Library.Xna.Phone.csproj
@@ -83,13 +83,6 @@
False
-
- 4.0
- False
-
-
- False
-
@@ -116,9 +109,6 @@
StringBuilderExtensions.cs
-
- XmlSerializerHelpers.cs
-
diff --git a/Library/Xna/Jellyfish.Library.Xna.Xbox.csproj b/Library/Xna/Jellyfish.Library.Xna.Xbox.csproj
index d5157db..7e899d9 100644
--- a/Library/Xna/Jellyfish.Library.Xna.Xbox.csproj
+++ b/Library/Xna/Jellyfish.Library.Xna.Xbox.csproj
@@ -98,13 +98,6 @@
False
-
- 4.0
- False
-
-
- False
-
@@ -131,9 +124,6 @@
StringBuilderExtensions.cs
-
- XmlSerializerHelpers.cs
-
diff --git a/Library/Xna/Jellyfish.Library.Xna.csproj b/Library/Xna/Jellyfish.Library.Xna.csproj
index 289517a..692ba95 100644
--- a/Library/Xna/Jellyfish.Library.Xna.csproj
+++ b/Library/Xna/Jellyfish.Library.Xna.csproj
@@ -95,11 +95,10 @@
4.0
False
-
+
False
-
- 4.0
+
False
@@ -140,9 +139,6 @@
StringBuilderExtensions.cs
-
- XmlSerializerHelpers.cs
-
diff --git a/Library/Xna/Properties/AssemblyInfo.cs b/Library/Xna/Properties/AssemblyInfo.cs
index 1257789..13881d3 100644
--- a/Library/Xna/Properties/AssemblyInfo.cs
+++ b/Library/Xna/Properties/AssemblyInfo.cs
@@ -17,9 +17,9 @@
[assembly: AssemblyCopyright("Copyright © 2009-2010 Digital Jellyfish Design Ltd")]
[assembly: AssemblyComment("Developed by Sean Fausett")]
-[assembly: AssemblyVersion("0.1.3.0")]
-[assembly: AssemblyFileVersion("0.1.3.0")]
-[assembly: AssemblyInformationalVersion("0.1.3.0")]
+[assembly: AssemblyVersion("0.2.0.0")]
+[assembly: AssemblyFileVersion("0.2.0.0")]
+[assembly: AssemblyInformationalVersion("0.2.0.0")]
[assembly: CLSCompliant(false)]
[assembly: ComVisible(false)]
diff --git a/Virtu/Cpu.cs b/Virtu/Cpu.cs
index d926a1a..a2b9773 100644
--- a/Virtu/Cpu.cs
+++ b/Virtu/Cpu.cs
@@ -1,6 +1,7 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
+using System.IO;
namespace Jellyfish.Virtu
{
@@ -144,16 +145,17 @@ public Cpu(Machine machine) :
Execute65X02SedF8, Execute65C02SbcF9, Execute65C02PlxFA, Execute65C02NopFB,
Execute65C02NopFC, Execute65C02SbcFD, Execute65C02IncFE, Execute65C02NopFF
};
-
- RS = 0xFF;
}
public override void Initialize()
{
_memory = Machine.Memory;
- UpdateSettings();
- Machine.Video.VSync += (sender, e) => UpdateSettings();
+ Is65C02 = true;
+ IsThrottled = true;
+ Multiplier = 1;
+
+ RS = 0xFF;
}
public override void Reset()
@@ -161,15 +163,53 @@ public override void Reset()
RS = (RS - 3) & 0xFF; // [4-14]
RPC = _memory.ReadRomRegionE0FF(0xFFFC) | (_memory.ReadRomRegionE0FF(0xFFFD) << 8);
RP |= (PB | PI);
- if (Machine.Settings.Cpu.Is65C02) // [C-10]
+ if (Is65C02) // [C-10]
{
RP &= ~PD;
}
}
+ public override void LoadState(BinaryReader reader, Version version)
+ {
+ if (reader == null)
+ {
+ throw new ArgumentNullException("reader");
+ }
+
+ Is65C02 = reader.ReadBoolean();
+ IsThrottled = reader.ReadBoolean();
+ Multiplier = reader.ReadInt32();
+
+ RA = reader.ReadInt32();
+ RX = reader.ReadInt32();
+ RY = reader.ReadInt32();
+ RS = reader.ReadInt32();
+ RP = reader.ReadInt32();
+ RPC = reader.ReadInt32();
+ }
+
+ public override void SaveState(BinaryWriter writer)
+ {
+ if (writer == null)
+ {
+ throw new ArgumentNullException("writer");
+ }
+
+ writer.Write(Is65C02);
+ writer.Write(IsThrottled);
+ writer.Write(Multiplier);
+
+ writer.Write(RA);
+ writer.Write(RX);
+ writer.Write(RY);
+ writer.Write(RS);
+ writer.Write(RP);
+ writer.Write(RPC);
+ }
+
public override string ToString()
{
- return string.Format(CultureInfo.CurrentCulture, "A = 0x{0:X2} X = 0x{1:X2} Y = 0x{2:X2} P = 0x{3:X2} S = 0x01{4:X2} PC = 0x{5:X4} EA = 0x{6:X4} CC = {7}",
+ return string.Format(CultureInfo.InvariantCulture, "A = 0x{0:X2} X = 0x{1:X2} Y = 0x{2:X2} P = 0x{3:X2} S = 0x01{4:X2} PC = 0x{5:X4} EA = 0x{6:X4} CC = {7}",
RA, RX, RY, RP, RS, RPC, EA, CC);
}
@@ -184,11 +224,6 @@ public int Execute()
return CC;
}
- public void ToggleThrottle()
- {
- Machine.Settings.Cpu.IsThrottled ^= true;
- }
-
#region Core Operand Actions
private void GetAddressAbs() // abs
{
@@ -740,7 +775,7 @@ private void ExecuteIrq(int cc)
Push(RPC & 0xFF);
Push(RP & ~PB);
RP |= PI;
- if (Machine.Settings.Cpu.Is65C02) // [C-10]
+ if (Is65C02) // [C-10]
{
RP &= ~PD;
}
@@ -830,7 +865,7 @@ private void ExecuteNmi(int cc)
Push(RPC & 0xFF);
Push(RP & ~PB);
RP |= PI;
- if (Machine.Settings.Cpu.Is65C02) // [C-10]
+ if (Is65C02) // [C-10]
{
RP &= ~PD;
}
@@ -3203,10 +3238,9 @@ private void Execute65C02Tsb0C() // tsb abs
}
#endregion
- private void UpdateSettings()
- {
- _executeOpCode = Machine.Settings.Cpu.Is65C02 ? ExecuteOpCode65C02 : ExecuteOpCode65N02;
- }
+ public bool Is65C02 { get { return _is65C02; } set { _is65C02 = value; _executeOpCode = _is65C02 ? ExecuteOpCode65C02 : ExecuteOpCode65N02; } }
+ public bool IsThrottled { get; set; }
+ public int Multiplier { get; set; }
public int RA { get; private set; }
public int RX { get; private set; }
@@ -3221,6 +3255,7 @@ private void UpdateSettings()
private Memory _memory;
+ private bool _is65C02;
private Action[] _executeOpCode;
}
}
diff --git a/Virtu/Disk525.cs b/Virtu/Disk525.cs
index 040a94d..4bcdb26 100644
--- a/Virtu/Disk525.cs
+++ b/Virtu/Disk525.cs
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
+using System.IO;
namespace Jellyfish.Virtu
{
@@ -35,6 +36,34 @@ public static Disk525 CreateDisk(string name, byte[] data, bool isWriteProtected
return null;
}
+ [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "version")]
+ public static Disk525 LoadState(BinaryReader reader, Version version)
+ {
+ if (reader == null)
+ {
+ throw new ArgumentNullException("reader");
+ }
+
+ string name = reader.ReadString();
+ bool isWriteProtected = reader.ReadBoolean();
+ byte[] data = reader.ReadBytes(reader.ReadInt32());
+
+ return CreateDisk(name, data, isWriteProtected);
+ }
+
+ public void SaveState(BinaryWriter writer)
+ {
+ if (writer == null)
+ {
+ throw new ArgumentNullException("writer");
+ }
+
+ writer.Write(Name);
+ writer.Write(IsWriteProtected);
+ writer.Write(Data.Length);
+ writer.Write(Data);
+ }
+
public abstract void ReadTrack(int number, int fraction, byte[] buffer);
public abstract void WriteTrack(int number, int fraction, byte[] buffer);
diff --git a/Virtu/DiskIIController.cs b/Virtu/DiskIIController.cs
index 4ee4476..dced1fa 100644
--- a/Virtu/DiskIIController.cs
+++ b/Virtu/DiskIIController.cs
@@ -1,7 +1,8 @@
-using System.Diagnostics.CodeAnalysis;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
using Jellyfish.Library;
using Jellyfish.Virtu.Services;
-using Jellyfish.Virtu.Settings;
namespace Jellyfish.Virtu
{
@@ -14,21 +15,8 @@ public DiskIIController(Machine machine) :
public override void Initialize()
{
- var romStream = StorageService.GetResourceStream("Roms/DiskII.rom", 0x0100);
- romStream.ReadBlock(_romRegionC1C7, 0x0000, 0x0100);
-
- _drives[0].InsertDisk("Default.dsk", StorageService.GetResourceStream("Disks/Default.dsk", 0x23000), false);
-#if WINDOWS
- var settings = Machine.Settings.DiskII;
- if (settings.Disk1.Name.Length > 0)
- {
- _drives[0].InsertDisk(settings.Disk1.Name, settings.Disk1.IsWriteProtected);
- }
- if (settings.Disk2.Name.Length > 0)
- {
- _drives[1].InsertDisk(settings.Disk2.Name, settings.Disk2.IsWriteProtected);
- }
-#endif
+ StorageService.LoadResource("Roms/DiskII.rom", 0x0100, stream => stream.ReadBlock(_romRegionC1C7, 0, 0x0100));
+ StorageService.LoadResource("Disks/Default.dsk", 0x23000, stream => _drives[0].InsertDisk("Default.dsk", stream, false));
}
public override void Reset()
@@ -40,9 +28,38 @@ public override void Reset()
_writeMode = false;
}
- public override void Uninitialize()
+ public override void LoadState(BinaryReader reader, Version version)
{
- Flush();
+ if (reader == null)
+ {
+ throw new ArgumentNullException("reader");
+ }
+
+ _latch = reader.ReadInt32();
+ _phaseStates = reader.ReadInt32();
+ _motorOn = reader.ReadBoolean();
+ _driveNumber = reader.ReadInt32();
+ _loadMode = reader.ReadBoolean();
+ _writeMode = reader.ReadBoolean();
+ _driveSpin = reader.ReadBoolean();
+ _drives.ForEach(drive => drive.LoadState(reader, version));
+ }
+
+ public override void SaveState(BinaryWriter writer)
+ {
+ if (writer == null)
+ {
+ throw new ArgumentNullException("writer");
+ }
+
+ writer.Write(_latch);
+ writer.Write(_phaseStates);
+ writer.Write(_motorOn);
+ writer.Write(_driveNumber);
+ writer.Write(_loadMode);
+ writer.Write(_writeMode);
+ writer.Write(_driveSpin);
+ _drives.ForEach(drive => drive.SaveState(writer));
}
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
diff --git a/Virtu/DiskIIDrive.cs b/Virtu/DiskIIDrive.cs
index fc2249e..a9ae9db 100644
--- a/Virtu/DiskIIDrive.cs
+++ b/Virtu/DiskIIDrive.cs
@@ -1,7 +1,7 @@
using System;
using System.IO;
-using System.Security;
using Jellyfish.Library;
+using Jellyfish.Virtu.Services;
namespace Jellyfish.Virtu
{
@@ -15,13 +15,49 @@ public DiskIIDrive()
DriveArmStepDelta[3] = new int[] { 0, 1, 0, 1, -1, 0, -1, 0, 0, 1, 0, 1, -1, 0, -1, 0 }; // phase 3
}
- [SecurityCritical]
+ public void LoadState(BinaryReader reader, Version version)
+ {
+ if (reader == null)
+ {
+ throw new ArgumentNullException("reader");
+ }
+
+ _trackLoaded = reader.ReadBoolean();
+ _trackChanged = reader.ReadBoolean();
+ _trackNumber = reader.ReadInt32();
+ _trackOffset = reader.ReadInt32();
+ if (_trackLoaded)
+ {
+ reader.Read(_trackData, 0, _trackData.Length);
+ }
+ _disk = reader.ReadBoolean() ? Disk525.LoadState(reader, version) : null;
+ }
+
+ public void SaveState(BinaryWriter writer)
+ {
+ if (writer == null)
+ {
+ throw new ArgumentNullException("writer");
+ }
+
+ writer.Write(_trackLoaded);
+ writer.Write(_trackChanged);
+ writer.Write(_trackNumber);
+ writer.Write(_trackOffset);
+ if (_trackLoaded)
+ {
+ writer.Write(_trackData);
+ }
+ writer.Write(_disk != null);
+ if (_disk != null)
+ {
+ _disk.SaveState(writer);
+ }
+ }
+
public void InsertDisk(string fileName, bool isWriteProtected)
{
- using (var stream = File.OpenRead(fileName))
- {
- InsertDisk(fileName, stream, isWriteProtected);
- }
+ StorageService.LoadFile(fileName, stream => InsertDisk(fileName, stream, isWriteProtected));
}
public void InsertDisk(string name, Stream stream, bool isWriteProtected)
diff --git a/Virtu/GamePort.cs b/Virtu/GamePort.cs
index ff56aea..8d420a1 100644
--- a/Virtu/GamePort.cs
+++ b/Virtu/GamePort.cs
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
+using System.IO;
using Jellyfish.Library;
using Jellyfish.Virtu.Services;
@@ -20,30 +21,88 @@ public override void Initialize()
{
_keyboardService = Machine.Services.GetService();
_gamePortService = Machine.Services.GetService();
+
+ JoystickDeadZone = 0.4;
+ }
+
+ public override void LoadState(BinaryReader reader, Version version)
+ {
+ if (reader == null)
+ {
+ throw new ArgumentNullException("reader");
+ }
+
+ JoystickDeadZone = reader.ReadDouble();
+
+ UseKeyboard = reader.ReadBoolean();
+ Joystick0UpLeftKey = reader.ReadInt32();
+ Joystick0UpKey = reader.ReadInt32();
+ Joystick0UpRightKey = reader.ReadInt32();
+ Joystick0LeftKey = reader.ReadInt32();
+ Joystick0RightKey = reader.ReadInt32();
+ Joystick0DownLeftKey = reader.ReadInt32();
+ Joystick0DownKey = reader.ReadInt32();
+ Joystick0DownRightKey = reader.ReadInt32();
+ Joystick1UpLeftKey = reader.ReadInt32();
+ Joystick1UpKey = reader.ReadInt32();
+ Joystick1UpRightKey = reader.ReadInt32();
+ Joystick1LeftKey = reader.ReadInt32();
+ Joystick1RightKey = reader.ReadInt32();
+ Joystick1DownLeftKey = reader.ReadInt32();
+ Joystick1DownKey = reader.ReadInt32();
+ Joystick1DownRightKey = reader.ReadInt32();
+ Button0Key = reader.ReadInt32();
+ Button1Key = reader.ReadInt32();
+ Button2Key = reader.ReadInt32();
+ }
+
+ public override void SaveState(BinaryWriter writer)
+ {
+ if (writer == null)
+ {
+ throw new ArgumentNullException("writer");
+ }
+
+ writer.Write(JoystickDeadZone);
+
+ writer.Write(UseKeyboard);
+ writer.Write(Joystick0UpLeftKey);
+ writer.Write(Joystick0UpKey);
+ writer.Write(Joystick0UpRightKey);
+ writer.Write(Joystick0LeftKey);
+ writer.Write(Joystick0RightKey);
+ writer.Write(Joystick0DownLeftKey);
+ writer.Write(Joystick0DownKey);
+ writer.Write(Joystick0DownRightKey);
+ writer.Write(Joystick1UpLeftKey);
+ writer.Write(Joystick1UpKey);
+ writer.Write(Joystick1UpRightKey);
+ writer.Write(Joystick1LeftKey);
+ writer.Write(Joystick1RightKey);
+ writer.Write(Joystick1DownLeftKey);
+ writer.Write(Joystick1DownKey);
+ writer.Write(Joystick1DownRightKey);
+ writer.Write(Button0Key);
+ writer.Write(Button1Key);
+ writer.Write(Button2Key);
}
public bool ReadButton0()
{
- var settings = Machine.Settings.GamePort;
-
return (_gamePortService.IsButton0Down || _keyboardService.IsOpenAppleKeyDown ||
- (settings.UseKeyboard && (settings.Key.Button0 > 0) && _keyboardService.IsKeyDown(settings.Key.Button0)));
+ (UseKeyboard && (Button0Key > 0) && _keyboardService.IsKeyDown(Button0Key)));
}
public bool ReadButton1()
{
- var settings = Machine.Settings.GamePort;
-
return (_gamePortService.IsButton1Down || _keyboardService.IsCloseAppleKeyDown ||
- (settings.UseKeyboard && (settings.Key.Button1 > 0) && _keyboardService.IsKeyDown(settings.Key.Button1)));
+ (UseKeyboard && (Button1Key > 0) && _keyboardService.IsKeyDown(Button1Key)));
}
public bool ReadButton2()
{
- var settings = Machine.Settings.GamePort;
-
return (_gamePortService.IsButton2Down || !_keyboardService.IsShiftKeyDown || // Shift' [TN9]
- (settings.UseKeyboard && (settings.Key.Button2 > 0) && _keyboardService.IsKeyDown(settings.Key.Button2)));
+ (UseKeyboard && (Button2Key > 0) && _keyboardService.IsKeyDown(Button2Key)));
}
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
@@ -54,55 +113,53 @@ public void TriggerTimers()
int paddle2 = _gamePortService.Paddle2;
int paddle3 = _gamePortService.Paddle3;
- var settings = Machine.Settings.GamePort;
-
- if (settings.UseKeyboard) // override
+ if (UseKeyboard) // override
{
- if (((settings.Key.Joystick0.UpLeft > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick0.UpLeft)) ||
- ((settings.Key.Joystick0.Left > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick0.Left)) ||
- ((settings.Key.Joystick0.DownLeft > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick0.DownLeft)))
+ if (((Joystick0UpLeftKey > 0) && _keyboardService.IsKeyDown(Joystick0UpLeftKey)) ||
+ ((Joystick0LeftKey > 0) && _keyboardService.IsKeyDown(Joystick0LeftKey)) ||
+ ((Joystick0DownLeftKey > 0) && _keyboardService.IsKeyDown(Joystick0DownLeftKey)))
{
paddle0 -= 128;
}
- if (((settings.Key.Joystick0.UpRight > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick0.UpRight)) ||
- ((settings.Key.Joystick0.Right > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick0.Right)) ||
- ((settings.Key.Joystick0.DownRight > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick0.DownRight)))
+ if (((Joystick0UpRightKey > 0) && _keyboardService.IsKeyDown(Joystick0UpRightKey)) ||
+ ((Joystick0RightKey > 0) && _keyboardService.IsKeyDown(Joystick0RightKey)) ||
+ ((Joystick0DownRightKey > 0) && _keyboardService.IsKeyDown(Joystick0DownRightKey)))
{
paddle0 += 128;
}
- if (((settings.Key.Joystick0.UpLeft > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick0.UpLeft)) ||
- ((settings.Key.Joystick0.Up > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick0.Up)) ||
- ((settings.Key.Joystick0.UpRight > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick0.UpRight)))
+ if (((Joystick0UpLeftKey > 0) && _keyboardService.IsKeyDown(Joystick0UpLeftKey)) ||
+ ((Joystick0UpKey > 0) && _keyboardService.IsKeyDown(Joystick0UpKey)) ||
+ ((Joystick0UpRightKey > 0) && _keyboardService.IsKeyDown(Joystick0UpRightKey)))
{
paddle1 -= 128;
}
- if (((settings.Key.Joystick0.DownLeft > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick0.DownLeft)) ||
- ((settings.Key.Joystick0.Down > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick0.Down)) ||
- ((settings.Key.Joystick0.DownRight > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick0.DownRight)))
+ if (((Joystick0DownLeftKey > 0) && _keyboardService.IsKeyDown(Joystick0DownLeftKey)) ||
+ ((Joystick0DownKey > 0) && _keyboardService.IsKeyDown(Joystick0DownKey)) ||
+ ((Joystick0DownRightKey > 0) && _keyboardService.IsKeyDown(Joystick0DownRightKey)))
{
paddle1 += 128;
}
- if (((settings.Key.Joystick1.UpLeft > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick1.UpLeft)) ||
- ((settings.Key.Joystick1.Left > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick1.Left)) ||
- ((settings.Key.Joystick1.DownLeft > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick1.DownLeft)))
+ if (((Joystick1UpLeftKey > 0) && _keyboardService.IsKeyDown(Joystick1UpLeftKey)) ||
+ ((Joystick1LeftKey > 0) && _keyboardService.IsKeyDown(Joystick1LeftKey)) ||
+ ((Joystick1DownLeftKey > 0) && _keyboardService.IsKeyDown(Joystick1DownLeftKey)))
{
paddle2 -= 128;
}
- if (((settings.Key.Joystick1.UpRight > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick1.UpRight)) ||
- ((settings.Key.Joystick1.Right > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick1.Right)) ||
- ((settings.Key.Joystick1.DownRight > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick1.DownRight)))
+ if (((Joystick1UpRightKey > 0) && _keyboardService.IsKeyDown(Joystick1UpRightKey)) ||
+ ((Joystick1RightKey > 0) && _keyboardService.IsKeyDown(Joystick1RightKey)) ||
+ ((Joystick1DownRightKey > 0) && _keyboardService.IsKeyDown(Joystick1DownRightKey)))
{
paddle2 += 128;
}
- if (((settings.Key.Joystick1.UpLeft > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick1.UpLeft)) ||
- ((settings.Key.Joystick1.Up > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick1.Up)) ||
- ((settings.Key.Joystick1.UpRight > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick1.UpRight)))
+ if (((Joystick1UpLeftKey > 0) && _keyboardService.IsKeyDown(Joystick1UpLeftKey)) ||
+ ((Joystick1UpKey > 0) && _keyboardService.IsKeyDown(Joystick1UpKey)) ||
+ ((Joystick1UpRightKey > 0) && _keyboardService.IsKeyDown(Joystick1UpRightKey)))
{
paddle3 -= 128;
}
- if (((settings.Key.Joystick1.DownLeft > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick1.DownLeft)) ||
- ((settings.Key.Joystick1.Down > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick1.Down)) ||
- ((settings.Key.Joystick1.DownRight > 0) && _keyboardService.IsKeyDown(settings.Key.Joystick1.DownRight)))
+ if (((Joystick1DownLeftKey > 0) && _keyboardService.IsKeyDown(Joystick1DownLeftKey)) ||
+ ((Joystick1DownKey > 0) && _keyboardService.IsKeyDown(Joystick1DownKey)) ||
+ ((Joystick1DownRightKey > 0) && _keyboardService.IsKeyDown(Joystick1DownRightKey)))
{
paddle3 += 128;
}
@@ -139,6 +196,29 @@ private void ResetPaddle3StrobeEvent()
Paddle3Strobe = false;
}
+ public double JoystickDeadZone { get; set; }
+
+ public bool UseKeyboard { get; set; }
+ public int Joystick0UpLeftKey { get; set; }
+ public int Joystick0UpKey { get; set; }
+ public int Joystick0UpRightKey { get; set; }
+ public int Joystick0LeftKey { get; set; }
+ public int Joystick0RightKey { get; set; }
+ public int Joystick0DownLeftKey { get; set; }
+ public int Joystick0DownKey { get; set; }
+ public int Joystick0DownRightKey { get; set; }
+ public int Joystick1UpLeftKey { get; set; }
+ public int Joystick1UpKey { get; set; }
+ public int Joystick1UpRightKey { get; set; }
+ public int Joystick1LeftKey { get; set; }
+ public int Joystick1RightKey { get; set; }
+ public int Joystick1DownLeftKey { get; set; }
+ public int Joystick1DownKey { get; set; }
+ public int Joystick1DownRightKey { get; set; }
+ public int Button0Key { get; set; }
+ public int Button1Key { get; set; }
+ public int Button2Key { get; set; }
+
public bool Paddle0Strobe { get; private set; }
public bool Paddle1Strobe { get; private set; }
public bool Paddle2Strobe { get; private set; }
diff --git a/Virtu/Keyboard.cs b/Virtu/Keyboard.cs
index a1b4663..a839f32 100644
--- a/Virtu/Keyboard.cs
+++ b/Virtu/Keyboard.cs
@@ -1,4 +1,6 @@
-using System.Diagnostics.CodeAnalysis;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
using Jellyfish.Virtu.Services;
namespace Jellyfish.Virtu
@@ -16,6 +18,64 @@ public override void Initialize()
_gamePortService = Machine.Services.GetService();
}
+ public override void LoadState(BinaryReader reader, Version version)
+ {
+ if (reader == null)
+ {
+ throw new ArgumentNullException("reader");
+ }
+
+ UseGamePort = reader.ReadBoolean();
+ Joystick0UpLeftKey = reader.ReadInt32();
+ Joystick0UpKey = reader.ReadInt32();
+ Joystick0UpRightKey = reader.ReadInt32();
+ Joystick0LeftKey = reader.ReadInt32();
+ Joystick0RightKey = reader.ReadInt32();
+ Joystick0DownLeftKey = reader.ReadInt32();
+ Joystick0DownKey = reader.ReadInt32();
+ Joystick0DownRightKey = reader.ReadInt32();
+ Joystick1UpLeftKey = reader.ReadInt32();
+ Joystick1UpKey = reader.ReadInt32();
+ Joystick1UpRightKey = reader.ReadInt32();
+ Joystick1LeftKey = reader.ReadInt32();
+ Joystick1RightKey = reader.ReadInt32();
+ Joystick1DownLeftKey = reader.ReadInt32();
+ Joystick1DownKey = reader.ReadInt32();
+ Joystick1DownRightKey = reader.ReadInt32();
+ Button0Key = reader.ReadInt32();
+ Button1Key = reader.ReadInt32();
+ Button2Key = reader.ReadInt32();
+ }
+
+ public override void SaveState(BinaryWriter writer)
+ {
+ if (writer == null)
+ {
+ throw new ArgumentNullException("writer");
+ }
+
+ writer.Write(UseGamePort);
+ writer.Write(Joystick0UpLeftKey);
+ writer.Write(Joystick0UpKey);
+ writer.Write(Joystick0UpRightKey);
+ writer.Write(Joystick0LeftKey);
+ writer.Write(Joystick0RightKey);
+ writer.Write(Joystick0DownLeftKey);
+ writer.Write(Joystick0DownKey);
+ writer.Write(Joystick0DownRightKey);
+ writer.Write(Joystick1UpLeftKey);
+ writer.Write(Joystick1UpKey);
+ writer.Write(Joystick1UpRightKey);
+ writer.Write(Joystick1LeftKey);
+ writer.Write(Joystick1RightKey);
+ writer.Write(Joystick1DownLeftKey);
+ writer.Write(Joystick1DownKey);
+ writer.Write(Joystick1DownRightKey);
+ writer.Write(Button0Key);
+ writer.Write(Button1Key);
+ writer.Write(Button2Key);
+ }
+
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
public int ReadLatch()
{
@@ -24,87 +84,85 @@ public int ReadLatch()
return Latch;
}
- var settings = Machine.Settings.Keyboard;
-
- if (settings.UseGamePort)
+ if (UseGamePort)
{
- if ((settings.Key.Joystick0.UpLeft > 0) && _gamePortService.Joystick0.IsUp && _gamePortService.Joystick0.IsLeft)
+ if ((Joystick0UpLeftKey > 0) && _gamePortService.IsJoystick0Up && _gamePortService.IsJoystick0Left)
{
- Latch = settings.Key.Joystick0.UpLeft;
+ Latch = Joystick0UpLeftKey;
}
- else if ((settings.Key.Joystick0.UpRight > 0) && _gamePortService.Joystick0.IsUp && _gamePortService.Joystick0.IsRight)
+ else if ((Joystick0UpRightKey > 0) && _gamePortService.IsJoystick0Up && _gamePortService.IsJoystick0Right)
{
- Latch = settings.Key.Joystick0.UpRight;
+ Latch = Joystick0UpRightKey;
}
- else if ((settings.Key.Joystick0.DownLeft > 0) && _gamePortService.Joystick0.IsDown && _gamePortService.Joystick0.IsLeft)
+ else if ((Joystick0DownLeftKey > 0) && _gamePortService.IsJoystick0Down && _gamePortService.IsJoystick0Left)
{
- Latch = settings.Key.Joystick0.DownLeft;
+ Latch = Joystick0DownLeftKey;
}
- else if ((settings.Key.Joystick0.DownRight > 0) && _gamePortService.Joystick0.IsDown && _gamePortService.Joystick0.IsRight)
+ else if ((Joystick0DownRightKey > 0) && _gamePortService.IsJoystick0Down && _gamePortService.IsJoystick0Right)
{
- Latch = settings.Key.Joystick0.DownRight;
+ Latch = Joystick0DownRightKey;
}
- else if ((settings.Key.Joystick0.Up > 0) && _gamePortService.Joystick0.IsUp)
+ else if ((Joystick0UpKey > 0) && _gamePortService.IsJoystick0Up)
{
- Latch = settings.Key.Joystick0.Up;
+ Latch = Joystick0UpKey;
}
- else if ((settings.Key.Joystick0.Left > 0) && _gamePortService.Joystick0.IsLeft)
+ else if ((Joystick0LeftKey > 0) && _gamePortService.IsJoystick0Left)
{
- Latch = settings.Key.Joystick0.Left;
+ Latch = Joystick0LeftKey;
}
- else if ((settings.Key.Joystick0.Right > 0) && _gamePortService.Joystick0.IsRight)
+ else if ((Joystick0RightKey > 0) && _gamePortService.IsJoystick0Right)
{
- Latch = settings.Key.Joystick0.Right;
+ Latch = Joystick0RightKey;
}
- else if ((settings.Key.Joystick0.Down > 0) && _gamePortService.Joystick0.IsDown)
+ else if ((Joystick0DownKey > 0) && _gamePortService.IsJoystick0Down)
{
- Latch = settings.Key.Joystick0.Down;
+ Latch = Joystick0DownKey;
}
- if ((settings.Key.Joystick1.UpLeft > 0) && _gamePortService.Joystick1.IsUp && _gamePortService.Joystick1.IsLeft) // override
+ if ((Joystick1UpLeftKey > 0) && _gamePortService.IsJoystick1Up && _gamePortService.IsJoystick1Left) // override
{
- Latch = settings.Key.Joystick1.UpLeft;
+ Latch = Joystick1UpLeftKey;
}
- else if ((settings.Key.Joystick1.UpRight > 0) && _gamePortService.Joystick1.IsUp && _gamePortService.Joystick1.IsRight)
+ else if ((Joystick1UpRightKey > 0) && _gamePortService.IsJoystick1Up && _gamePortService.IsJoystick1Right)
{
- Latch = settings.Key.Joystick1.UpRight;
+ Latch = Joystick1UpRightKey;
}
- else if ((settings.Key.Joystick1.DownLeft > 0) && _gamePortService.Joystick1.IsDown && _gamePortService.Joystick1.IsLeft)
+ else if ((Joystick1DownLeftKey > 0) && _gamePortService.IsJoystick1Down && _gamePortService.IsJoystick1Left)
{
- Latch = settings.Key.Joystick1.DownLeft;
+ Latch = Joystick1DownLeftKey;
}
- else if ((settings.Key.Joystick1.DownRight > 0) && _gamePortService.Joystick1.IsDown && _gamePortService.Joystick1.IsRight)
+ else if ((Joystick1DownRightKey > 0) && _gamePortService.IsJoystick1Down && _gamePortService.IsJoystick1Right)
{
- Latch = settings.Key.Joystick1.DownRight;
+ Latch = Joystick1DownRightKey;
}
- else if ((settings.Key.Joystick1.Up > 0) && _gamePortService.Joystick1.IsUp)
+ else if ((Joystick1UpKey > 0) && _gamePortService.IsJoystick1Up)
{
- Latch = settings.Key.Joystick1.Up;
+ Latch = Joystick1UpKey;
}
- else if ((settings.Key.Joystick1.Left > 0) && _gamePortService.Joystick1.IsLeft)
+ else if ((Joystick1LeftKey > 0) && _gamePortService.IsJoystick1Left)
{
- Latch = settings.Key.Joystick1.Left;
+ Latch = Joystick1LeftKey;
}
- else if ((settings.Key.Joystick1.Right > 0) && _gamePortService.Joystick1.IsRight)
+ else if ((Joystick1RightKey > 0) && _gamePortService.IsJoystick1Right)
{
- Latch = settings.Key.Joystick1.Right;
+ Latch = Joystick1RightKey;
}
- else if ((settings.Key.Joystick1.Down > 0) && _gamePortService.Joystick1.IsDown)
+ else if ((Joystick1DownKey > 0) && _gamePortService.IsJoystick1Down)
{
- Latch = settings.Key.Joystick1.Down;
+ Latch = Joystick1DownKey;
}
- if ((settings.Key.Button0 > 0) && _gamePortService.IsButton0Down) // override
+ if ((Button0Key > 0) && _gamePortService.IsButton0Down) // override
{
- Latch = settings.Key.Button0;
+ Latch = Button0Key;
}
- else if ((settings.Key.Button1 > 0) && _gamePortService.IsButton1Down)
+ else if ((Button1Key > 0) && _gamePortService.IsButton1Down)
{
- Latch = settings.Key.Button1;
+ Latch = Button1Key;
}
- else if ((settings.Key.Button2 > 0) && _gamePortService.IsButton2Down)
+ else if ((Button2Key > 0) && _gamePortService.IsButton2Down)
{
- Latch = settings.Key.Button2;
+ Latch = Button2Key;
}
}
@@ -116,6 +174,27 @@ public void ResetStrobe()
Strobe = false;
}
+ public bool UseGamePort { get; set; }
+ public int Joystick0UpLeftKey { get; set; }
+ public int Joystick0UpKey { get; set; }
+ public int Joystick0UpRightKey { get; set; }
+ public int Joystick0LeftKey { get; set; }
+ public int Joystick0RightKey { get; set; }
+ public int Joystick0DownLeftKey { get; set; }
+ public int Joystick0DownKey { get; set; }
+ public int Joystick0DownRightKey { get; set; }
+ public int Joystick1UpLeftKey { get; set; }
+ public int Joystick1UpKey { get; set; }
+ public int Joystick1UpRightKey { get; set; }
+ public int Joystick1LeftKey { get; set; }
+ public int Joystick1RightKey { get; set; }
+ public int Joystick1DownLeftKey { get; set; }
+ public int Joystick1DownKey { get; set; }
+ public int Joystick1DownRightKey { get; set; }
+ public int Button0Key { get; set; }
+ public int Button1Key { get; set; }
+ public int Button2Key { get; set; }
+
public bool IsAnyKeyDown { get { return _keyboardService.IsAnyKeyDown; } }
public int Latch { get { return _latch; } set { _latch = value; Strobe = true; } }
public bool Strobe { get; private set; }
diff --git a/Virtu/Machine.cs b/Virtu/Machine.cs
index e6a6c18..a8e4557 100644
--- a/Virtu/Machine.cs
+++ b/Virtu/Machine.cs
@@ -1,9 +1,11 @@
using System;
using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
using System.Threading;
using Jellyfish.Library;
using Jellyfish.Virtu.Services;
-using Jellyfish.Virtu.Settings;
namespace Jellyfish.Virtu
{
@@ -15,7 +17,6 @@ public Machine()
{
Events = new MachineEvents();
Services = new MachineServices();
- Settings = new MachineSettings();
Cpu = new Cpu(this);
Memory = new Memory(this);
@@ -36,7 +37,7 @@ public Machine()
Slot7 = emptySlot;
Slots = new Collection { null, Slot1, Slot2, Slot3, Slot4, Slot5, Slot6, Slot7 };
- Components = new Collection { Cpu, Memory, Keyboard, GamePort, Cassette, Speaker, Video, Slot1, Slot2, Slot3, Slot4, Slot5, Slot6, Slot7 };
+ Components = new Collection { Cpu, Memory, Keyboard, GamePort, Cassette, Speaker, Video, NoSlotClock, Slot1, Slot2, Slot3, Slot4, Slot5, Slot6, Slot7 };
Thread = new Thread(Run) { Name = "Machine" };
}
@@ -49,14 +50,11 @@ public void Dispose()
public void Reset()
{
- Components.ForEach(component => component.Reset()); // while machine starting or paused
+ Components.ForEach(component => component.Reset());
}
public void Start()
{
- _storageService = Services.GetService();
- _storageService.Load(MachineSettings.FileName, stream => Settings.Deserialize(stream));
-
State = MachineState.Starting;
Thread.Start();
}
@@ -83,11 +81,6 @@ public void Stop()
Thread.Join();
}
State = MachineState.Stopped;
-
- if (_storageService != null)
- {
- _storageService.Save(MachineSettings.FileName, stream => Settings.Serialize(stream));
- }
}
public DiskIIController FindDiskIIController()
@@ -104,10 +97,59 @@ public DiskIIController FindDiskIIController()
return null;
}
- private void Run() // machine thread
+ private void Initialize()
{
Components.ForEach(component => component.Initialize());
+ }
+
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+ private void LoadState()
+ {
+ var storageService = Services.GetService();
+ storageService.Load(Machine.LastStateFileName, stream =>
+ {
+ try
+ {
+ var version = new Version(Version);
+ using (var reader = new BinaryReader(stream))
+ {
+ version = new Version(reader.ReadString());
+ Components.ForEach(component => component.LoadState(reader, version));
+ }
+ }
+ catch (Exception)
+ {
+ if (Debugger.IsAttached)
+ {
+ Debugger.Break();
+ }
+ }
+ });
+ }
+
+ private void Uninitialize()
+ {
+ Components.ForEach(component => component.Uninitialize());
+ }
+
+ private void SaveState()
+ {
+ var storageService = Services.GetService();
+ storageService.Save(Machine.LastStateFileName, stream =>
+ {
+ using (var writer = new BinaryWriter(stream))
+ {
+ writer.Write(Version);
+ Components.ForEach(component => component.SaveState(writer));
+ }
+ });
+ }
+
+ private void Run() // machine thread
+ {
+ Initialize();
Reset();
+ LoadState();
State = MachineState.Running;
do
@@ -126,12 +168,14 @@ private void Run() // machine thread
}
while (State != MachineState.Stopping);
- Components.ForEach(component => component.Uninitialize());
+ SaveState();
+ Uninitialize();
}
+ public const string Version = "0.9.0.0";
+
public MachineEvents Events { get; private set; }
public MachineServices Services { get; private set; }
- public MachineSettings Settings { get; private set; }
public MachineState State { get; private set; }
public Cpu Cpu { get; private set; }
@@ -156,9 +200,9 @@ private void Run() // machine thread
public Thread Thread { get; private set; }
+ private const string LastStateFileName = "LastState.bin";
+
private AutoResetEvent _pauseEvent = new AutoResetEvent(false);
private AutoResetEvent _unpauseEvent = new AutoResetEvent(false);
-
- private StorageService _storageService;
}
}
diff --git a/Virtu/MachineComponent.cs b/Virtu/MachineComponent.cs
index 44e1078..e1e3836 100644
--- a/Virtu/MachineComponent.cs
+++ b/Virtu/MachineComponent.cs
@@ -1,4 +1,7 @@
-namespace Jellyfish.Virtu
+using System;
+using System.IO;
+
+namespace Jellyfish.Virtu
{
public abstract class MachineComponent
{
@@ -15,10 +18,18 @@ public virtual void Reset()
{
}
+ public virtual void LoadState(BinaryReader reader, Version version)
+ {
+ }
+
public virtual void Uninitialize()
{
}
+ public virtual void SaveState(BinaryWriter writer)
+ {
+ }
+
protected Machine Machine { get; private set; }
}
}
diff --git a/Virtu/MachineEvents.cs b/Virtu/MachineEvents.cs
index a6013ef..f008d04 100644
--- a/Virtu/MachineEvents.cs
+++ b/Virtu/MachineEvents.cs
@@ -14,7 +14,7 @@ public MachineEvent(int delta, Action action)
public override string ToString()
{
- return string.Format(CultureInfo.CurrentCulture, "Delta = {0} Action = {{{1}.{2}}}", Delta, Action.Method.DeclaringType.Name, Action.Method.Name);
+ return string.Format(CultureInfo.InvariantCulture, "Delta = {0} Action = {{{1}.{2}}}", Delta, Action.Method.DeclaringType.Name, Action.Method.Name);
}
public int Delta { get; set; }
diff --git a/Virtu/MachineSettings.cs b/Virtu/MachineSettings.cs
deleted file mode 100644
index d4314fd..0000000
--- a/Virtu/MachineSettings.cs
+++ /dev/null
@@ -1,408 +0,0 @@
-using System;
-using System.Diagnostics.CodeAnalysis;
-using System.IO;
-using System.Xml;
-using System.Xml.Linq;
-
-namespace Jellyfish.Virtu.Settings
-{
- public sealed class MachineSettings
- {
- public MachineSettings()
- {
- Cpu = new CpuSettings { Is65C02 = true, IsThrottled = true, Multiplier = 1 };
- DiskII = new DiskIISettings
- {
- Disk1 = new DiskSettings { Name = string.Empty, IsWriteProtected = false },
- Disk2 = new DiskSettings { Name = string.Empty, IsWriteProtected = false }
- };
- Keyboard = new KeyboardSettings
- {
- UseGamePort = false,
- Key = new KeySettings
- {
- Joystick0 = new JoystickSettings { UpLeft = 0, Up = 'I', UpRight = 0, Left = 'J', Right = 'L', DownLeft = 0, Down = 'K', DownRight = 0 },
- Joystick1 = new JoystickSettings { UpLeft = 0, Up = 'E', UpRight = 0, Left = 'S', Right = 'F', DownLeft = 0, Down = 'D', DownRight = 0 },
- Button0 = 0, Button1 = 0, Button2 = 0
- }
- };
- GamePort = new GamePortSettings
- {
- UseKeyboard = false,
- Key = new KeySettings
- {
- Joystick0 = new JoystickSettings { UpLeft = 0, Up = 0, UpRight = 0, Left = 0, Right = 0, DownLeft = 0, Down = 0, DownRight = 0 },
- Joystick1 = new JoystickSettings { UpLeft = 0, Up = 0, UpRight = 0, Left = 0, Right = 0, DownLeft = 0, Down = 0, DownRight = 0 },
- Button0 = 0, Button1 = 0, Button2 = 0
- }
- };
- Audio = new AudioSettings { Volume = 0.5 };
- Video = new VideoSettings
- {
- IsFullScreen = false, IsMonochrome = false, ScannerOptions = ScannerOptions.None,
- Color = new ColorSettings
- {
- Black = 0xFF000000, // BGRA
- DarkBlue = 0xFF000099,
- DarkGreen = 0xFF117722,
- MediumBlue = 0xFF0000FF,
- Brown = 0xFF885500,
- LightGrey = 0xFF99AAAA,
- Green = 0xFF00EE11,
- Aquamarine = 0xFF55FFAA,
- DeepRed = 0xFFFF1111,
- Purple = 0xFFDD00DD,
- DarkGrey = 0xFF445555,
- LightBlue = 0xFF33AAFF,
- Orange = 0xFFFF4411,
- Pink = 0xFFFF9988,
- Yellow = 0xFFFFFF11,
- White = 0xFFFFFFFF,
- Monochrome = 0xFF00AA00
- }
- };
- }
-
- [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
- public void Deserialize(Stream stream)
- {
- try
- {
- using (var reader = XmlReader.Create(stream))
- {
- var ns = Namespace;
- var root = XElement.Load(reader);
- var cpu = root.Element(ns + "Cpu");
- Cpu = new CpuSettings
- {
- Is65C02 = (bool)cpu.Attribute("Is65C02"),
- IsThrottled = (bool)cpu.Attribute("IsThrottled"),
- Multiplier = (int)cpu.Attribute("Multiplier")
- };
- var diskII = root.Element(ns + "DiskII");
- var disk1 = diskII.Element(ns + "Disk1");
- var disk2 = diskII.Element(ns + "Disk2");
- DiskII = new DiskIISettings
- {
- Disk1 = new DiskSettings
- {
- Name = (string)disk1.Attribute("Name") ?? string.Empty,
- IsWriteProtected = (bool)disk1.Attribute("IsWriteProtected")
- },
- Disk2 = new DiskSettings
- {
- Name = (string)disk2.Attribute("Name") ?? string.Empty,
- IsWriteProtected = (bool)disk2.Attribute("IsWriteProtected")
- },
- };
- var keyboard = root.Element(ns + "Keyboard");
- var key = keyboard.Element(ns + "Key");
- var joystick0 = key.Element(ns + "Joystick0");
- var joystick1 = key.Element(ns + "Joystick1");
- var buttons = key.Element(ns + "Buttons");
- Keyboard = new KeyboardSettings
- {
- UseGamePort = (bool)keyboard.Attribute("UseGamePort"),
- Key = new KeySettings
- {
- Joystick0 = new JoystickSettings
- {
- UpLeft = (int)joystick0.Attribute("UpLeft"),
- Up = (int)joystick0.Attribute("Up"),
- UpRight = (int)joystick0.Attribute("UpRight"),
- Left = (int)joystick0.Attribute("Left"),
- Right = (int)joystick0.Attribute("Right"),
- DownLeft = (int)joystick0.Attribute("DownLeft"),
- Down = (int)joystick0.Attribute("Down"),
- DownRight = (int)joystick0.Attribute("DownRight")
- },
- Joystick1 = new JoystickSettings
- {
- UpLeft = (int)joystick1.Attribute("UpLeft"),
- Up = (int)joystick1.Attribute("Up"),
- UpRight = (int)joystick1.Attribute("UpRight"),
- Left = (int)joystick1.Attribute("Left"),
- Right = (int)joystick1.Attribute("Right"),
- DownLeft = (int)joystick1.Attribute("DownLeft"),
- Down = (int)joystick1.Attribute("Down"),
- DownRight = (int)joystick1.Attribute("DownRight")
- },
- Button0 = (int)buttons.Attribute("Button0"),
- Button1 = (int)buttons.Attribute("Button1"),
- Button2 = (int)buttons.Attribute("Button2")
- }
- };
- var gamePort = root.Element(ns + "GamePort");
- key = gamePort.Element(ns + "Key");
- joystick0 = key.Element(ns + "Joystick0");
- joystick1 = key.Element(ns + "Joystick1");
- buttons = key.Element(ns + "Buttons");
- GamePort = new GamePortSettings
- {
- UseKeyboard = (bool)gamePort.Attribute("UseKeyboard"),
- Key = new KeySettings
- {
- Joystick0 = new JoystickSettings
- {
- UpLeft = (int)joystick0.Attribute("UpLeft"),
- Up = (int)joystick0.Attribute("Up"),
- UpRight = (int)joystick0.Attribute("UpRight"),
- Left = (int)joystick0.Attribute("Left"),
- Right = (int)joystick0.Attribute("Right"),
- DownLeft = (int)joystick0.Attribute("DownLeft"),
- Down = (int)joystick0.Attribute("Down"),
- DownRight = (int)joystick0.Attribute("DownRight")
- },
- Joystick1 = new JoystickSettings
- {
- UpLeft = (int)joystick1.Attribute("UpLeft"),
- Up = (int)joystick1.Attribute("Up"),
- UpRight = (int)joystick1.Attribute("UpRight"),
- Left = (int)joystick1.Attribute("Left"),
- Right = (int)joystick1.Attribute("Right"),
- DownLeft = (int)joystick1.Attribute("DownLeft"),
- Down = (int)joystick1.Attribute("Down"),
- DownRight = (int)joystick1.Attribute("DownRight")
- },
- Button0 = (int)buttons.Attribute("Button0"),
- Button1 = (int)buttons.Attribute("Button1"),
- Button2 = (int)buttons.Attribute("Button2")
- }
- };
- var audio = root.Element(ns + "Audio");
- Audio = new AudioSettings
- {
- Volume = (double)audio.Attribute("Volume")
- };
- var video = root.Element(ns + "Video");
- var color = video.Element(ns + "Color");
- Video = new VideoSettings
- {
- IsFullScreen = (bool)video.Attribute("IsFullScreen"),
- IsMonochrome = (bool)video.Attribute("IsMonochrome"),
- ScannerOptions = (ScannerOptions)Enum.Parse(typeof(ScannerOptions), (string)video.Attribute("ScannerOptions"), true),
- Color = new ColorSettings
- {
- Black = (uint)color.Attribute("Black"),
- DarkBlue = (uint)color.Attribute("DarkBlue"),
- DarkGreen = (uint)color.Attribute("DarkGreen"),
- MediumBlue = (uint)color.Attribute("MediumBlue"),
- Brown = (uint)color.Attribute("Brown"),
- LightGrey = (uint)color.Attribute("LightGrey"),
- Green = (uint)color.Attribute("Green"),
- Aquamarine = (uint)color.Attribute("Aquamarine"),
- DeepRed = (uint)color.Attribute("DeepRed"),
- Purple = (uint)color.Attribute("Purple"),
- DarkGrey = (uint)color.Attribute("DarkGrey"),
- LightBlue = (uint)color.Attribute("LightBlue"),
- Orange = (uint)color.Attribute("Orange"),
- Pink = (uint)color.Attribute("Pink"),
- Yellow = (uint)color.Attribute("Yellow"),
- White = (uint)color.Attribute("White"),
- Monochrome = (uint)color.Attribute("Monochrome")
- }
- };
- }
- }
- catch (Exception)
- {
- }
- }
-
- public void Serialize(Stream stream)
- {
- var ns = Namespace;
- var xml = new XElement(ns + "MachineSettings",
- new XElement(ns + "Cpu",
- new XAttribute("Is65C02", Cpu.Is65C02),
- new XAttribute("IsThrottled", Cpu.IsThrottled),
- new XAttribute("Multiplier", Cpu.Multiplier)),
- new XElement(ns + "DiskII",
- new XElement(ns + "Disk1",
- new XAttribute("Name", DiskII.Disk1.Name),
- new XAttribute("IsWriteProtected", DiskII.Disk1.IsWriteProtected)),
- new XElement(ns + "Disk2",
- new XAttribute("Name", DiskII.Disk2.Name),
- new XAttribute("IsWriteProtected", DiskII.Disk2.IsWriteProtected))),
- new XElement(ns + "Keyboard",
- new XAttribute("UseGamePort", Keyboard.UseGamePort),
- new XElement(ns + "Key",
- new XElement(ns + "Joystick0",
- new XAttribute("UpLeft", Keyboard.Key.Joystick0.UpLeft),
- new XAttribute("Up", Keyboard.Key.Joystick0.Up),
- new XAttribute("UpRight", Keyboard.Key.Joystick0.UpRight),
- new XAttribute("Left", Keyboard.Key.Joystick0.Left),
- new XAttribute("Right", Keyboard.Key.Joystick0.Right),
- new XAttribute("DownLeft", Keyboard.Key.Joystick0.DownLeft),
- new XAttribute("Down", Keyboard.Key.Joystick0.Down),
- new XAttribute("DownRight", Keyboard.Key.Joystick0.DownRight)),
- new XElement(ns + "Joystick1",
- new XAttribute("UpLeft", Keyboard.Key.Joystick1.UpLeft),
- new XAttribute("Up", Keyboard.Key.Joystick1.Up),
- new XAttribute("UpRight", Keyboard.Key.Joystick1.UpRight),
- new XAttribute("Left", Keyboard.Key.Joystick1.Left),
- new XAttribute("Right", Keyboard.Key.Joystick1.Right),
- new XAttribute("DownLeft", Keyboard.Key.Joystick1.DownLeft),
- new XAttribute("Down", Keyboard.Key.Joystick1.Down),
- new XAttribute("DownRight", Keyboard.Key.Joystick1.DownRight)),
- new XElement(ns + "Buttons",
- new XAttribute("Button0", Keyboard.Key.Button0),
- new XAttribute("Button1", Keyboard.Key.Button1),
- new XAttribute("Button2", Keyboard.Key.Button2)))),
- new XElement(ns + "GamePort",
- new XAttribute("UseKeyboard", GamePort.UseKeyboard),
- new XElement(ns + "Key",
- new XElement(ns + "Joystick0",
- new XAttribute("UpLeft", GamePort.Key.Joystick0.UpLeft),
- new XAttribute("Up", GamePort.Key.Joystick0.Up),
- new XAttribute("UpRight", GamePort.Key.Joystick0.UpRight),
- new XAttribute("Left", GamePort.Key.Joystick0.Left),
- new XAttribute("Right", GamePort.Key.Joystick0.Right),
- new XAttribute("DownLeft", GamePort.Key.Joystick0.DownLeft),
- new XAttribute("Down", GamePort.Key.Joystick0.Down),
- new XAttribute("DownRight", GamePort.Key.Joystick0.DownRight)),
- new XElement(ns + "Joystick1",
- new XAttribute("UpLeft", GamePort.Key.Joystick1.UpLeft),
- new XAttribute("Up", GamePort.Key.Joystick1.Up),
- new XAttribute("UpRight", GamePort.Key.Joystick1.UpRight),
- new XAttribute("Left", GamePort.Key.Joystick1.Left),
- new XAttribute("Right", GamePort.Key.Joystick1.Right),
- new XAttribute("DownLeft", GamePort.Key.Joystick1.DownLeft),
- new XAttribute("Down", GamePort.Key.Joystick1.Down),
- new XAttribute("DownRight", GamePort.Key.Joystick1.DownRight)),
- new XElement(ns + "Buttons",
- new XAttribute("Button0", Keyboard.Key.Button0),
- new XAttribute("Button1", Keyboard.Key.Button1),
- new XAttribute("Button2", Keyboard.Key.Button2)))),
- new XElement(ns + "Audio",
- new XAttribute("Volume", Audio.Volume)),
- new XElement(ns + "Video",
- new XAttribute("IsFullScreen", Video.IsFullScreen),
- new XAttribute("IsMonochrome", Video.IsMonochrome),
- new XAttribute("ScannerOptions", Video.ScannerOptions),
- new XElement(ns + "Color",
- new XAttribute("Black", Video.Color.Black),
- new XAttribute("DarkBlue", Video.Color.DarkBlue),
- new XAttribute("DarkGreen", Video.Color.DarkGreen),
- new XAttribute("MediumBlue", Video.Color.MediumBlue),
- new XAttribute("Brown", Video.Color.Brown),
- new XAttribute("LightGrey", Video.Color.LightGrey),
- new XAttribute("Green", Video.Color.Green),
- new XAttribute("Aquamarine", Video.Color.Aquamarine),
- new XAttribute("DeepRed", Video.Color.DeepRed),
- new XAttribute("Purple", Video.Color.Purple),
- new XAttribute("DarkGrey", Video.Color.DarkGrey),
- new XAttribute("LightBlue", Video.Color.LightBlue),
- new XAttribute("Orange", Video.Color.Orange),
- new XAttribute("Pink", Video.Color.Pink),
- new XAttribute("Yellow", Video.Color.Yellow),
- new XAttribute("White", Video.Color.White),
- new XAttribute("Monochrome", Video.Color.Monochrome))));
-
- using (var writer = XmlWriter.Create(stream))
- {
- xml.WriteTo(writer);
- }
- }
-
- public CpuSettings Cpu { get; set; }
- public DiskIISettings DiskII { get; set; }
- public KeyboardSettings Keyboard { get; set; }
- public GamePortSettings GamePort { get; set; }
- public AudioSettings Audio { get; set; }
- public VideoSettings Video { get; set; }
-
- public const string FileName = "Settings.xml";
- [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
- public static readonly XNamespace Namespace = "http://schemas.jellyfish.co.nz/virtu/settings";
- }
-
- public sealed class CpuSettings
- {
- public bool Is65C02 { get; set; }
- public bool IsThrottled { get; set; }
- public int Multiplier { get; set; }
- }
-
- public sealed class DiskSettings
- {
- public string Name { get; set; }
- public bool IsWriteProtected { get; set; }
- };
-
- public sealed class DiskIISettings
- {
- public DiskSettings Disk1 { get; set; }
- public DiskSettings Disk2 { get; set; }
- };
-
- public sealed class JoystickSettings
- {
- public int UpLeft { get; set; }
- public int Up { get; set; }
- public int UpRight { get; set; }
- public int Left { get; set; }
- public int Right { get; set; }
- public int DownLeft { get; set; }
- public int Down { get; set; }
- public int DownRight { get; set; }
- };
-
- public sealed class KeySettings
- {
- public JoystickSettings Joystick0 { get; set; }
- public JoystickSettings Joystick1 { get; set; }
- public int Button0 { get; set; }
- public int Button1 { get; set; }
- public int Button2 { get; set; }
- };
-
- public sealed class KeyboardSettings
- {
- public bool UseGamePort { get; set; }
- public KeySettings Key { get; set; }
- }
-
- public sealed class GamePortSettings
- {
- public bool UseKeyboard { get; set; }
- public KeySettings Key { get; set; }
- }
-
- public sealed class AudioSettings
- {
- public double Volume { get; set; }
- };
-
- public sealed class ColorSettings
- {
- public uint Black { get; set; }
- public uint DarkBlue { get; set; }
- public uint DarkGreen { get; set; }
- public uint MediumBlue { get; set; }
- public uint Brown { get; set; }
- public uint LightGrey { get; set; }
- public uint Green { get; set; }
- public uint Aquamarine { get; set; }
- public uint DeepRed { get; set; }
- public uint Purple { get; set; }
- public uint DarkGrey { get; set; }
- public uint LightBlue { get; set; }
- public uint Orange { get; set; }
- public uint Pink { get; set; }
- public uint Yellow { get; set; }
- public uint White { get; set; }
- public uint Monochrome { get; set; }
- }
-
- [Flags]
- public enum ScannerOptions { None = 0x0, AppleII = 0x1, Pal = 0x2 } // defaults to AppleIIe, Ntsc
-
- public sealed class VideoSettings
- {
- public bool IsFullScreen { get; set; }
- public bool IsMonochrome { get; set; }
- public ScannerOptions ScannerOptions { get; set; }
- public ColorSettings Color { get; set; }
- };
-}
diff --git a/Virtu/Memory.cs b/Virtu/Memory.cs
index 8417e6a..3e675cb 100644
--- a/Virtu/Memory.cs
+++ b/Virtu/Memory.cs
@@ -77,6 +77,12 @@ public Memory(Machine machine) :
WriteRamModeBankRegion[Video.ModeF][BankAux][Region080B] = WriteRamModeFAuxRegion080B;
WriteRamModeBankRegion[Video.ModeF][BankAux][Region203F] = WriteRamModeFAuxRegion203F;
WriteRamModeBankRegion[Video.ModeF][BankAux][Region405F] = WriteRamModeFAuxRegion405F;
+
+ _writeIoRegionC0C0 = WriteIoRegionC0C0; // cache delegates; avoids garbage
+ _writeIoRegionC1C7 = WriteIoRegionC1C7;
+ _writeIoRegionC3C3 = WriteIoRegionC3C3;
+ _writeIoRegionC8CF = WriteIoRegionC8CF;
+ _writeRomRegionD0FF = WriteRomRegionD0FF;
}
public override void Initialize()
@@ -88,11 +94,13 @@ public override void Initialize()
_video = Machine.Video;
_noSlotClock = Machine.NoSlotClock;
- var romStream = StorageService.GetResourceStream("Roms/AppleIIe.rom", 0x4000);
- romStream.Seek(0x0100, SeekOrigin.Current);
- romStream.ReadBlock(_romInternalRegionC1CF, 0x0000, 0x0F00);
- romStream.ReadBlock(_romRegionD0DF, 0x0000, 0x1000);
- romStream.ReadBlock(_romRegionE0FF, 0x0000, 0x2000);
+ StorageService.LoadResource("Roms/AppleIIe.rom", 0x4000, stream =>
+ {
+ stream.Seek(0x0100, SeekOrigin.Current);
+ stream.ReadBlock(_romInternalRegionC1CF, 0, _romInternalRegionC1CF.Length);
+ stream.ReadBlock(_romRegionD0DF, 0, _romRegionD0DF.Length);
+ stream.ReadBlock(_romRegionE0FF, 0, _romRegionE0FF.Length);
+ });
if ((ReadRomRegionE0FF(0xFBB3) == 0x06) && (ReadRomRegionE0FF(0xFBBF) == 0xC1))
{
@@ -116,6 +124,55 @@ public override void Reset() // [7-3]
MapRegionD0FF();
}
+ public override void LoadState(BinaryReader reader, Version version)
+ {
+ if (reader == null)
+ {
+ throw new ArgumentNullException("reader");
+ }
+
+ _state = reader.ReadInt32();
+ _slotRegionC8CF = reader.ReadInt32();
+
+ reader.Read(_ramMainRegion0001, 0, _ramMainRegion0001.Length);
+ reader.Read(_ramMainRegion02BF, 0, _ramMainRegion02BF.Length);
+ reader.Read(_ramMainBank1RegionD0DF, 0, _ramMainBank1RegionD0DF.Length);
+ reader.Read(_ramMainBank2RegionD0DF, 0, _ramMainBank2RegionD0DF.Length);
+ reader.Read(_ramMainRegionE0FF, 0, _ramMainRegionE0FF.Length);
+ reader.Read(_ramAuxRegion0001, 0, _ramAuxRegion0001.Length);
+ reader.Read(_ramAuxRegion02BF, 0, _ramAuxRegion02BF.Length);
+ reader.Read(_ramAuxBank1RegionD0DF, 0, _ramAuxBank1RegionD0DF.Length);
+ reader.Read(_ramAuxBank2RegionD0DF, 0, _ramAuxBank2RegionD0DF.Length);
+ reader.Read(_ramAuxRegionE0FF, 0, _ramAuxRegionE0FF.Length);
+
+ MapRegion0001();
+ MapRegion02BF();
+ MapRegionC0CF();
+ MapRegionD0FF();
+ }
+
+ public override void SaveState(BinaryWriter writer)
+ {
+ if (writer == null)
+ {
+ throw new ArgumentNullException("writer");
+ }
+
+ writer.Write(_state);
+ writer.Write(_slotRegionC8CF);
+
+ writer.Write(_ramMainRegion0001);
+ writer.Write(_ramMainRegion02BF);
+ writer.Write(_ramMainBank1RegionD0DF);
+ writer.Write(_ramMainBank2RegionD0DF);
+ writer.Write(_ramMainRegionE0FF);
+ writer.Write(_ramAuxRegion0001);
+ writer.Write(_ramAuxRegion02BF);
+ writer.Write(_ramAuxBank1RegionD0DF);
+ writer.Write(_ramAuxBank2RegionD0DF);
+ writer.Write(_ramAuxRegionE0FF);
+ }
+
#region Core Read & Write
public int Read(int address)
{
@@ -1203,10 +1260,10 @@ private void MapRegionC0CF()
_regionWrite[RegionC1C7] = null;
_regionWrite[RegionC3C3] = null;
_regionWrite[RegionC8CF] = null;
- _writeRegion[RegionC0C0] = WriteIoRegionC0C0;
- _writeRegion[RegionC1C7] = WriteIoRegionC1C7;
- _writeRegion[RegionC3C3] = WriteIoRegionC3C3;
- _writeRegion[RegionC8CF] = WriteIoRegionC8CF;
+ _writeRegion[RegionC0C0] = _writeIoRegionC0C0;
+ _writeRegion[RegionC1C7] = _writeIoRegionC1C7;
+ _writeRegion[RegionC3C3] = _writeIoRegionC3C3;
+ _writeRegion[RegionC8CF] = _writeIoRegionC8CF;
}
private void MapRegionD0FF()
@@ -1248,8 +1305,8 @@ private void MapRegionD0FF()
{
_regionWrite[RegionD0DF] = null;
_regionWrite[RegionE0FF] = null;
- _writeRegion[RegionD0DF] = WriteRomRegionD0FF;
- _writeRegion[RegionE0FF] = WriteRomRegionD0FF;
+ _writeRegion[RegionD0DF] = _writeRomRegionD0FF;
+ _writeRegion[RegionE0FF] = _writeRomRegionD0FF;
}
}
@@ -1533,6 +1590,12 @@ private bool TestState(int mask, int value)
public MonitorType Monitor { get; private set; }
public int VideoMode { get { return StateVideoMode[_state & StateVideo]; } }
+ private Action _writeIoRegionC0C0;
+ private Action _writeIoRegionC1C7;
+ private Action _writeIoRegionC3C3;
+ private Action _writeIoRegionC8CF;
+ private Action _writeRomRegionD0FF;
+
private Keyboard _keyboard;
private GamePort _gamePort;
private Cassette _cassette;
diff --git a/Virtu/NoSlotClock.cs b/Virtu/NoSlotClock.cs
index 72574b6..9ff1292 100644
--- a/Virtu/NoSlotClock.cs
+++ b/Virtu/NoSlotClock.cs
@@ -1,5 +1,5 @@
using System;
-using System.Collections;
+using System.IO;
namespace Jellyfish.Virtu
{
@@ -8,7 +8,42 @@ public sealed class NoSlotClock : MachineComponent
public NoSlotClock(Machine machine) :
base(machine)
{
- ResetClock();
+ }
+
+ public override void Initialize()
+ {
+ _clockEnabled = false;
+ _writeEnabled = true;
+ _clockRegister = new RingRegister(0x0, 0x1);
+ _comparisonRegister = new RingRegister(ClockInitSequence, 0x1);
+ }
+
+ public override void LoadState(BinaryReader reader, Version version)
+ {
+ if (reader == null)
+ {
+ throw new ArgumentNullException("reader");
+ }
+
+ _clockEnabled = reader.ReadBoolean();
+ _writeEnabled = reader.ReadBoolean();
+ _clockRegister = new RingRegister(reader.ReadUInt64(), reader.ReadUInt64());
+ _comparisonRegister = new RingRegister(reader.ReadUInt64(), reader.ReadUInt64());
+ }
+
+ public override void SaveState(BinaryWriter writer)
+ {
+ if (writer == null)
+ {
+ throw new ArgumentNullException("writer");
+ }
+
+ writer.Write(_clockEnabled);
+ writer.Write(_writeEnabled);
+ writer.Write(_clockRegister.Data);
+ writer.Write(_clockRegister.Mask);
+ writer.Write(_comparisonRegister.Data);
+ writer.Write(_comparisonRegister.Mask);
}
public int Read(int address, int data)
@@ -36,18 +71,10 @@ public void Write(int address)
}
}
- private void ResetClock()
- {
- // SmartWatch reset - whether tied to system reset is component specific
- _comparisonRegister.Reset();
- _clockRegisterEnabled = false;
- _writeEnabled = true;
- }
-
private int ReadClock(int data)
{
// for a ROM, A2 high = read, and data out (if any) is on D0
- if (!_clockRegisterEnabled)
+ if (!_clockEnabled)
{
_comparisonRegister.Reset();
_writeEnabled = true;
@@ -57,7 +84,7 @@ private int ReadClock(int data)
data = _clockRegister.ReadBit(Machine.Video.ReadFloatingBus());
if (_clockRegister.NextBit())
{
- _clockRegisterEnabled = false;
+ _clockEnabled = false;
}
return data;
}
@@ -70,13 +97,13 @@ private void WriteClock(int address)
return;
}
- if (!_clockRegisterEnabled)
+ if (!_clockEnabled)
{
if ((_comparisonRegister.CompareBit(address)))
{
if (_comparisonRegister.NextBit())
{
- _clockRegisterEnabled = true;
+ _clockEnabled = true;
PopulateClockRegister();
}
}
@@ -89,7 +116,7 @@ private void WriteClock(int address)
else if (_clockRegister.NextBit())
{
// simulate writes, but our clock register is read-only
- _clockRegisterEnabled = false;
+ _clockEnabled = false;
}
}
@@ -133,18 +160,17 @@ private void PopulateClockRegister()
private const ulong ClockInitSequence = 0x5CA33AC55CA33AC5;
- private bool _clockRegisterEnabled;
+ private bool _clockEnabled;
private bool _writeEnabled;
- private RingRegister _clockRegister = new RingRegister();
- private RingRegister _comparisonRegister = new RingRegister(ClockInitSequence);
+ private RingRegister _clockRegister;
+ private RingRegister _comparisonRegister;
- private sealed class RingRegister
+ private struct RingRegister
{
- public RingRegister(ulong data = 0)
+ public RingRegister(ulong data, ulong mask)
{
- _register = data;
-
- Reset();
+ _data = data;
+ _mask = mask;
}
public void Reset()
@@ -169,17 +195,17 @@ public void WriteBits(int data, int count)
public void WriteBit(int data)
{
- _register = ((data & 0x1) != 0) ? (_register | _mask) : (_register & ~_mask);
+ _data = ((data & 0x1) != 0) ? (_data | _mask) : (_data & ~_mask);
}
public int ReadBit(int data)
{
- return ((_register & _mask) != 0) ? (data | 0x1) : (data & ~0x1);
+ return ((_data & _mask) != 0) ? (data | 0x1) : (data & ~0x1);
}
public bool CompareBit(int data)
{
- return (((_register & _mask) != 0) == ((data & 0x1) != 0));
+ return (((_data & _mask) != 0) == ((data & 0x1) != 0));
}
public bool NextBit()
@@ -192,8 +218,11 @@ public bool NextBit()
return false;
}
+ public ulong Data { get { return _data; } } // no auto props
+ public ulong Mask { get { return _mask; } }
+
+ private ulong _data;
private ulong _mask;
- private ulong _register;
}
}
}
diff --git a/Virtu/Services/AudioService.cs b/Virtu/Services/AudioService.cs
index 4d83b77..8465389 100644
--- a/Virtu/Services/AudioService.cs
+++ b/Virtu/Services/AudioService.cs
@@ -27,8 +27,7 @@ public void Output(int data) // machine thread
_index = (_index + 2) % SampleSize;
if (_index == 0)
{
- _readEvent.Set();
- if (Machine.Settings.Cpu.IsThrottled)
+ if (Machine.Cpu.IsThrottled)
{
_writeEvent.WaitOne(SampleLatency * 2); // allow timeout; avoids deadlock
}
@@ -40,18 +39,10 @@ public void Reset()
Buffer.BlockCopy(SampleZero, 0, _buffer, 0, SampleSize);
}
- public abstract void SetVolume(double volume); // machine thread
+ public abstract void SetVolume(double volume);
- protected void Update(int bufferSize, Action updateBuffer) // audio thread
+ protected void Update() // audio thread
{
- if (Machine.State == MachineState.Running)
- {
- _readEvent.WaitOne(SampleLatency * 2); // allow timeout; avoids deadlock
- }
- if (updateBuffer != null)
- {
- updateBuffer(_buffer, bufferSize);
- }
_writeEvent.Set();
}
@@ -64,10 +55,12 @@ protected void Update(int bufferSize, Action updateBuffer) // audio
[SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
protected static readonly byte[] SampleZero = new byte[SampleSize];
+ [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
+ protected byte[] Source { get { return _buffer; } }
+
private byte[] _buffer = new byte[SampleSize];
private int _index;
- private AutoResetEvent _readEvent = new AutoResetEvent(false);
private AutoResetEvent _writeEvent = new AutoResetEvent(false);
}
}
diff --git a/Virtu/Services/GamePortService.cs b/Virtu/Services/GamePortService.cs
index 395eebb..c5f5674 100644
--- a/Virtu/Services/GamePortService.cs
+++ b/Virtu/Services/GamePortService.cs
@@ -1,53 +1,5 @@
namespace Jellyfish.Virtu.Services
{
- public struct Joystick
- {
- public Joystick(bool isUp, bool isLeft, bool isRight, bool isDown)
- {
- _isUp = isUp;
- _isLeft = isLeft;
- _isRight = isRight;
- _isDown = isDown;
- }
-
- public override bool Equals(object obj)
- {
- return ((obj is Joystick) && (this == (Joystick)obj));
- }
-
- public override int GetHashCode()
- {
- return (_isUp.GetHashCode() ^ _isLeft.GetHashCode() ^ _isRight.GetHashCode() ^ _isDown.GetHashCode());
- }
-
- public override string ToString()
- {
- return !(_isUp || _isDown || _isLeft || _isRight) ? "Position = Center" :
- string.Concat("Position = ", _isUp ? "Up" : _isDown ? "Down" : string.Empty, _isLeft ? "Left" : _isRight ? "Right" : string.Empty);
- }
-
- public static bool operator ==(Joystick joystick1, Joystick joystick2)
- {
- return ((joystick1._isUp == joystick2._isUp) && (joystick1._isLeft == joystick2._isLeft) &&
- (joystick1._isRight == joystick2._isRight) && (joystick1._isDown == joystick2._isDown));
- }
-
- public static bool operator !=(Joystick joystick1, Joystick joystick2)
- {
- return !(joystick1 == joystick2);
- }
-
- public bool IsUp { get { return _isUp; } } // no auto props
- public bool IsLeft { get { return _isLeft; } }
- public bool IsRight { get { return _isRight; } }
- public bool IsDown { get { return _isDown; } }
-
- private bool _isUp;
- private bool _isLeft;
- private bool _isRight;
- private bool _isDown;
- }
-
public class GamePortService : MachineService
{
public GamePortService(Machine machine) :
@@ -63,8 +15,15 @@ public virtual void Update() { } // main thread
public int Paddle2 { get; protected set; }
public int Paddle3 { get; protected set; }
- public Joystick Joystick0 { get; protected set; }
- public Joystick Joystick1 { get; protected set; }
+ public bool IsJoystick0Up { get; protected set; }
+ public bool IsJoystick0Left { get; protected set; }
+ public bool IsJoystick0Right { get; protected set; }
+ public bool IsJoystick0Down { get; protected set; }
+
+ public bool IsJoystick1Up { get; protected set; }
+ public bool IsJoystick1Left { get; protected set; }
+ public bool IsJoystick1Right { get; protected set; }
+ public bool IsJoystick1Down { get; protected set; }
public bool IsButton0Down { get; protected set; }
public bool IsButton1Down { get; protected set; }
diff --git a/Virtu/Services/IsolatedStorageService.cs b/Virtu/Services/IsolatedStorageService.cs
index c5acf62..f806261 100644
--- a/Virtu/Services/IsolatedStorageService.cs
+++ b/Virtu/Services/IsolatedStorageService.cs
@@ -12,7 +12,7 @@ public IsolatedStorageService(Machine machine) :
{
}
- public override void Load(string path, Action reader)
+ public override void Load(string fileName, Action reader)
{
if (reader == null)
{
@@ -23,7 +23,7 @@ public override void Load(string path, Action reader)
{
using (var store = GetStore())
{
- using (var stream = new IsolatedStorageFileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, store))
+ using (var stream = store.OpenFile(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
reader(stream);
}
@@ -37,7 +37,7 @@ public override void Load(string path, Action reader)
}
}
- public override void Save(string path, Action writer)
+ public override void Save(string fileName, Action writer)
{
if (writer == null)
{
@@ -48,7 +48,7 @@ public override void Save(string path, Action writer)
{
using (var store = GetStore())
{
- using (var stream = new IsolatedStorageFileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, store))
+ using (var stream = store.OpenFile(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
writer(stream);
}
diff --git a/Virtu/Services/MachineServices.cs b/Virtu/Services/MachineServices.cs
index 6c97f74..b8669ee 100644
--- a/Virtu/Services/MachineServices.cs
+++ b/Virtu/Services/MachineServices.cs
@@ -16,7 +16,7 @@ public void AddService(Type serviceType, MachineService serviceProvider)
}
if (_serviceProviders.ContainsKey(serviceType))
{
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Strings.ServiceAlreadyPresent, serviceType.FullName), "serviceType");
+ throw new ArgumentException(string.Format(CultureInfo.CurrentUICulture, Strings.ServiceAlreadyPresent, serviceType.FullName), "serviceType");
}
if (serviceProvider == null)
{
@@ -24,7 +24,7 @@ public void AddService(Type serviceType, MachineService serviceProvider)
}
if (!serviceType.IsAssignableFrom(serviceProvider.GetType()))
{
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Strings.ServiceMustBeAssignable, serviceType.FullName, serviceProvider.GetType().FullName));
+ throw new ArgumentException(string.Format(CultureInfo.CurrentUICulture, Strings.ServiceMustBeAssignable, serviceType.FullName, serviceProvider.GetType().FullName));
}
_serviceProviders.Add(serviceType, serviceProvider);
diff --git a/Virtu/Services/StorageService.cs b/Virtu/Services/StorageService.cs
index ca2a2a5..95e4976 100644
--- a/Virtu/Services/StorageService.cs
+++ b/Virtu/Services/StorageService.cs
@@ -1,9 +1,9 @@
using System;
-using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
-using System.Reflection;
using System.Resources;
+using System.Security;
+using Jellyfish.Library;
using Jellyfish.Virtu.Properties;
namespace Jellyfish.Virtu.Services
@@ -15,24 +15,128 @@ protected StorageService(Machine machine) :
{
}
- [SuppressMessage("Microsoft.Design", "CA1026:DefaultParametersShouldNotBeUsed")]
- public static Stream GetResourceStream(string resourceName, int resourceSize = 0)
+ public abstract void Load(string fileName, Action reader);
+
+#if !WINDOWS
+ [SecuritySafeCritical]
+#endif
+ public static void LoadFile(string fileName, Action reader)
{
- var resourceManager = new ResourceManager("Jellyfish.Virtu.g", Assembly.GetExecutingAssembly()) { IgnoreCase = true };
- var resourceStream = (Stream)resourceManager.GetObject(resourceName);
+ if (reader == null)
+ {
+ throw new ArgumentNullException("reader");
+ }
+
+ try
+ {
+ using (var stream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
+ {
+ reader(stream);
+ }
+ }
+ catch (FileNotFoundException)
+ {
+ }
+ }
+
+#if !WINDOWS
+ [SecuritySafeCritical]
+#endif
+ public static void LoadFile(FileInfo fileInfo, Action reader)
+ {
+ if (fileInfo == null)
+ {
+ throw new ArgumentNullException("fileInfo");
+ }
+ if (reader == null)
+ {
+ throw new ArgumentNullException("reader");
+ }
+
+ try
+ {
+ using (var stream = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.Read))
+ {
+ reader(stream);
+ }
+ }
+ catch (SecurityException)
+ {
+ }
+ }
+
+ public static void LoadResource(string resourceName, int resourceSize, Action reader)
+ {
+ if (reader == null)
+ {
+ throw new ArgumentNullException("reader");
+ }
+
+ try
+ {
+ using (var stream = GetResourceStream(resourceName, resourceSize))
+ {
+ reader(stream);
+ }
+ }
+ catch (FileNotFoundException)
+ {
+ }
+ }
+
+ public abstract void Save(string fileName, Action writer);
+
+#if !WINDOWS
+ [SecuritySafeCritical]
+#endif
+ public static void SaveFile(string fileName, Action writer)
+ {
+ if (writer == null)
+ {
+ throw new ArgumentNullException("writer");
+ }
+
+ using (var stream = File.Open(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
+ {
+ writer(stream);
+ }
+ }
+
+#if !WINDOWS
+ [SecuritySafeCritical]
+#endif
+ public static void SaveFile(FileInfo fileInfo, Action writer)
+ {
+ if (fileInfo == null)
+ {
+ throw new ArgumentNullException("fileInfo");
+ }
+ if (writer == null)
+ {
+ throw new ArgumentNullException("writer");
+ }
+
+ using (var stream = fileInfo.Open(FileMode.Create, FileAccess.Write, FileShare.None))
+ {
+ writer(stream);
+ }
+ }
+
+ private static Stream GetResourceStream(string resourceName, int resourceSize)
+ {
+ var resourceStream = _resourceManager.Value.GetStream(resourceName, CultureInfo.CurrentUICulture);
if (resourceStream == null)
{
- throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings.ResourceNotFound, resourceName));
+ throw new FileNotFoundException(string.Format(CultureInfo.CurrentUICulture, Strings.ResourceNotFound, resourceName));
}
if ((resourceSize > 0) && (resourceStream.Length != resourceSize))
{
- throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings.ResourceInvalid, resourceName));
+ throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, Strings.ResourceInvalid, resourceName));
}
return resourceStream;
}
- public abstract void Load(string path, Action reader);
- public abstract void Save(string path, Action writer);
+ private static Lazy _resourceManager = new Lazy(() => new ResourceManager("Jellyfish.Virtu.g", typeof(StorageService).Assembly) { IgnoreCase = true });
}
}
diff --git a/Virtu/Services/VideoService.cs b/Virtu/Services/VideoService.cs
index e56968c..3ab1498 100644
--- a/Virtu/Services/VideoService.cs
+++ b/Virtu/Services/VideoService.cs
@@ -7,14 +7,8 @@ protected VideoService(Machine machine) :
{
}
+ public abstract void SetFullScreen(bool isFullScreen);
public abstract void SetPixel(int x, int y, uint color);
public abstract void Update(); // main thread
-
- public void ToggleFullScreen()
- {
- IsFullScreen ^= true;
- }
-
- public bool IsFullScreen { get; private set; }
}
}
diff --git a/Virtu/Silverlight/Jellyfish.Virtu.Silverlight.csproj b/Virtu/Silverlight/Jellyfish.Virtu.Silverlight.csproj
index 5a94459..65d8f45 100644
--- a/Virtu/Silverlight/Jellyfish.Virtu.Silverlight.csproj
+++ b/Virtu/Silverlight/Jellyfish.Virtu.Silverlight.csproj
@@ -92,9 +92,6 @@
-
- True
-
@@ -155,9 +152,6 @@
Core\MachineEvents.cs
-
- Core\MachineSettings.cs
-
Core\Memory.cs
diff --git a/Virtu/Silverlight/MainPage.xaml.cs b/Virtu/Silverlight/MainPage.xaml.cs
index 6f1b65c..1757cd6 100644
--- a/Virtu/Silverlight/MainPage.xaml.cs
+++ b/Virtu/Silverlight/MainPage.xaml.cs
@@ -66,20 +66,16 @@ private void OnCompositionTargetRendering(object sender, EventArgs e)
private void OnDiskButtonClick(int drive)
{
var dialog = new OpenFileDialog() { Filter = "Disk Files (*.dsk;*.nib)|*.dsk;*.nib|All Files (*.*)|*.*" };
-
bool? result = dialog.ShowDialog();
if (result.HasValue && result.Value)
{
- using (var stream = dialog.File.OpenRead())
+ _machine.Pause();
+ var diskII = _machine.FindDiskIIController();
+ if (diskII != null)
{
- _machine.Pause();
- var diskII = _machine.FindDiskIIController();
- if (diskII != null)
- {
- diskII.Drives[drive].InsertDisk(dialog.File.Name, stream, false);
- }
- _machine.Unpause();
+ StorageService.LoadFile(dialog.File, stream => diskII.Drives[drive].InsertDisk(dialog.File.Name, stream, false));
}
+ _machine.Unpause();
}
}
diff --git a/Virtu/Silverlight/Phone/Jellyfish.Virtu.Silverlight.Phone.csproj b/Virtu/Silverlight/Phone/Jellyfish.Virtu.Silverlight.Phone.csproj
index cfbc095..bfbc8ba 100644
--- a/Virtu/Silverlight/Phone/Jellyfish.Virtu.Silverlight.Phone.csproj
+++ b/Virtu/Silverlight/Phone/Jellyfish.Virtu.Silverlight.Phone.csproj
@@ -79,7 +79,6 @@
-
@@ -140,9 +139,6 @@
Core\MachineEvents.cs
-
- Core\MachineSettings.cs
-
Core\Memory.cs
diff --git a/Virtu/Silverlight/Phone/MainPage.xaml.cs b/Virtu/Silverlight/Phone/MainPage.xaml.cs
index 742a37d..4df1174 100644
--- a/Virtu/Silverlight/Phone/MainPage.xaml.cs
+++ b/Virtu/Silverlight/Phone/MainPage.xaml.cs
@@ -66,16 +66,16 @@ private void OnCompositionTargetRendering(object sender, EventArgs e)
//private void OnDiskButtonClick(int drive) // TODO
//{
// var dialog = new OpenFileDialog() { Filter = "Disk Files (*.dsk;*.nib)|*.dsk;*.nib|All Files (*.*)|*.*" };
-
// bool? result = dialog.ShowDialog();
// if (result.HasValue && result.Value)
// {
- // using (var stream = dialog.File.OpenRead())
+ // _machine.Pause();
+ // var diskII = _machine.FindDiskIIController();
+ // if (diskII != null)
// {
- // _machine.Pause();
- // _machine.DiskII.Drives[drive].InsertDisk(dialog.File.Name, stream, false);
- // _machine.Unpause();
+ // StorageService.LoadFile(dialog.File, stream => diskII.Drives[drive].InsertDisk(dialog.File.Name, stream, false));
// }
+ // _machine.Unpause();
// }
//}
diff --git a/Virtu/Silverlight/Phone/Properties/AssemblyInfo.cs b/Virtu/Silverlight/Phone/Properties/AssemblyInfo.cs
index 0f15503..1463887 100644
--- a/Virtu/Silverlight/Phone/Properties/AssemblyInfo.cs
+++ b/Virtu/Silverlight/Phone/Properties/AssemblyInfo.cs
@@ -3,6 +3,7 @@
using System.Resources;
using System.Runtime.InteropServices;
using Jellyfish.Library;
+using Jellyfish.Virtu;
[assembly: AssemblyTitle("Virtu")]
[assembly: AssemblyDescription("Apple IIe Emulator")]
@@ -11,9 +12,9 @@
[assembly: AssemblyCopyright("Copyright © 1995-2010 Digital Jellyfish Design Ltd")]
[assembly: AssemblyComment("Developed by Sean Fausett & Nick Westgate")]
-[assembly: AssemblyVersion("0.8.3.0")]
-[assembly: AssemblyFileVersion("0.8.3.0")]
-[assembly: AssemblyInformationalVersion("0.8.3.0")]
+[assembly: AssemblyVersion(Machine.Version)]
+[assembly: AssemblyFileVersion(Machine.Version)]
+[assembly: AssemblyInformationalVersion(Machine.Version)]
[assembly: CLSCompliant(false)]
[assembly: ComVisible(false)]
diff --git a/Virtu/Silverlight/Properties/AssemblyInfo.cs b/Virtu/Silverlight/Properties/AssemblyInfo.cs
index 43c2de1..a0bd1f1 100644
--- a/Virtu/Silverlight/Properties/AssemblyInfo.cs
+++ b/Virtu/Silverlight/Properties/AssemblyInfo.cs
@@ -3,6 +3,7 @@
using System.Resources;
using System.Runtime.InteropServices;
using Jellyfish.Library;
+using Jellyfish.Virtu;
[assembly: AssemblyTitle("Virtu")]
[assembly: AssemblyDescription("Apple IIe Emulator")]
@@ -11,9 +12,9 @@
[assembly: AssemblyCopyright("Copyright © 1995-2010 Digital Jellyfish Design Ltd")]
[assembly: AssemblyComment("Developed by Sean Fausett & Nick Westgate")]
-[assembly: AssemblyVersion("0.8.3.0")]
-[assembly: AssemblyFileVersion("0.8.3.0")]
-[assembly: AssemblyInformationalVersion("0.8.3.0")]
+[assembly: AssemblyVersion(Machine.Version)]
+[assembly: AssemblyFileVersion(Machine.Version)]
+[assembly: AssemblyInformationalVersion(Machine.Version)]
[assembly: CLSCompliant(false)]
[assembly: ComVisible(false)]
diff --git a/Virtu/Silverlight/Services/SilverlightAudioService.cs b/Virtu/Silverlight/Services/SilverlightAudioService.cs
index 57d0e6d..802aed2 100644
--- a/Virtu/Silverlight/Services/SilverlightAudioService.cs
+++ b/Virtu/Silverlight/Services/SilverlightAudioService.cs
@@ -28,9 +28,9 @@ public SilverlightAudioService(Machine machine, UserControl page, MediaElement m
#endif
}
- public override void SetVolume(double volume) // machine thread
+ public override void SetVolume(double volume)
{
- _media.Dispatcher.BeginInvoke(() => _media.Volume = volume);
+ _media.Dispatcher.Send(() => _media.Volume = volume);
}
protected override void Dispose(bool disposing)
@@ -50,7 +50,8 @@ private void OnMediaSourceUpdate(byte[] buffer, int bufferSize) // audio thread
// DebugService.WriteLine("OnMediaSourceUpdate");
//}
- Update(bufferSize, (source, count) => Buffer.BlockCopy(source, 0, buffer, 0, count));
+ Buffer.BlockCopy(Source, 0, buffer, 0, bufferSize);
+ Update();
}
private MediaElement _media;
diff --git a/Virtu/Silverlight/Services/SilverlightDebugService.cs b/Virtu/Silverlight/Services/SilverlightDebugService.cs
index 1c355fc..bdf938e 100644
--- a/Virtu/Silverlight/Services/SilverlightDebugService.cs
+++ b/Virtu/Silverlight/Services/SilverlightDebugService.cs
@@ -18,7 +18,7 @@ public SilverlightDebugService(Machine machine, MainPage page) :
protected override void OnWriteLine(string message)
{
- _page.Dispatcher.CheckBeginInvoke(() => _page.WriteLine(message + Environment.NewLine));
+ _page.Dispatcher.Post(() => _page.WriteLine(message + Environment.NewLine));
}
private MainPage _page;
diff --git a/Virtu/Silverlight/Services/SilverlightKeyboardService.cs b/Virtu/Silverlight/Services/SilverlightKeyboardService.cs
index 7c90c52..b56f730 100644
--- a/Virtu/Silverlight/Services/SilverlightKeyboardService.cs
+++ b/Virtu/Silverlight/Services/SilverlightKeyboardService.cs
@@ -93,17 +93,18 @@ private void OnPageKeyUp(object sender, KeyEventArgs e)
}
else if (control && (e.Key == Key.Divide))
{
- Machine.Cpu.ToggleThrottle();
+ Machine.Cpu.IsThrottled ^= true;
}
else if (control && (e.Key == Key.Multiply))
{
- Machine.Video.ToggleMonochrome();
+ Machine.Video.IsMonochrome ^= true;
}
+#if !WINDOWS_PHONE
else if (control && (e.Key == Key.Subtract))
{
- Machine.Video.ToggleFullScreen();
+ Machine.Video.IsFullScreen ^= true;
}
-
+#endif
Update();
}
diff --git a/Virtu/Silverlight/Services/SilverlightVideoService.cs b/Virtu/Silverlight/Services/SilverlightVideoService.cs
index dda8d97..36d4613 100644
--- a/Virtu/Silverlight/Services/SilverlightVideoService.cs
+++ b/Virtu/Silverlight/Services/SilverlightVideoService.cs
@@ -3,6 +3,7 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
+using Jellyfish.Library;
#if WINDOWS_PHONE
using Microsoft.Phone.Controls;
#endif
@@ -35,6 +36,24 @@ public SilverlightVideoService(Machine machine, UserControl page, Image image) :
_page.SizeChanged += (sender, e) => SetImageSize();
}
+ public override void SetFullScreen(bool isFullScreen)
+ {
+#if !WINDOWS_PHONE
+ _page.Dispatcher.Send(() =>
+ {
+ var application = Application.Current;
+ if (application.IsRunningOutOfBrowser)
+ {
+ var content = application.Host.Content;
+ if (content.IsFullScreen != isFullScreen)
+ {
+ content.IsFullScreen = isFullScreen;
+ }
+ }
+ });
+#endif
+ }
+
[SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow")]
public override void SetPixel(int x, int y, uint color)
{
@@ -44,13 +63,6 @@ public override void SetPixel(int x, int y, uint color)
public override void Update() // main thread
{
-#if !WINDOWS_PHONE
- var content = Application.Current.Host.Content;
- if (Application.Current.IsRunningOutOfBrowser && (content.IsFullScreen != IsFullScreen))
- {
- Application.Current.RootVisual.Dispatcher.BeginInvoke(() => content.IsFullScreen = IsFullScreen); // queue to dispatcher; avoids crash!
- }
-#endif
if (_pixelsDirty)
{
_pixelsDirty = false;
@@ -68,17 +80,17 @@ private void SetImageSize(bool swapOrientation = false)
Math.Min((int)_page.RenderSize.Width / BitmapWidth, (int)_page.RenderSize.Height / BitmapHeight));
_image.Width = uniformScale * BitmapWidth;
_image.Height = uniformScale * BitmapHeight;
- Machine.Video.DirtyScreen();
}
#if !WINDOWS_PHONE
private void SetWindowSizeToContent()
{
- if (Application.Current.IsRunningOutOfBrowser && !_sizedToContent)
+ var application = Application.Current;
+ if (application.IsRunningOutOfBrowser && !_sizedToContent)
{
_sizedToContent = true;
- var window = Application.Current.MainWindow;
- var size = Application.Current.RootVisual.DesiredSize;
+ var window = application.MainWindow;
+ var size = application.RootVisual.DesiredSize;
window.Width = size.Width;
window.Height = size.Height;
}
diff --git a/Virtu/Speaker.cs b/Virtu/Speaker.cs
index 6f98d70..7a55033 100644
--- a/Virtu/Speaker.cs
+++ b/Virtu/Speaker.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using Jellyfish.Virtu.Services;
namespace Jellyfish.Virtu
@@ -15,10 +16,12 @@ public override void Initialize()
{
_audioService = Machine.Services.GetService();
- UpdateSettings();
- Machine.Video.VSync += (sender, e) => UpdateSettings();
-
- Machine.Events.AddEvent(CyclesPerFlush * Machine.Settings.Cpu.Multiplier, _flushOutputEvent);
+#if WINDOWS_PHONE
+ Volume = 0.85;
+#else
+ Volume = 0.5;
+#endif
+ Machine.Events.AddEvent(CyclesPerFlush * Machine.Cpu.Multiplier, _flushOutputEvent);
}
public override void Reset()
@@ -28,6 +31,26 @@ public override void Reset()
_highCycles = _totalCycles = 0;
}
+ public override void LoadState(BinaryReader reader, Version version)
+ {
+ if (reader == null)
+ {
+ throw new ArgumentNullException("reader");
+ }
+
+ Volume = reader.ReadDouble();
+ }
+
+ public override void SaveState(BinaryWriter writer)
+ {
+ if (writer == null)
+ {
+ throw new ArgumentNullException("writer");
+ }
+
+ writer.Write(Volume);
+ }
+
public void ToggleOutput()
{
UpdateCycles();
@@ -40,7 +63,7 @@ private void FlushOutputEvent()
_audioService.Output(_highCycles * short.MaxValue / _totalCycles); // quick and dirty decimation
_highCycles = _totalCycles = 0;
- Machine.Events.AddEvent(CyclesPerFlush * Machine.Settings.Cpu.Multiplier, _flushOutputEvent);
+ Machine.Events.AddEvent(CyclesPerFlush * Machine.Cpu.Multiplier, _flushOutputEvent);
}
private void UpdateCycles()
@@ -54,20 +77,18 @@ private void UpdateCycles()
_lastCycles = Machine.Cpu.Cycles;
}
- private void UpdateSettings()
- {
- _audioService.SetVolume(Machine.Settings.Audio.Volume);
- }
+ public double Volume { get { return _volume; } set { _volume = value; _audioService.SetVolume(_volume); } }
private const int CyclesPerFlush = 23;
private Action _flushOutputEvent;
+ private AudioService _audioService;
+
private bool _isHigh;
private int _highCycles;
private int _totalCycles;
private long _lastCycles;
-
- private AudioService _audioService;
+ private double _volume;
}
}
diff --git a/Virtu/Video.cs b/Virtu/Video.cs
index e52a4c1..f1dbd64 100644
--- a/Virtu/Video.cs
+++ b/Virtu/Video.cs
@@ -1,9 +1,12 @@
using System;
+using System.IO;
using Jellyfish.Virtu.Services;
-using Jellyfish.Virtu.Settings;
namespace Jellyfish.Virtu
{
+ [Flags]
+ public enum ScannerOptions { None = 0x0, AppleII = 0x1, Pal = 0x2 } // defaults to AppleIIe, Ntsc
+
public sealed partial class Video : MachineComponent
{
public Video(Machine machine) :
@@ -26,7 +29,29 @@ public override void Initialize()
_memory = Machine.Memory;
_videoService = Machine.Services.GetService();
- UpdateSettings();
+ _colorBlack = 0xFF000000; // BGRA
+ _colorDarkBlue = 0xFF000099;
+ _colorDarkGreen = 0xFF117722;
+ _colorMediumBlue = 0xFF0000FF;
+ _colorBrown = 0xFF885500;
+ _colorLightGrey = 0xFF99AAAA;
+ _colorGreen = 0xFF00EE11;
+ _colorAquamarine = 0xFF55FFAA;
+ _colorDeepRed = 0xFFFF1111;
+ _colorPurple = 0xFFDD00DD;
+ _colorDarkGrey = 0xFF445555;
+ _colorLightBlue = 0xFF33AAFF;
+ _colorOrange = 0xFFFF4411;
+ _colorPink = 0xFFFF9988;
+ _colorYellow = 0xFFFFFF11;
+ _colorWhite = 0xFFFFFFFF;
+ _colorMonochrome = 0xFF00AA00;
+ SetPalette();
+
+ IsFullScreen = false;
+ IsMonochrome = false;
+ ScannerOptions = ScannerOptions.None;
+
IsVBlank = true;
Machine.Events.AddEvent(_cyclesPerVBlankPreset, _leaveVBlankEvent); // align flush events with scanner; assumes vcount preset at start of frame [3-15, 3-16]
@@ -41,6 +66,71 @@ public override void Reset()
FlushScreen();
}
+ public override void LoadState(BinaryReader reader, Version version)
+ {
+ if (reader == null)
+ {
+ throw new ArgumentNullException("reader");
+ }
+
+ _colorBlack = reader.ReadUInt32();
+ _colorDarkBlue = reader.ReadUInt32();
+ _colorDarkGreen = reader.ReadUInt32();
+ _colorMediumBlue = reader.ReadUInt32();
+ _colorBrown = reader.ReadUInt32();
+ _colorLightGrey = reader.ReadUInt32();
+ _colorGreen = reader.ReadUInt32();
+ _colorAquamarine = reader.ReadUInt32();
+ _colorDeepRed = reader.ReadUInt32();
+ _colorPurple = reader.ReadUInt32();
+ _colorDarkGrey = reader.ReadUInt32();
+ _colorLightBlue = reader.ReadUInt32();
+ _colorOrange = reader.ReadUInt32();
+ _colorPink = reader.ReadUInt32();
+ _colorYellow = reader.ReadUInt32();
+ _colorWhite = reader.ReadUInt32();
+ _colorMonochrome = reader.ReadUInt32();
+ SetPalette();
+
+ IsFullScreen = reader.ReadBoolean();
+ IsMonochrome = reader.ReadBoolean();
+ ScannerOptions = (ScannerOptions)reader.ReadInt32();
+
+ SetCharSet();
+ DirtyScreen();
+ FlushScreen();
+ }
+
+ public override void SaveState(BinaryWriter writer)
+ {
+ if (writer == null)
+ {
+ throw new ArgumentNullException("writer");
+ }
+
+ writer.Write(_colorBlack);
+ writer.Write(_colorDarkBlue);
+ writer.Write(_colorDarkGreen);
+ writer.Write(_colorMediumBlue);
+ writer.Write(_colorBrown);
+ writer.Write(_colorLightGrey);
+ writer.Write(_colorGreen);
+ writer.Write(_colorAquamarine);
+ writer.Write(_colorDeepRed);
+ writer.Write(_colorPurple);
+ writer.Write(_colorDarkGrey);
+ writer.Write(_colorLightBlue);
+ writer.Write(_colorOrange);
+ writer.Write(_colorPink);
+ writer.Write(_colorYellow);
+ writer.Write(_colorWhite);
+ writer.Write(_colorMonochrome);
+
+ writer.Write(IsFullScreen);
+ writer.Write(IsMonochrome);
+ writer.Write((int)ScannerOptions);
+ }
+
public void DirtyCell(int addressOffset)
{
_isCellDirty[CellIndex[addressOffset]] = true;
@@ -123,25 +213,10 @@ public void SetCharSet()
DirtyScreenText();
}
- public void ToggleFullScreen()
- {
- Machine.Settings.Video.IsFullScreen ^= true;
- _videoService.ToggleFullScreen();
- DirtyScreen();
- FlushScreen();
- }
-
- public void ToggleMonochrome()
- {
- Machine.Settings.Video.IsMonochrome ^= true;
- DirtyScreen();
- FlushScreen();
- }
-
#region Draw Methods
private void DrawText40(int data, int x, int y)
{
- int color = Machine.Settings.Video.IsMonochrome ? ColorMono00 : ColorWhite00;
+ int color = IsMonochrome ? ColorMono00 : ColorWhite00;
int index = _charSet[data] * CharBitmapBytes;
int inverseMask = (_isTextInversed && !_memory.IsCharSetAlternate && (0x40 <= data) && (data <= 0x7F)) ? 0x7F : 0x00;
for (int i = 0; i < TextHeight; i++, y++)
@@ -166,7 +241,7 @@ private void DrawText40(int data, int x, int y)
private void DrawText80(int data, int x, int y)
{
- int color = Machine.Settings.Video.IsMonochrome ? ColorMono00 : ColorWhite00;
+ int color = IsMonochrome ? ColorMono00 : ColorWhite00;
int index = _charSet[data] * CharBitmapBytes;
int mask = (_isTextInversed && !_memory.IsCharSetAlternate && (0x40 <= data) && (data <= 0x7F)) ? 0x7F : 0x00;
for (int i = 0; i < TextHeight; i++, y++)
@@ -184,7 +259,7 @@ private void DrawText80(int data, int x, int y)
private void DrawLores(int data, int x, int y)
{
- if (Machine.Settings.Video.IsMonochrome)
+ if (IsMonochrome)
{
if ((x & 0x02) == 0x02) // odd cell
{
@@ -268,7 +343,7 @@ private void DrawLores(int data, int x, int y)
private void Draw7MLores(int data, int x, int y)
{
- if (Machine.Settings.Video.IsMonochrome)
+ if (IsMonochrome)
{
if ((x & 0x02) == 0x02) // odd cell
{
@@ -352,7 +427,7 @@ private void Draw7MLores(int data, int x, int y)
private void DrawDLores(int data, int x, int y)
{
- if (Machine.Settings.Video.IsMonochrome)
+ if (IsMonochrome)
{
if ((x & 0x01) == 0x00) // even half cell
{
@@ -408,7 +483,7 @@ private void DrawDLores(int data, int x, int y)
private void DrawHires(int address, int x, int y)
{
- if (Machine.Settings.Video.IsMonochrome)
+ if (IsMonochrome)
{
int data = _memory.ReadRamMainRegion02BF(address);
SetPixel(x + 0, y, data & 0x01);
@@ -466,7 +541,7 @@ private void DrawHires(int address, int x, int y)
private void DrawNDHires(int address, int x, int y)
{
- if (Machine.Settings.Video.IsMonochrome)
+ if (IsMonochrome)
{
int data = _memory.ReadRamMainRegion02BF(address);
SetPixel(x + 0, y, data & 0x01);
@@ -524,7 +599,7 @@ private void DrawNDHires(int address, int x, int y)
private void DrawDHiresA(int address, int x, int y)
{
- if (Machine.Settings.Video.IsMonochrome)
+ if (IsMonochrome)
{
if ((x & 0x2) == 0x00) // even cell
{
@@ -592,7 +667,7 @@ private void DrawDHiresA(int address, int x, int y)
private void DrawDHiresM(int address, int x, int y)
{
- if (Machine.Settings.Video.IsMonochrome)
+ if (IsMonochrome)
{
if ((x & 0x2) == 0x02) // odd cell
{
@@ -919,64 +994,58 @@ private void LeaveVBlankEvent()
private void ResetVSyncEvent()
{
- UpdateSettings();
-
- var handler = VSync;
- if (handler != null)
- {
- handler(this, EventArgs.Empty);
- }
-
Machine.Events.AddEvent(_cyclesPerVSync, _resetVSyncEvent);
}
+ private void SetPalette()
+ {
+ _colorPalette[ColorMono00] = _colorBlack;
+ _colorPalette[ColorMono01] = _colorMonochrome;
+ _colorPalette[ColorMono02] = _colorMonochrome;
+ _colorPalette[ColorMono04] = _colorMonochrome;
+ _colorPalette[ColorMono08] = _colorMonochrome;
+ _colorPalette[ColorMono10] = _colorMonochrome;
+ _colorPalette[ColorMono20] = _colorMonochrome;
+ _colorPalette[ColorMono40] = _colorMonochrome;
+ _colorPalette[ColorMono80] = _colorMonochrome;
+
+ _colorPalette[ColorWhite00] = _colorBlack;
+ _colorPalette[ColorWhite01] = _colorWhite;
+ _colorPalette[ColorWhite02] = _colorWhite;
+ _colorPalette[ColorWhite04] = _colorWhite;
+ _colorPalette[ColorWhite08] = _colorWhite;
+ _colorPalette[ColorWhite10] = _colorWhite;
+ _colorPalette[ColorWhite20] = _colorWhite;
+ _colorPalette[ColorWhite40] = _colorWhite;
+ _colorPalette[ColorWhite80] = _colorWhite;
+
+ _colorPalette[ColorDHires0] = _colorBlack;
+ _colorPalette[ColorDHires1] = _colorDarkBlue;
+ _colorPalette[ColorDHires2] = _colorDarkGreen;
+ _colorPalette[ColorDHires3] = _colorMediumBlue;
+ _colorPalette[ColorDHires4] = _colorBrown;
+ _colorPalette[ColorDHires5] = _colorLightGrey;
+ _colorPalette[ColorDHires6] = _colorGreen;
+ _colorPalette[ColorDHires7] = _colorAquamarine;
+ _colorPalette[ColorDHires8] = _colorDeepRed;
+ _colorPalette[ColorDHires9] = _colorPurple;
+ _colorPalette[ColorDHiresA] = _colorDarkGrey;
+ _colorPalette[ColorDHiresB] = _colorLightBlue;
+ _colorPalette[ColorDHiresC] = _colorOrange;
+ _colorPalette[ColorDHiresD] = _colorPink;
+ _colorPalette[ColorDHiresE] = _colorYellow;
+ _colorPalette[ColorDHiresF] = _colorWhite;
+
+ DirtyScreen();
+ }
+
private void SetPixel(int x, int y, int color)
{
_videoService.SetPixel(x, 2 * y, _colorPalette[color]);
}
- private void UpdateSettings()
+ private void SetScanner()
{
- var settings = Machine.Settings.Video;
-
- _colorPalette[ColorMono00] = settings.Color.Black;
- _colorPalette[ColorMono01] = settings.Color.Monochrome;
- _colorPalette[ColorMono02] = settings.Color.Monochrome;
- _colorPalette[ColorMono04] = settings.Color.Monochrome;
- _colorPalette[ColorMono08] = settings.Color.Monochrome;
- _colorPalette[ColorMono10] = settings.Color.Monochrome;
- _colorPalette[ColorMono20] = settings.Color.Monochrome;
- _colorPalette[ColorMono40] = settings.Color.Monochrome;
- _colorPalette[ColorMono80] = settings.Color.Monochrome;
-
- _colorPalette[ColorWhite00] = settings.Color.Black;
- _colorPalette[ColorWhite01] = settings.Color.White;
- _colorPalette[ColorWhite02] = settings.Color.White;
- _colorPalette[ColorWhite04] = settings.Color.White;
- _colorPalette[ColorWhite08] = settings.Color.White;
- _colorPalette[ColorWhite10] = settings.Color.White;
- _colorPalette[ColorWhite20] = settings.Color.White;
- _colorPalette[ColorWhite40] = settings.Color.White;
- _colorPalette[ColorWhite80] = settings.Color.White;
-
- _colorPalette[ColorDHires0] = settings.Color.Black;
- _colorPalette[ColorDHires1] = settings.Color.DarkBlue;
- _colorPalette[ColorDHires2] = settings.Color.DarkGreen;
- _colorPalette[ColorDHires3] = settings.Color.MediumBlue;
- _colorPalette[ColorDHires4] = settings.Color.Brown;
- _colorPalette[ColorDHires5] = settings.Color.LightGrey;
- _colorPalette[ColorDHires6] = settings.Color.Green;
- _colorPalette[ColorDHires7] = settings.Color.Aquamarine;
- _colorPalette[ColorDHires8] = settings.Color.DeepRed;
- _colorPalette[ColorDHires9] = settings.Color.Purple;
- _colorPalette[ColorDHiresA] = settings.Color.DarkGrey;
- _colorPalette[ColorDHiresB] = settings.Color.LightBlue;
- _colorPalette[ColorDHiresC] = settings.Color.Orange;
- _colorPalette[ColorDHiresD] = settings.Color.Pink;
- _colorPalette[ColorDHiresE] = settings.Color.Yellow;
- _colorPalette[ColorDHiresF] = settings.Color.White;
-
- _scannerOptions = settings.ScannerOptions;
if ((_scannerOptions & ScannerOptions.Pal) != 0)
{
_vCountPreset = VCountPresetPal;
@@ -992,17 +1061,31 @@ private void UpdateSettings()
_cyclesPerVBlankPreset = (_vLineLeaveVBlank - VLineTriggerPreset) * CyclesPerHSync; // cycles during vblank after vcount preset [3-15, 3-16]
_cyclesPerVSync = _vLineLeaveVBlank * CyclesPerHSync;
_cyclesPerFlash = VSyncsPerFlash * _cyclesPerVSync;
-
- if (_videoService.IsFullScreen != settings.IsFullScreen)
- {
- _videoService.ToggleFullScreen();
- }
}
- public bool IsVBlank { get; private set; }
- public long TicksPerVSync { get { return TimeSpan.FromSeconds((double)_cyclesPerVSync / CyclesPerSecond).Ticks; } }
+ public uint ColorBlack { get { return _colorBlack; } set { _colorBlack = value; SetPalette(); } }
+ public uint ColorDarkBlue { get { return _colorDarkBlue; } set { _colorDarkBlue = value; SetPalette(); } }
+ public uint ColorDarkGreen { get { return _colorDarkGreen; } set { _colorDarkGreen = value; SetPalette(); } }
+ public uint ColorMediumBlue { get { return _colorMediumBlue; } set { _colorMediumBlue = value; SetPalette(); } }
+ public uint ColorBrown { get { return _colorBrown; } set { _colorBrown = value; SetPalette(); } }
+ public uint ColorLightGrey { get { return _colorLightGrey; } set { _colorLightGrey = value; SetPalette(); } }
+ public uint ColorGreen { get { return _colorGreen; } set { _colorGreen = value; SetPalette(); } }
+ public uint ColorAquamarine { get { return _colorAquamarine; } set { _colorAquamarine = value; SetPalette(); } }
+ public uint ColorDeepRed { get { return _colorDeepRed; } set { _colorDeepRed = value; SetPalette(); } }
+ public uint ColorPurple { get { return _colorPurple; } set { _colorPurple = value; SetPalette(); } }
+ public uint ColorDarkGrey { get { return _colorDarkGrey; } set { _colorDarkGrey = value; SetPalette(); } }
+ public uint ColorLightBlue { get { return _colorLightBlue; } set { _colorLightBlue = value; SetPalette(); } }
+ public uint ColorOrange { get { return _colorOrange; } set { _colorOrange = value; SetPalette(); } }
+ public uint ColorPink { get { return _colorPink; } set { _colorPink = value; SetPalette(); } }
+ public uint ColorYellow { get { return _colorYellow; } set { _colorYellow = value; SetPalette(); } }
+ public uint ColorWhite { get { return _colorWhite; } set { _colorWhite = value; SetPalette(); } }
+ public uint ColorMonochrome { get { return _colorMonochrome; } set { _colorMonochrome = value; SetPalette(); } }
- public event EventHandler VSync;
+ public bool IsFullScreen { get { return _isFullScreen; } set { _isFullScreen = value; _videoService.SetFullScreen(_isFullScreen); } }
+ public bool IsMonochrome { get { return _isMonochrome; } set { _isMonochrome = value; DirtyScreen(); } }
+ public ScannerOptions ScannerOptions { get { return _scannerOptions; } set { _scannerOptions = value; SetScanner(); } }
+
+ public bool IsVBlank { get; private set; }
private Action _flushRowEvent;
private Action _inverseTextEvent;
@@ -1012,16 +1095,36 @@ private void UpdateSettings()
private Memory _memory;
private VideoService _videoService;
- private ushort[] _charSet;
- private uint[] _colorPalette = new uint[ColorPaletteCount];
- private bool[] _isCellDirty = new bool[Height * CellColumns + 1]; // includes sentinel
+ private uint _colorBlack;
+ private uint _colorDarkBlue;
+ private uint _colorDarkGreen;
+ private uint _colorMediumBlue;
+ private uint _colorBrown;
+ private uint _colorLightGrey;
+ private uint _colorGreen;
+ private uint _colorAquamarine;
+ private uint _colorDeepRed;
+ private uint _colorPurple;
+ private uint _colorDarkGrey;
+ private uint _colorLightBlue;
+ private uint _colorOrange;
+ private uint _colorPink;
+ private uint _colorYellow;
+ private uint _colorWhite;
+ private uint _colorMonochrome;
+ private bool _isFullScreen;
+ private bool _isMonochrome;
private bool _isTextInversed;
+ private ScannerOptions _scannerOptions;
private int _cyclesPerVBlank;
private int _cyclesPerVBlankPreset;
private int _cyclesPerVSync;
private int _cyclesPerFlash;
private int _vCountPreset;
private int _vLineLeaveVBlank;
- private ScannerOptions _scannerOptions;
+
+ private ushort[] _charSet;
+ private uint[] _colorPalette = new uint[ColorPaletteCount];
+ private bool[] _isCellDirty = new bool[Height * CellColumns + 1]; // includes sentinel
}
}
diff --git a/Virtu/Wpf/Jellyfish.Virtu.Wpf.csproj b/Virtu/Wpf/Jellyfish.Virtu.Wpf.csproj
index 6dbffec..ad9681f 100644
--- a/Virtu/Wpf/Jellyfish.Virtu.Wpf.csproj
+++ b/Virtu/Wpf/Jellyfish.Virtu.Wpf.csproj
@@ -74,7 +74,6 @@
4.0
-
@@ -145,9 +144,6 @@
Core\MachineEvents.cs
-
- Core\MachineSettings.cs
-
Core\Memory.cs
diff --git a/Virtu/Wpf/MainPage.xaml.cs b/Virtu/Wpf/MainPage.xaml.cs
index f874ad8..9a51b7c 100644
--- a/Virtu/Wpf/MainPage.xaml.cs
+++ b/Virtu/Wpf/MainPage.xaml.cs
@@ -68,29 +68,16 @@ private void OnCompositionTargetRendering(object sender, EventArgs e)
private void OnDiskButtonClick(int drive)
{
var dialog = new OpenFileDialog() { Filter = "Disk Files (*.dsk;*.nib)|*.dsk;*.nib|All Files (*.*)|*.*" };
-
bool? result = dialog.ShowDialog();
if (result.HasValue && result.Value)
{
- using (var stream = File.OpenRead(dialog.FileName))
+ _machine.Pause();
+ var diskII = _machine.FindDiskIIController();
+ if (diskII != null)
{
- _machine.Pause();
- var diskII = _machine.FindDiskIIController();
- if (diskII != null)
- {
- diskII.Drives[drive].InsertDisk(dialog.FileName, stream, false);
- var settings = _machine.Settings.DiskII;
- if (drive == 0)
- {
- settings.Disk1.Name = dialog.FileName;
- }
- else
- {
- settings.Disk2.Name = dialog.FileName;
- }
- }
- _machine.Unpause();
+ StorageService.LoadFile(dialog.FileName, stream => diskII.Drives[drive].InsertDisk(dialog.FileName, stream, false));
}
+ _machine.Unpause();
}
}
diff --git a/Virtu/Wpf/Properties/AssemblyInfo.cs b/Virtu/Wpf/Properties/AssemblyInfo.cs
index 02dd19e..d3d6287 100644
--- a/Virtu/Wpf/Properties/AssemblyInfo.cs
+++ b/Virtu/Wpf/Properties/AssemblyInfo.cs
@@ -4,6 +4,7 @@
using System.Runtime.InteropServices;
using System.Windows;
using Jellyfish.Library;
+using Jellyfish.Virtu;
[assembly: AssemblyTitle("Virtu")]
[assembly: AssemblyDescription("Apple IIe Emulator")]
@@ -12,9 +13,9 @@
[assembly: AssemblyCopyright("Copyright © 1995-2010 Digital Jellyfish Design Ltd")]
[assembly: AssemblyComment("Developed by Sean Fausett & Nick Westgate")]
-[assembly: AssemblyVersion("0.8.3.0")]
-[assembly: AssemblyFileVersion("0.8.3.0")]
-[assembly: AssemblyInformationalVersion("0.8.3.0")]
+[assembly: AssemblyVersion(Machine.Version)]
+[assembly: AssemblyFileVersion(Machine.Version)]
+[assembly: AssemblyInformationalVersion(Machine.Version)]
[assembly: CLSCompliant(false)]
[assembly: ComVisible(false)]
diff --git a/Virtu/Wpf/Services/WpfAudioService.cs b/Virtu/Wpf/Services/WpfAudioService.cs
index 08c831b..ad41c61 100644
--- a/Virtu/Wpf/Services/WpfAudioService.cs
+++ b/Virtu/Wpf/Services/WpfAudioService.cs
@@ -28,7 +28,7 @@ public WpfAudioService(Machine machine, UserControl page) :
};
}
- public override void SetVolume(double volume) // machine thread
+ public override void SetVolume(double volume)
{
_directSound.SetVolume(volume);
}
@@ -50,7 +50,8 @@ private void OnDirectSoundUpdate(IntPtr buffer, int bufferSize) // audio thread
// DebugService.WriteLine("OnDirectSoundUpdate");
//}
- Update(bufferSize, (source, count) => Marshal.Copy(source, 0, buffer, count));
+ Marshal.Copy(Source, 0, buffer, bufferSize);
+ Update();
}
private DirectSound _directSound;
diff --git a/Virtu/Wpf/Services/WpfDebugService.cs b/Virtu/Wpf/Services/WpfDebugService.cs
index 9c77ea9..6eefa8c 100644
--- a/Virtu/Wpf/Services/WpfDebugService.cs
+++ b/Virtu/Wpf/Services/WpfDebugService.cs
@@ -18,7 +18,7 @@ public WpfDebugService(Machine machine, MainPage page) :
protected override void OnWriteLine(string message)
{
- _page.Dispatcher.CheckInvoke(() => _page.WriteLine(message + Environment.NewLine));
+ _page.Dispatcher.Post(() => _page.WriteLine(message + Environment.NewLine));
}
private MainPage _page;
diff --git a/Virtu/Wpf/Services/WpfKeyboardService.cs b/Virtu/Wpf/Services/WpfKeyboardService.cs
index b733407..c3e4e75 100644
--- a/Virtu/Wpf/Services/WpfKeyboardService.cs
+++ b/Virtu/Wpf/Services/WpfKeyboardService.cs
@@ -88,15 +88,15 @@ private void OnPageKeyUp(object sender, KeyEventArgs e)
if (control && (e.Key == Key.Divide))
{
- Machine.Cpu.ToggleThrottle();
+ Machine.Cpu.IsThrottled ^= true;
}
else if (control && (e.Key == Key.Multiply))
{
- Machine.Video.ToggleMonochrome();
+ Machine.Video.IsMonochrome ^= true;
}
else if (control && (e.Key == Key.Subtract))
{
- Machine.Video.ToggleFullScreen();
+ Machine.Video.IsFullScreen ^= true;
}
Update();
diff --git a/Virtu/Wpf/Services/WpfVideoService.cs b/Virtu/Wpf/Services/WpfVideoService.cs
index fcd2f34..0e4ad3d 100644
--- a/Virtu/Wpf/Services/WpfVideoService.cs
+++ b/Virtu/Wpf/Services/WpfVideoService.cs
@@ -4,6 +4,7 @@
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
+using Jellyfish.Library;
namespace Jellyfish.Virtu.Services
{
@@ -29,6 +30,30 @@ public WpfVideoService(Machine machine, UserControl page, Image image) :
_page.SizeChanged += (sender, e) => SetImageSize();
}
+ public override void SetFullScreen(bool isFullScreen)
+ {
+ if (_isFullScreen != isFullScreen)
+ {
+ _isFullScreen = isFullScreen;
+ _page.Dispatcher.Send(() =>
+ {
+ var window = Window.GetWindow(_page);
+ if (_isFullScreen)
+ {
+ window.ResizeMode = ResizeMode.NoResize;
+ window.WindowStyle = WindowStyle.None;
+ window.WindowState = WindowState.Maximized;
+ }
+ else
+ {
+ window.WindowState = WindowState.Normal;
+ window.WindowStyle = WindowStyle.SingleBorderWindow;
+ window.ResizeMode = ResizeMode.CanResize;
+ }
+ });
+ }
+ }
+
[SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow")]
public override void SetPixel(int x, int y, uint color)
{
@@ -38,24 +63,6 @@ public override void SetPixel(int x, int y, uint color)
public override void Update() // main thread
{
- if (_isFullScreen != IsFullScreen)
- {
- var window = Window.GetWindow(_page);
- if (IsFullScreen)
- {
- window.ResizeMode = ResizeMode.NoResize;
- window.WindowStyle = WindowStyle.None;
- window.WindowState = WindowState.Maximized;
- }
- else
- {
- window.WindowState = WindowState.Normal;
- window.WindowStyle = WindowStyle.SingleBorderWindow;
- window.ResizeMode = ResizeMode.CanResize;
- }
- _isFullScreen = IsFullScreen;
- }
-
if (_pixelsDirty)
{
_pixelsDirty = false;
@@ -68,7 +75,6 @@ private void SetImageSize()
int uniformScale = Math.Max(1, Math.Min((int)_page.RenderSize.Width / BitmapWidth, (int)_page.RenderSize.Height / BitmapHeight));
_image.Width = uniformScale * BitmapWidth;
_image.Height = uniformScale * BitmapHeight;
- Machine.Video.DirtyScreen();
}
private void SetWindowSizeToContent()
diff --git a/Virtu/Xna/Jellyfish.Virtu.Xna.Phone.csproj b/Virtu/Xna/Jellyfish.Virtu.Xna.Phone.csproj
index fbbd0a2..32bec19 100644
--- a/Virtu/Xna/Jellyfish.Virtu.Xna.Phone.csproj
+++ b/Virtu/Xna/Jellyfish.Virtu.Xna.Phone.csproj
@@ -102,9 +102,6 @@
False
-
- False
-
@@ -149,9 +146,6 @@
Core\MachineEvents.cs
-
- Core\MachineSettings.cs
-
Core\Memory.cs
diff --git a/Virtu/Xna/Jellyfish.Virtu.Xna.Xbox.csproj b/Virtu/Xna/Jellyfish.Virtu.Xna.Xbox.csproj
index d497617..5d01606 100644
--- a/Virtu/Xna/Jellyfish.Virtu.Xna.Xbox.csproj
+++ b/Virtu/Xna/Jellyfish.Virtu.Xna.Xbox.csproj
@@ -108,9 +108,6 @@
False
-
- False
-
@@ -155,9 +152,6 @@
Core\MachineEvents.cs
-
- Core\MachineSettings.cs
-
Core\Memory.cs
diff --git a/Virtu/Xna/Jellyfish.Virtu.Xna.csproj b/Virtu/Xna/Jellyfish.Virtu.Xna.csproj
index 35e2bd6..45a553a 100644
--- a/Virtu/Xna/Jellyfish.Virtu.Xna.csproj
+++ b/Virtu/Xna/Jellyfish.Virtu.Xna.csproj
@@ -112,9 +112,6 @@
False
-
- False
-
@@ -159,9 +156,6 @@
Core\MachineEvents.cs
-
- Core\MachineSettings.cs
-
Core\Memory.cs
diff --git a/Virtu/Xna/Properties/AssemblyInfo.cs b/Virtu/Xna/Properties/AssemblyInfo.cs
index cad7758..0179ef6 100644
--- a/Virtu/Xna/Properties/AssemblyInfo.cs
+++ b/Virtu/Xna/Properties/AssemblyInfo.cs
@@ -3,6 +3,7 @@
using System.Resources;
using System.Runtime.InteropServices;
using Jellyfish.Library;
+using Jellyfish.Virtu;
[assembly: AssemblyTitle("Virtu")]
[assembly: AssemblyDescription("Apple IIe Emulator")]
@@ -17,9 +18,9 @@
[assembly: AssemblyCopyright("Copyright © 1995-2010 Digital Jellyfish Design Ltd")]
[assembly: AssemblyComment("Developed by Sean Fausett & Nick Westgate")]
-[assembly: AssemblyVersion("0.8.3.0")]
-[assembly: AssemblyFileVersion("0.8.3.0")]
-[assembly: AssemblyInformationalVersion("0.8.3.0")]
+[assembly: AssemblyVersion(Machine.Version)]
+[assembly: AssemblyFileVersion(Machine.Version)]
+[assembly: AssemblyInformationalVersion(Machine.Version)]
[assembly: CLSCompliant(false)]
[assembly: ComVisible(false)]
diff --git a/Virtu/Xna/Services/XnaAudioService.cs b/Virtu/Xna/Services/XnaAudioService.cs
index 5b8e672..f8a7c87 100644
--- a/Virtu/Xna/Services/XnaAudioService.cs
+++ b/Virtu/Xna/Services/XnaAudioService.cs
@@ -23,7 +23,7 @@ public XnaAudioService(Machine machine, GameBase game) :
_dynamicSoundEffect.Play();
}
- public override void SetVolume(double volume) // machine thread
+ public override void SetVolume(double volume)
{
_dynamicSoundEffect.Volume = (float)volume;
}
@@ -45,7 +45,8 @@ private void OnDynamicSoundEffectBufferNeeded(object sender, EventArgs e) // aud
// DebugService.WriteLine("OnDynamicSoundEffectBufferNeeded");
//}
- Update(SampleSize, (source, count) => _dynamicSoundEffect.SubmitBuffer(source, 0, count));
+ _dynamicSoundEffect.SubmitBuffer(Source, 0, SampleSize);
+ Update();
}
private GameBase _game;
diff --git a/Virtu/Xna/Services/XnaGamePortService.cs b/Virtu/Xna/Services/XnaGamePortService.cs
index 89fddab..6c2b40e 100644
--- a/Virtu/Xna/Services/XnaGamePortService.cs
+++ b/Virtu/Xna/Services/XnaGamePortService.cs
@@ -20,14 +20,22 @@ public override void Update() // main thread
var left = _state.ThumbSticks.Left;
var right = _state.ThumbSticks.Right;
var dpad = _state.DPad;
+ float joystickDeadZone = (float)Machine.GamePort.JoystickDeadZone;
Paddle0 = (int)((1 + left.X) * PaddleScale);
Paddle1 = (int)((1 - left.Y) * PaddleScale); // invert y
Paddle2 = (int)((1 + right.X) * PaddleScale);
Paddle3 = (int)((1 - right.Y) * PaddleScale); // invert y
- Joystick0 = GetJoystick(ref left, ref dpad);
- Joystick1 = GetJoystick(ref right);
+ IsJoystick0Up = ((left.Y > joystickDeadZone) || (dpad.Up == ButtonState.Pressed));
+ IsJoystick0Left = ((left.X < -joystickDeadZone) || (dpad.Left == ButtonState.Pressed));
+ IsJoystick0Right = ((left.X > joystickDeadZone) || (dpad.Right == ButtonState.Pressed));
+ IsJoystick0Down = ((left.Y < -joystickDeadZone) || (dpad.Down == ButtonState.Pressed));
+
+ IsJoystick1Up = (right.Y > joystickDeadZone);
+ IsJoystick1Left = (right.X < -joystickDeadZone);
+ IsJoystick1Right = (right.X > joystickDeadZone);
+ IsJoystick1Down = (right.Y < -joystickDeadZone);
IsButton0Down = ((_state.Buttons.A == ButtonState.Pressed) || (_state.Buttons.LeftShoulder == ButtonState.Pressed));
IsButton1Down = ((_state.Buttons.B == ButtonState.Pressed) || (_state.Buttons.RightShoulder == ButtonState.Pressed));
@@ -35,28 +43,7 @@ public override void Update() // main thread
}
}
- private static Joystick GetJoystick(ref Vector2 thumbstick)
- {
- bool isUp = (thumbstick.Y > JoystickDeadZone);
- bool isLeft = (thumbstick.X < -JoystickDeadZone);
- bool isRight = (thumbstick.X > JoystickDeadZone);
- bool isDown = (thumbstick.Y < -JoystickDeadZone);
-
- return new Joystick(isUp, isLeft, isRight, isDown);
- }
-
- private static Joystick GetJoystick(ref Vector2 thumbstick, ref GamePadDPad dpad)
- {
- bool isUp = ((thumbstick.Y > JoystickDeadZone) || (dpad.Up == ButtonState.Pressed));
- bool isLeft = ((thumbstick.X < -JoystickDeadZone) || (dpad.Left == ButtonState.Pressed));
- bool isRight = ((thumbstick.X > JoystickDeadZone) || (dpad.Right == ButtonState.Pressed));
- bool isDown = ((thumbstick.Y < -JoystickDeadZone) || (dpad.Down == ButtonState.Pressed));
-
- return new Joystick(isUp, isLeft, isRight, isDown);
- }
-
private const int PaddleScale = 128;
- private const float JoystickDeadZone = 0.5f;
private GamePadState _state;
private GamePadState _lastState;
diff --git a/Virtu/Xna/Services/XnaKeyboardService.cs b/Virtu/Xna/Services/XnaKeyboardService.cs
index 92a4dc5..2fda62d 100644
--- a/Virtu/Xna/Services/XnaKeyboardService.cs
+++ b/Virtu/Xna/Services/XnaKeyboardService.cs
@@ -105,16 +105,16 @@ private void OnKeyUp(Keys key, bool gamePadControl)
}
else if ((control && (key == Keys.Divide)) || (gamePadControl && (key == Keys.D8)))
{
- Machine.Cpu.ToggleThrottle();
+ Machine.Cpu.IsThrottled ^= true;
}
else if ((control && (key == Keys.Multiply)) || (gamePadControl && (key == Keys.D9)))
{
- Machine.Video.ToggleMonochrome();
+ Machine.Video.IsMonochrome ^= true;
}
#if WINDOWS
else if ((control && (key == Keys.Subtract)) || (gamePadControl && (key == Keys.D0)))
{
- Machine.Video.ToggleFullScreen();
+ Machine.Video.IsFullScreen ^= true;
}
#endif
}
diff --git a/Virtu/Xna/Services/XnaStorageService.cs b/Virtu/Xna/Services/XnaStorageService.cs
index 7a593e5..29675a2 100644
--- a/Virtu/Xna/Services/XnaStorageService.cs
+++ b/Virtu/Xna/Services/XnaStorageService.cs
@@ -18,7 +18,7 @@ public XnaStorageService(Machine machine, GameBase game) :
_game = game;
}
- public override void Load(string path, Action reader)
+ public override void Load(string fileName, Action reader)
{
if (reader == null)
{
@@ -29,7 +29,7 @@ public override void Load(string path, Action reader)
{
using (var storageContainer = OpenContainer())
{
- using (var stream = storageContainer.OpenFile(path, FileMode.Open, FileAccess.Read, FileShare.Read))
+ using (var stream = storageContainer.OpenFile(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
reader(stream);
}
@@ -40,7 +40,7 @@ public override void Load(string path, Action reader)
}
}
- public override void Save(string path, Action writer)
+ public override void Save(string fileName, Action writer)
{
if (writer == null)
{
@@ -49,7 +49,7 @@ public override void Save(string path, Action writer)
using (var storageContainer = OpenContainer())
{
- using (var stream = storageContainer.OpenFile(path, FileMode.Create, FileAccess.Write, FileShare.None))
+ using (var stream = storageContainer.OpenFile(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
writer(stream);
}
diff --git a/Virtu/Xna/Services/XnaVideoService.cs b/Virtu/Xna/Services/XnaVideoService.cs
index 8716004..6c4e6e4 100644
--- a/Virtu/Xna/Services/XnaVideoService.cs
+++ b/Virtu/Xna/Services/XnaVideoService.cs
@@ -26,6 +26,18 @@ public XnaVideoService(Machine machine, GameBase game) :
_game.GraphicsDeviceService.DeviceReset += (sender, e) => SetTexturePosition();
}
+ public override void SetFullScreen(bool isFullScreen)
+ {
+#if WINDOWS
+ var graphicsDeviceManager = _game.GraphicsDeviceManager;
+ if (graphicsDeviceManager.IsFullScreen != isFullScreen)
+ {
+ graphicsDeviceManager.IsFullScreen = isFullScreen;
+ _game.SynchronizationContext.Send(state => graphicsDeviceManager.ApplyChanges(), null);
+ }
+#endif
+ }
+
[SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow")]
public override void SetPixel(int x, int y, uint color)
{
@@ -35,12 +47,6 @@ public override void SetPixel(int x, int y, uint color)
public override void Update() // main thread
{
-#if WINDOWS
- if (_game.GraphicsDeviceManager.IsFullScreen != IsFullScreen)
- {
- _game.GraphicsDeviceManager.ToggleFullScreen();
- }
-#endif
if (_pixelsDirty)
{
_pixelsDirty = false;