diff --git a/Library/DirectSound.cs b/Library/DirectSound.cs index f679d97..23025bf 100644 --- a/Library/DirectSound.cs +++ b/Library/DirectSound.cs @@ -163,7 +163,7 @@ private void Run() // com mta thread private IntPtr _window; private IDirectSound _device; private IDirectSoundBuffer _buffer; - private object _bufferLock = new object(); + private readonly object _bufferLock = new object(); private Action _updater; private AutoResetEvent _position1Event = new AutoResetEvent(false); diff --git a/Library/Lazy.cs b/Library/Lazy.cs index ab4d831..22245b9 100644 --- a/Library/Lazy.cs +++ b/Library/Lazy.cs @@ -1,5 +1,4 @@ using System; -using System.Threading; namespace Jellyfish.Library { @@ -16,13 +15,11 @@ public T Value { if (_value == null) { - T value = _initializer(); - if (Interlocked.CompareExchange(ref _value, value, null) != null) + lock (_lock) { - var disposable = value as IDisposable; // dispose preempted instance - if (disposable != null) + if (_value == null) { - disposable.Dispose(); + _value = _initializer(); } } } @@ -32,6 +29,7 @@ public T Value } private Func _initializer; - private T _value; + private readonly object _lock = new object(); + private volatile T _value; } } diff --git a/Library/StreamExtensions.cs b/Library/StreamExtensions.cs index 16d7651..e55767f 100644 --- a/Library/StreamExtensions.cs +++ b/Library/StreamExtensions.cs @@ -6,13 +6,16 @@ namespace Jellyfish.Library { public static class StreamExtensions { - [SuppressMessage("Microsoft.Design", "CA1026:DefaultParametersShouldNotBeUsed")] - public static int ReadBlock(this Stream stream, byte[] buffer, int offset = 0, int minCount = int.MaxValue) + [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "3#")] + public static int ReadBlock(this Stream stream, byte[] buffer, int offset, ref int count) { - return ReadBlock(stream, buffer, offset, int.MaxValue, minCount); + int read = ReadBlock(stream, buffer, offset, count, count); + count -= read; + return read; } - public static int ReadBlock(this Stream stream, byte[] buffer, int offset, int count, int minCount) + [SuppressMessage("Microsoft.Design", "CA1026:DefaultParametersShouldNotBeUsed")] + public static int ReadBlock(this Stream stream, byte[] buffer, int offset = 0, int count = int.MaxValue, int minCount = int.MaxValue) { if (stream == null) { @@ -42,6 +45,25 @@ public static int ReadBlock(this Stream stream, byte[] buffer, int offset, int c return total; } + [SuppressMessage("Microsoft.Design", "CA1026:DefaultParametersShouldNotBeUsed")] + public static int ReadWord(this Stream stream, bool optional = false) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + + int lowByte = stream.ReadByte(); + int highByte = stream.ReadByte(); + int word = lowByte | (highByte << 8); + if ((word < 0) && !optional) + { + throw new EndOfStreamException(); + } + + return word; + } + public static void SkipBlock(this Stream stream, int count) { if (stream == null) @@ -55,16 +77,18 @@ public static void SkipBlock(this Stream stream, int count) } else { - const int BufferSize = 1024; - var buffer = new byte[BufferSize]; int total = 0; int read; do { - total += read = stream.Read(buffer, 0, Math.Min(count - total, BufferSize)); + total += read = stream.Read(_skipBuffer, 0, Math.Min(count - total, SkipBufferSize)); } while ((read > 0) && (total < count)); } } + + private const int SkipBufferSize = 1024; + + private static byte[] _skipBuffer = new byte[SkipBufferSize]; } } diff --git a/Virtu/CustomDictionary.xml b/Virtu/CustomDictionary.xml index c3f0bfb..31c5309 100644 --- a/Virtu/CustomDictionary.xml +++ b/Virtu/CustomDictionary.xml @@ -10,8 +10,10 @@ Annunciator Dsk + Prg Unpause Virtu + Xex Xna x y diff --git a/Virtu/DiskIIController.cs b/Virtu/DiskIIController.cs index 3d78dd5..d082a11 100644 --- a/Virtu/DiskIIController.cs +++ b/Virtu/DiskIIController.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using System.IO; using Jellyfish.Library; @@ -11,6 +12,12 @@ public sealed class DiskIIController : PeripheralCard public DiskIIController(Machine machine) : base(machine) { + Drive1 = new DiskIIDrive(machine); + Drive2 = new DiskIIDrive(machine); + + Drives = new Collection { Drive1, Drive2 }; + + BootDrive = Drive1; } public override void Initialize() @@ -41,7 +48,12 @@ public override void LoadState(BinaryReader reader, Version version) _loadMode = reader.ReadBoolean(); _writeMode = reader.ReadBoolean(); _driveSpin = reader.ReadBoolean(); - _drives.ForEach(drive => drive.LoadState(reader, version)); + foreach (var drive in Drives) + { + DebugService.WriteMessage("Loading machine '{0}'", drive.GetType().Name); + drive.LoadState(reader, version); + //DebugService.WriteMessage("Loaded machine '{0}'", drive.GetType().Name); + } } public override void SaveState(BinaryWriter writer) @@ -58,7 +70,12 @@ public override void SaveState(BinaryWriter writer) writer.Write(_loadMode); writer.Write(_writeMode); writer.Write(_driveSpin); - _drives.ForEach(drive => drive.SaveState(writer)); + foreach (var drive in Drives) + { + DebugService.WriteMessage("Saving machine '{0}'", drive.GetType().Name); + drive.SaveState(writer); + //DebugService.WriteMessage("Saved machine '{0}'", drive.GetType().Name); + } } [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] @@ -92,7 +109,7 @@ public override int ReadIoRegionC0C0(int address) { if (!_writeMode) { - return _latch = _drives[_driveNumber].Read(); + return _latch = Drives[_driveNumber].Read(); } else { @@ -107,7 +124,7 @@ public override int ReadIoRegionC0C0(int address) { // write protect is forced if phase 1 is on [F9.7] _latch &= 0x7F; - if (_drives[_driveNumber].IsWriteProtected || + if (Drives[_driveNumber].IsWriteProtected || (_phaseStates & Phase1On) != 0) { _latch |= 0x80; @@ -205,13 +222,13 @@ private void WriteLatch() // write protect is forced if phase 1 is on [F9.7] if ((_phaseStates & Phase1On) == 0) { - _drives[_driveNumber].Write(_latch); + Drives[_driveNumber].Write(_latch); } } private void Flush() { - _drives[_driveNumber].FlushTrack(); + Drives[_driveNumber].FlushTrack(); } private void SetDriveNumber(int driveNumber) @@ -241,19 +258,22 @@ private void SetPhase(int address) if (_motorOn) { - _drives[_driveNumber].ApplyPhaseChange(_phaseStates); + Drives[_driveNumber].ApplyPhaseChange(_phaseStates); } } - [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] - public DiskIIDrive[] Drives { get { return _drives; } } + public DiskIIDrive Drive1 { get; private set; } + public DiskIIDrive Drive2 { get; private set; } + + public Collection Drives { get; private set; } + + public DiskIIDrive BootDrive { get; private set; } private const int Phase0On = 1 << 0; private const int Phase1On = 1 << 1; private const int Phase2On = 1 << 2; private const int Phase3On = 1 << 3; - private DiskIIDrive[] _drives = new DiskIIDrive[] { new DiskIIDrive(), new DiskIIDrive() }; private int _latch; private int _phaseStates; private bool _motorOn; diff --git a/Virtu/DiskIIDrive.cs b/Virtu/DiskIIDrive.cs index efef69e..c59c2cf 100644 --- a/Virtu/DiskIIDrive.cs +++ b/Virtu/DiskIIDrive.cs @@ -5,9 +5,10 @@ namespace Jellyfish.Virtu { - public sealed class DiskIIDrive + public sealed class DiskIIDrive : MachineComponent { - public DiskIIDrive() + public DiskIIDrive(Machine machine) : + base(machine) { DriveArmStepDelta[0] = new int[] { 0, 0, 1, 1, 0, 0, 1, 1, -1, -1, 0, 0, -1, -1, 0, 0 }; // phase 0 DriveArmStepDelta[1] = new int[] { 0, -1, 0, -1, 1, 0, 1, 0, 0, -1, 0, -1, 1, 0, 1, 0 }; // phase 1 @@ -15,7 +16,7 @@ public DiskIIDrive() DriveArmStepDelta[3] = new int[] { 0, 1, 0, 1, -1, 0, -1, 0, 0, 1, 0, 1, -1, 0, -1, 0 }; // phase 3 } - public void LoadState(BinaryReader reader, Version version) + public override void LoadState(BinaryReader reader, Version version) { if (reader == null) { @@ -30,10 +31,18 @@ public void LoadState(BinaryReader reader, Version version) { reader.Read(_trackData, 0, _trackData.Length); } - _disk = reader.ReadBoolean() ? Disk525.LoadState(reader, version) : null; + if (reader.ReadBoolean()) + { + DebugService.WriteMessage("Loading machine '{0}'", typeof(Disk525).Name); + _disk = Disk525.LoadState(reader, version); + } + else + { + _disk = null; + } } - public void SaveState(BinaryWriter writer) + public override void SaveState(BinaryWriter writer) { if (writer == null) { @@ -51,12 +60,14 @@ public void SaveState(BinaryWriter writer) writer.Write(_disk != null); if (_disk != null) { + DebugService.WriteMessage("Saving machine '{0}'", _disk.GetType().Name); _disk.SaveState(writer); } } public void InsertDisk(string name, Stream stream, bool isWriteProtected) { + DebugService.WriteMessage("Inserting disk '{0}'", name); FlushTrack(); _disk = Disk525.CreateDisk(name, stream, isWriteProtected); _trackLoaded = false; @@ -64,11 +75,15 @@ public void InsertDisk(string name, Stream stream, bool isWriteProtected) public void RemoveDisk() { - _trackLoaded = false; - _trackChanged = false; - _trackNumber = 0; - _trackOffset = 0; - _disk = null; + if (_disk != null) + { + DebugService.WriteMessage("Removing disk '{0}'", _disk.Name); + _trackLoaded = false; + _trackChanged = false; + _trackNumber = 0; + _trackOffset = 0; + _disk = null; + } } public void ApplyPhaseChange(int phaseState) diff --git a/Virtu/Machine.cs b/Virtu/Machine.cs index e1acf16..73f4af4 100644 --- a/Virtu/Machine.cs +++ b/Virtu/Machine.cs @@ -1,6 +1,6 @@ using System; -using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text.RegularExpressions; @@ -39,6 +39,8 @@ public Machine() Slots = new Collection { null, 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 }; + BootDiskII = Slots.OfType().Last(); + Thread = new Thread(Run) { Name = "Machine" }; } @@ -52,33 +54,45 @@ public void Reset() { foreach (var component in Components) { - //_debugService.WriteLine("Resetting component '{0}'", component.GetType().Name); + _debugService.WriteMessage("Resetting machine '{0}'", component.GetType().Name); component.Reset(); - //_debugService.WriteLine("Reset component '{0}'", component.GetType().Name); + //_debugService.WriteMessage("Reset machine '{0}'", component.GetType().Name); } } + [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Jellyfish.Virtu.Services.DebugService.WriteMessage(System.String)")] public void Start() { + _debugService = Services.GetService(); + _storageService = Services.GetService(); + + _debugService.WriteMessage("Starting machine"); State = MachineState.Starting; Thread.Start(); } + [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Jellyfish.Virtu.Services.DebugService.WriteMessage(System.String)")] public void Pause() { + _debugService.WriteMessage("Pausing machine"); State = MachineState.Pausing; _pauseEvent.WaitOne(); State = MachineState.Paused; + _debugService.WriteMessage("Paused machine"); } + [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Jellyfish.Virtu.Services.DebugService.WriteMessage(System.String)")] public void Unpause() { + _debugService.WriteMessage("Running machine"); State = MachineState.Running; _unpauseEvent.Set(); } + [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Jellyfish.Virtu.Services.DebugService.WriteMessage(System.String)")] public void Stop() { + _debugService.WriteMessage("Stopping machine"); State = MachineState.Stopping; _unpauseEvent.Set(); if (Thread.IsAlive) @@ -86,15 +100,16 @@ public void Stop() Thread.Join(); } State = MachineState.Stopped; + _debugService.WriteMessage("Stopped machine"); } private void Initialize() { foreach (var component in Components) { - //_debugService.WriteLine("Initializing component '{0}'", component.GetType().Name); + _debugService.WriteMessage("Initializing machine '{0}'", component.GetType().Name); component.Initialize(); - //_debugService.WriteLine("Initialized component '{0}'", component.GetType().Name); + //_debugService.WriteMessage("Initialized machine '{0}'", component.GetType().Name); } } @@ -119,18 +134,22 @@ private void LoadState() } else if (name.EndsWith(".prg", StringComparison.OrdinalIgnoreCase)) { - loader(name, stream => Memory.LoadProgram(stream)); + loader(name, stream => Memory.LoadPrg(stream)); + } + else if (name.EndsWith(".xex", StringComparison.OrdinalIgnoreCase)) + { + loader(name, stream => Memory.LoadXex(stream)); } else if (Regex.IsMatch(name, @"\.(dsk|nib)$", RegexOptions.IgnoreCase)) { - loader(name, stream => BootDiskII.Drives[0].InsertDisk(name, stream, false)); + loader(name, stream => BootDiskII.BootDrive.InsertDisk(name, stream, false)); } } else #endif if (!_storageService.Load(Machine.StateFileName, stream => LoadState(stream))) { - StorageService.LoadResource("Disks/Default.dsk", stream => BootDiskII.Drives[0].InsertDisk("Default.dsk", stream, false)); + StorageService.LoadResource("Disks/Default.dsk", stream => BootDiskII.BootDrive.InsertDisk("Default.dsk", stream, false)); } } @@ -138,17 +157,17 @@ private void LoadState(Stream stream) { using (var reader = new BinaryReader(stream)) { - string stateSignature = reader.ReadString(); - var stateVersion = new Version(reader.ReadString()); - if ((stateSignature != StateSignature) || (stateVersion != new Version(Machine.Version))) // avoid state version mismatch (for now) + string signature = reader.ReadString(); + var version = new Version(reader.ReadString()); + if ((signature != StateSignature) || (version != new Version(Machine.Version))) // avoid state version mismatch (for now) { throw new InvalidOperationException(); } foreach (var component in Components) { - //_debugService.WriteLine("Loading component '{0}' state", component.GetType().Name); - component.LoadState(reader, stateVersion); - //_debugService.WriteLine("Loaded component '{0}' state", component.GetType().Name); + _debugService.WriteMessage("Loading machine '{0}'", component.GetType().Name); + component.LoadState(reader, version); + //_debugService.WriteMessage("Loaded machine '{0}'", component.GetType().Name); } } } @@ -166,9 +185,9 @@ private void SaveState(Stream stream) writer.Write(Machine.Version); foreach (var component in Components) { - //_debugService.WriteLine("Saving component '{0}' state", component.GetType().Name); + _debugService.WriteMessage("Saving machine '{0}'", component.GetType().Name); component.SaveState(writer); - //_debugService.WriteLine("Saved component '{0}' state", component.GetType().Name); + //_debugService.WriteMessage("Saved machine '{0}'", component.GetType().Name); } } } @@ -177,22 +196,20 @@ private void Uninitialize() { foreach (var component in Components) { - //_debugService.WriteLine("Uninitializing component '{0}'", component.GetType().Name); + _debugService.WriteMessage("Uninitializing machine '{0}'", component.GetType().Name); component.Uninitialize(); - //_debugService.WriteLine("Uninitialized component '{0}'", component.GetType().Name); + //_debugService.WriteMessage("Uninitialized machine '{0}'", component.GetType().Name); } } + [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Jellyfish.Virtu.Services.DebugService.WriteMessage(System.String)")] private void Run() // machine thread { - //_debugService = Services.GetService(); - _storageService = Services.GetService(); - _bootDiskII = Slots.OfType().Last(); - Initialize(); Reset(); LoadState(); + _debugService.WriteMessage("Running machine"); State = MachineState.Running; do { @@ -237,20 +254,19 @@ private void Run() // machine thread public PeripheralCard Slot6 { get; private set; } public PeripheralCard Slot7 { get; private set; } - public DiskIIController BootDiskII { get { return _bootDiskII; } } - public Collection Slots { get; private set; } public Collection Components { get; private set; } + public DiskIIController BootDiskII { get; private set; } + public Thread Thread { get; private set; } private const string StateFileName = "State.bin"; private const string StateSignature = "Virtu"; - //private DebugService _debugService; + private DebugService _debugService; private StorageService _storageService; private volatile MachineState _state; - private DiskIIController _bootDiskII; private AutoResetEvent _pauseEvent = new AutoResetEvent(false); private AutoResetEvent _unpauseEvent = new AutoResetEvent(false); diff --git a/Virtu/MachineComponent.cs b/Virtu/MachineComponent.cs index e1e3836..195b8ed 100644 --- a/Virtu/MachineComponent.cs +++ b/Virtu/MachineComponent.cs @@ -1,5 +1,7 @@ using System; using System.IO; +using Jellyfish.Library; +using Jellyfish.Virtu.Services; namespace Jellyfish.Virtu { @@ -8,6 +10,8 @@ public abstract class MachineComponent protected MachineComponent(Machine machine) { Machine = machine; + + _debugService = new Lazy(() => Machine.Services.GetService()); } public virtual void Initialize() @@ -31,5 +35,8 @@ public virtual void SaveState(BinaryWriter writer) } protected Machine Machine { get; private set; } + protected DebugService DebugService { get { return _debugService.Value; } } + + private Lazy _debugService; } } diff --git a/Virtu/Memory.cs b/Virtu/Memory.cs index f55c6d7..683835f 100644 --- a/Virtu/Memory.cs +++ b/Virtu/Memory.cs @@ -1,7 +1,9 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.IO; using Jellyfish.Library; +using Jellyfish.Virtu.Properties; using Jellyfish.Virtu.Services; namespace Jellyfish.Virtu @@ -124,45 +126,6 @@ public override void Reset() // [7-3] MapRegionD0FF(); } - public void LoadProgram(Stream stream) - { - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - - int address = stream.ReadByte(); - address |= stream.ReadByte() << 8; - if (address < 0) - { - throw new EndOfStreamException(); - } - int entry = address; - - if (address < 0x0200) - { - address += stream.ReadBlock(_ramMainRegion0001, address, 0); - } - if ((0x0200 <= address) && (address < 0xC000)) - { - address += stream.ReadBlock(_ramMainRegion02BF, address - 0x0200, 0); - } - if ((0xC000 <= address) && (address < 0xD000)) - { - address += stream.ReadBlock(_ramMainBank1RegionD0DF, address - 0xC000, 0); - } - if ((0xD000 <= address) && (address < 0xE000)) - { - address += stream.ReadBlock(_ramMainBank2RegionD0DF, address - 0xD000, 0); - } - if (0xE000 <= address) - { - address += stream.ReadBlock(_ramMainRegionE0FF, address - 0xE000, 0); - } - - SetWarmEntry(entry); // assumes autostart monitor - } - public override void LoadState(BinaryReader reader, Version version) { if (reader == null) @@ -212,6 +175,49 @@ public override void SaveState(BinaryWriter writer) writer.Write(_ramAuxRegionE0FF); } + public void LoadPrg(Stream stream) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + + int startAddress = stream.ReadWord(); + SetWarmEntry(startAddress); // assumes autostart monitor + Load(stream, startAddress); + } + + public void LoadXex(Stream stream) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + + const int Marker = 0xFFFF; + int marker = stream.ReadWord(); // mandatory marker + if (marker != Marker) + { + throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, Strings.MarkerNotFound, Marker)); + } + int startAddress = stream.ReadWord(); + int endAddress = stream.ReadWord(); + SetWarmEntry(startAddress); // assumes autostart monitor + + do + { + if (startAddress > endAddress) + { + throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, Strings.InvalidAddressRange, startAddress, endAddress)); + } + Load(stream, startAddress, endAddress - startAddress + 1); + marker = stream.ReadWord(optional: true); // optional marker + startAddress = (marker != Marker) ? marker : stream.ReadWord(optional: true); + endAddress = stream.ReadWord(optional: true); + } + while ((startAddress >= 0) && (endAddress >= 0)); + } + #region Core Read & Write public int Read(int address) { @@ -1546,6 +1552,62 @@ private void SetZeroPage(bool value) } #endregion + private void Load(Stream stream, int startAddress) + { + DebugService.WriteMessage("Loading memory ${0:X04}", startAddress); + int address = startAddress; + if (address < 0x0200) + { + address += stream.ReadBlock(_ramMainRegion0001, address, minCount: 0); + } + if ((0x0200 <= address) && (address < 0xC000)) + { + address += stream.ReadBlock(_ramMainRegion02BF, address - 0x0200, minCount: 0); + } + if ((0xC000 <= address) && (address < 0xD000)) + { + address += stream.ReadBlock(_ramMainBank1RegionD0DF, address - 0xC000, minCount: 0); + } + if ((0xD000 <= address) && (address < 0xE000)) + { + address += stream.ReadBlock(_ramMainBank2RegionD0DF, address - 0xD000, minCount: 0); + } + if (0xE000 <= address) + { + address += stream.ReadBlock(_ramMainRegionE0FF, address - 0xE000, minCount: 0); + } + if (address > startAddress) + { + DebugService.WriteMessage("Loaded memory ${0:X04}-${1:X04} (${2:X04})", startAddress, address - 1, address - startAddress); + } + } + + private void Load(Stream stream, int startAddress, int length) + { + DebugService.WriteMessage("Loading memory ${0:X04}-${1:X04} (${2:X04})", startAddress, startAddress + length - 1, length); + int address = startAddress; + if (address < 0x0200) + { + address += stream.ReadBlock(_ramMainRegion0001, address, ref length); + } + if ((0x0200 <= address) && (address < 0xC000)) + { + address += stream.ReadBlock(_ramMainRegion02BF, address - 0x0200, ref length); + } + if ((0xC000 <= address) && (address < 0xD000)) + { + address += stream.ReadBlock(_ramMainBank1RegionD0DF, address - 0xC000, ref length); + } + if ((0xD000 <= address) && (address < 0xE000)) + { + address += stream.ReadBlock(_ramMainBank2RegionD0DF, address - 0xD000, ref length); + } + if (0xE000 <= address) + { + address += stream.ReadBlock(_ramMainRegionE0FF, address - 0xE000, ref length); + } + } + private void SetWarmEntry(int address) { _ramMainRegion02BF[0x03F2 - 0x0200] = (byte)(address & 0xFF); diff --git a/Virtu/Properties/Strings.Designer.cs b/Virtu/Properties/Strings.Designer.cs index 3996748..cbf407b 100644 --- a/Virtu/Properties/Strings.Designer.cs +++ b/Virtu/Properties/Strings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.530 +// Runtime Version:4.0.30319.544 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -60,6 +60,24 @@ internal Strings() { } } + /// + /// Looks up a localized string similar to Invalid address range ${0:X04}-${1:X04}.. + /// + internal static string InvalidAddressRange { + get { + return ResourceManager.GetString("InvalidAddressRange", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Marker ${0:X04} not found.. + /// + internal static string MarkerNotFound { + get { + return ResourceManager.GetString("MarkerNotFound", resourceCulture); + } + } + /// /// Looks up a localized string similar to Resource '{0}' not found.. /// diff --git a/Virtu/Properties/Strings.resx b/Virtu/Properties/Strings.resx index e703e94..90993f2 100644 --- a/Virtu/Properties/Strings.resx +++ b/Virtu/Properties/Strings.resx @@ -117,6 +117,12 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Invalid address range ${0:X04}-${1:X04}. + + + Marker ${0:X04} not found. + Resource '{0}' not found. diff --git a/Virtu/Services/DebugService.cs b/Virtu/Services/DebugService.cs index b1d09d6..3cf916c 100644 --- a/Virtu/Services/DebugService.cs +++ b/Virtu/Services/DebugService.cs @@ -1,6 +1,9 @@ using System; using System.Diagnostics; using System.Globalization; +using System.Text; +using System.Threading; +using Jellyfish.Library; namespace Jellyfish.Virtu.Services { @@ -11,19 +14,54 @@ public DebugService(Machine machine) : { } - public void WriteLine(string message) + public void WriteMessage(string message) { - OnWriteLine(string.Concat(DateTime.Now.TimeOfDay, ' ', message)); + OnWriteMessage(FormatMessage(message)); } - public void WriteLine(string format, params object[] args) + public void WriteMessage(string format, params object[] args) { - WriteLine(string.Format(CultureInfo.InvariantCulture, format, args)); + OnWriteMessage(FormatMessage(format, args)); } - protected virtual void OnWriteLine(string message) + protected virtual void OnWriteMessage(string message) { +#if SILVERLIGHT || WINDOWS_PHONE || XBOX Debug.WriteLine(message); +#else + Trace.WriteLine(message); +#endif } + + private string FormatMessage(string format, params object[] args) + { + var message = new StringBuilder(256); + message.AppendFormat(CultureInfo.InvariantCulture, "[{0} T{1:X3} Virtu] ", DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture), Thread.CurrentThread.ManagedThreadId); + if (args.Length > 0) + { + try + { + message.AppendFormat(CultureInfo.InvariantCulture, format, args); + } + catch (FormatException ex) + { +#if WINDOWS_PHONE || XBOX + WriteMessage("[DebugService.FormatMessage] format: {0}; exception: {1}", format, ex.Message); +#else + WriteMessage("[DebugService.FormatMessage] format: {0}; args: {1}; exception: {2}", format, string.Join(", ", args), ex.Message); +#endif + } + } + else + { + message.Append(format); + } + + return message.ToString(); + } + + public static DebugService Default { get { return _default.Value; } } + + private static readonly Lazy _default = new Lazy(() => new DebugService(null)); } } diff --git a/Virtu/Services/StorageService.cs b/Virtu/Services/StorageService.cs index 5bf1894..b1a438e 100644 --- a/Virtu/Services/StorageService.cs +++ b/Virtu/Services/StorageService.cs @@ -20,11 +20,12 @@ public bool Load(string fileName, Action reader) { try { + DebugService.WriteMessage("Loading file '{0}'", fileName); OnLoad(fileName, reader); } - catch (Exception e) + catch (Exception ex) { - Debug.WriteLine(e.ToString()); + DebugService.WriteMessage(ex.ToString()); return false; } @@ -44,14 +45,15 @@ public static bool LoadFile(string fileName, Action reader) try { + DebugService.Default.WriteMessage("Loading file '{0}'", fileName); using (var stream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { reader(stream); } } - catch (Exception e) + catch (Exception ex) { - Debug.WriteLine(e.ToString()); + DebugService.Default.WriteMessage(ex.ToString()); return false; } @@ -75,14 +77,15 @@ public static bool LoadFile(FileInfo fileInfo, Action reader) try { + DebugService.Default.WriteMessage("Loading file '{0}'", fileInfo.Name); using (var stream = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.Read)) { reader(stream); } } - catch (Exception e) + catch (Exception ex) { - Debug.WriteLine(e.ToString()); + DebugService.Default.WriteMessage(ex.ToString()); return false; } @@ -99,14 +102,15 @@ public static bool LoadResource(string resourceName, Action reader) try { + DebugService.Default.WriteMessage("Loading resource '{0}'", resourceName); using (var stream = GetResourceStream(resourceName)) { reader(stream); } } - catch (Exception e) + catch (Exception ex) { - Debug.WriteLine(e.ToString()); + DebugService.Default.WriteMessage(ex.ToString()); return false; } @@ -118,11 +122,12 @@ public bool Save(string fileName, Action writer) { try { + DebugService.WriteMessage("Saving file '{0}'", fileName); OnSave(fileName, writer); } - catch (Exception e) + catch (Exception ex) { - Debug.WriteLine(e.ToString()); + DebugService.WriteMessage(ex.ToString()); return false; } @@ -142,14 +147,15 @@ public static bool SaveFile(string fileName, Action writer) try { + DebugService.Default.WriteMessage("Saving file '{0}'", fileName); using (var stream = File.Open(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) { writer(stream); } } - catch (Exception e) + catch (Exception ex) { - Debug.WriteLine(e.ToString()); + DebugService.Default.WriteMessage(ex.ToString()); return false; } @@ -173,14 +179,15 @@ public static bool SaveFile(FileInfo fileInfo, Action writer) try { + DebugService.Default.WriteMessage("Saving file '{0}'", fileInfo.Name); using (var stream = fileInfo.Open(FileMode.Create, FileAccess.Write, FileShare.None)) { writer(stream); } } - catch (Exception e) + catch (Exception ex) { - Debug.WriteLine(e.ToString()); + DebugService.Default.WriteMessage(ex.ToString()); return false; } diff --git a/Virtu/Silverlight/MainPage.xaml.cs b/Virtu/Silverlight/MainPage.xaml.cs index 8b5dce9..1abea46 100644 --- a/Virtu/Silverlight/MainPage.xaml.cs +++ b/Virtu/Silverlight/MainPage.xaml.cs @@ -15,7 +15,7 @@ public MainPage() if (!DesignerProperties.IsInDesignTool) { - _debugService = new SilverlightDebugService(_machine, this); + _debugService = DebugService.Default; _storageService = new IsolatedStorageService(_machine); _keyboardService = new SilverlightKeyboardService(_machine, this); _gamePortService = new GamePortService(_machine); // not connected @@ -49,9 +49,9 @@ public void Dispose() _videoService.Dispose(); } - public void WriteLine(string message) + public void WriteMessage(string message) { - _debugText.Text += message; + _debugText.Text += message + Environment.NewLine; _debugScrollViewer.UpdateLayout(); _debugScrollViewer.ScrollToVerticalOffset(double.MaxValue); } diff --git a/Virtu/Silverlight/Phone/MainPage.xaml.cs b/Virtu/Silverlight/Phone/MainPage.xaml.cs index c111040..eb0f317 100644 --- a/Virtu/Silverlight/Phone/MainPage.xaml.cs +++ b/Virtu/Silverlight/Phone/MainPage.xaml.cs @@ -15,7 +15,7 @@ public MainPage() if (!DesignerProperties.IsInDesignTool) { - _debugService = new SilverlightDebugService(_machine, this); + _debugService = DebugService.Default; _storageService = new IsolatedStorageService(_machine); _keyboardService = new SilverlightKeyboardService(_machine, this); _gamePortService = new GamePortService(_machine); // not connected @@ -49,9 +49,9 @@ public void Dispose() _videoService.Dispose(); } - public void WriteLine(string message) + public void WriteMessage(string message) { - _debugText.Text += message; + _debugText.Text += message + Environment.NewLine; _debugScrollViewer.UpdateLayout(); _debugScrollViewer.ScrollToVerticalOffset(double.MaxValue); } diff --git a/Virtu/Silverlight/Services/SilverlightDebugService.cs b/Virtu/Silverlight/Services/SilverlightDebugService.cs index bdf938e..4e187ea 100644 --- a/Virtu/Silverlight/Services/SilverlightDebugService.cs +++ b/Virtu/Silverlight/Services/SilverlightDebugService.cs @@ -16,9 +16,9 @@ public SilverlightDebugService(Machine machine, MainPage page) : _page = page; } - protected override void OnWriteLine(string message) + protected override void OnWriteMessage(string message) { - _page.Dispatcher.Post(() => _page.WriteLine(message + Environment.NewLine)); + _page.Dispatcher.Post(() => _page.WriteMessage(message)); } private MainPage _page; diff --git a/Virtu/Wpf/Jellyfish.Virtu.Wpf.csproj b/Virtu/Wpf/Jellyfish.Virtu.Wpf.csproj index 9119a7a..16f6a17 100644 --- a/Virtu/Wpf/Jellyfish.Virtu.Wpf.csproj +++ b/Virtu/Wpf/Jellyfish.Virtu.Wpf.csproj @@ -29,6 +29,8 @@ true AllRules.ruleset false + + x86 @@ -41,6 +43,8 @@ true AllRules.ruleset false + + Jellyfish.Virtu.MainApp diff --git a/Virtu/Wpf/MainPage.xaml.cs b/Virtu/Wpf/MainPage.xaml.cs index 95c0091..d030c7b 100644 --- a/Virtu/Wpf/MainPage.xaml.cs +++ b/Virtu/Wpf/MainPage.xaml.cs @@ -16,7 +16,7 @@ public MainPage() if (!DesignerProperties.GetIsInDesignMode(this)) { - _debugService = new WpfDebugService(_machine, this); + _debugService = DebugService.Default; _storageService = new WpfStorageService(_machine); _keyboardService = new WpfKeyboardService(_machine, this); _gamePortService = new GamePortService(_machine); // not connected @@ -50,9 +50,9 @@ public void Dispose() _videoService.Dispose(); } - public void WriteLine(string message) + public void WriteMessage(string message) { - _debugText.Text += message; + _debugText.Text += message + Environment.NewLine; _debugScrollViewer.UpdateLayout(); _debugScrollViewer.ScrollToVerticalOffset(double.MaxValue); } diff --git a/Virtu/Wpf/Services/WpfDebugService.cs b/Virtu/Wpf/Services/WpfDebugService.cs index 6eefa8c..6ce27e1 100644 --- a/Virtu/Wpf/Services/WpfDebugService.cs +++ b/Virtu/Wpf/Services/WpfDebugService.cs @@ -16,9 +16,9 @@ public WpfDebugService(Machine machine, MainPage page) : _page = page; } - protected override void OnWriteLine(string message) + protected override void OnWriteMessage(string message) { - _page.Dispatcher.Post(() => _page.WriteLine(message + Environment.NewLine)); + _page.Dispatcher.Post(() => _page.WriteMessage(message)); } private MainPage _page; diff --git a/Virtu/Xna/MainGame.cs b/Virtu/Xna/MainGame.cs index bdf90b4..c173b91 100644 --- a/Virtu/Xna/MainGame.cs +++ b/Virtu/Xna/MainGame.cs @@ -20,7 +20,7 @@ public MainGame() : frameRateCounter.DrawOrder = 1; frameRateCounter.FontName = "Consolas"; - _debugService = new DebugService(_machine); + _debugService = DebugService.Default; #if WINDOWS_PHONE _storageService = new IsolatedStorageService(_machine); #else