From 27a5e3ac896e8b865a49c16b3c3fe111750f5b99 Mon Sep 17 00:00:00 2001 From: Sean Fausett Date: Tue, 18 Jun 2013 16:52:34 +1200 Subject: [PATCH] Add git attributes file. Normalize text files. --- .gitattributes | 14 + .gitignore | 12 +- Library/AssemblyMetadataAttribute.cs | 34 +- Library/CustomDictionary.xml | 18 +- Library/DirectSound.cs | 346 +- Library/DirectSoundInterop.cs | 220 +- Library/DispatcherExtensions.cs | 72 +- Library/DisposableBase.cs | 52 +- Library/FrameRateCounter.xaml | 18 +- Library/FrameRateCounter.xaml.cs | 84 +- Library/GCHandleHelpers.cs | 64 +- Library/GlobalSuppressions.cs | 8 +- Library/IEnumerableExtensions.cs | 50 +- Library/Jellyfish.Library.sln | 52 +- Library/MarshalHelpers.cs | 70 +- Library/MathHelpers.cs | 30 +- Library/Silverlight/ApplicationBase.cs | 190 +- .../Jellyfish.Library.Silverlight.csproj | 264 +- .../Jellyfish.Library.Silverlight.sln | 40 +- .../Silverlight/Properties/AssemblyInfo.cs | 44 +- Library/Silverlight/WaveMediaStreamSource.cs | 152 +- Library/StreamExtensions.cs | 188 +- Library/StringBuilderExtensions.cs | 108 +- Library/WaveFormat.cs | 98 +- Library/Wpf/ApplicationBase.cs | 130 +- Library/Wpf/Jellyfish.Library.Wpf.csproj | 238 +- Library/Wpf/Jellyfish.Library.Wpf.sln | 40 +- Library/Wpf/Properties/AssemblyInfo.cs | 44 +- Library/Wpf/WindowExtensions.cs | 28 +- License.txt | 560 +- Virtu/Cassette.cs | 46 +- Virtu/Cpu.cs | 6522 ++++++++--------- Virtu/CpuData.cs | 166 +- Virtu/CustomDictionary.xml | 56 +- Virtu/Disk525.cs | 194 +- Virtu/DiskDsk.cs | 648 +- Virtu/DiskIIController.cs | 574 +- Virtu/DiskIIDrive.cs | 344 +- Virtu/DiskNib.cs | 70 +- Virtu/GamePort.cs | 740 +- Virtu/GlobalSuppressions.cs | 6 +- Virtu/Jellyfish.Virtu.sln | 76 +- Virtu/Keyboard.cs | 240 +- Virtu/Machine.cs | 546 +- Virtu/MachineComponent.cs | 84 +- Virtu/MachineEvents.cs | 214 +- Virtu/Memory.cs | 3476 ++++----- Virtu/MemoryData.cs | 212 +- Virtu/NoSlotClock.cs | 456 +- Virtu/PeripheralCard.cs | 96 +- Virtu/Properties/Strings.Designer.cs | 216 +- Virtu/Properties/Strings.resx | 268 +- Virtu/Services/AudioService.cs | 132 +- Virtu/Services/DebugService.cs | 126 +- Virtu/Services/GamePortService.cs | 278 +- Virtu/Services/IsolatedStorageService.cs | 106 +- Virtu/Services/KeyboardService.cs | 86 +- Virtu/Services/MachineService.cs | 40 +- Virtu/Services/MachineServices.cs | 102 +- Virtu/Services/StorageService.cs | 426 +- Virtu/Services/VideoService.cs | 34 +- .../Jellyfish.Virtu.Silverlight.csproj | 538 +- .../Jellyfish.Virtu.Silverlight.sln | 52 +- Virtu/Silverlight/MainApp.xaml | 22 +- Virtu/Silverlight/MainApp.xaml.cs | 28 +- Virtu/Silverlight/MainPage.xaml | 46 +- Virtu/Silverlight/MainPage.xaml.cs | 174 +- Virtu/Silverlight/Properties/AppManifest.xml | 10 +- Virtu/Silverlight/Properties/AssemblyInfo.cs | 46 +- .../Properties/OutOfBrowserSettings.xml | 28 +- .../Services/SilverlightAudioService.cs | 118 +- .../Services/SilverlightDebugService.cs | 52 +- .../Services/SilverlightKeyboardService.cs | 802 +- .../Services/SilverlightVideoService.cs | 198 +- Virtu/Speaker.cs | 180 +- Virtu/Video.cs | 2300 +++--- Virtu/VideoData.cs | 3288 ++++----- Virtu/Wpf/Jellyfish.Virtu.Wpf.csproj | 498 +- Virtu/Wpf/Jellyfish.Virtu.Wpf.sln | 52 +- Virtu/Wpf/MainApp.xaml | 16 +- Virtu/Wpf/MainApp.xaml.cs | 28 +- Virtu/Wpf/MainPage.xaml | 46 +- Virtu/Wpf/MainPage.xaml.cs | 176 +- Virtu/Wpf/MainWindow.xaml | 14 +- Virtu/Wpf/MainWindow.xaml.cs | 24 +- Virtu/Wpf/Properties/AssemblyInfo.cs | 52 +- Virtu/Wpf/Services/WpfAudioService.cs | 120 +- Virtu/Wpf/Services/WpfDebugService.cs | 52 +- Virtu/Wpf/Services/WpfKeyboardService.cs | 596 +- Virtu/Wpf/Services/WpfStorageService.cs | 38 +- Virtu/Wpf/Services/WpfVideoService.cs | 214 +- 91 files changed, 14835 insertions(+), 14821 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3ce801b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,14 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union + +# Virtu +*.do binary +*.dsk binary +*.nib binary +*.po binary +*.rom binary diff --git a/.gitignore b/.gitignore index 9110376..fd61d2f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ -bin/ -obj/ - -*.cachefile -*.suo -*.user +bin/ +obj/ + +*.cachefile +*.suo +*.user diff --git a/Library/AssemblyMetadataAttribute.cs b/Library/AssemblyMetadataAttribute.cs index e885b60..a2e51e2 100644 --- a/Library/AssemblyMetadataAttribute.cs +++ b/Library/AssemblyMetadataAttribute.cs @@ -1,17 +1,17 @@ -using System; - -namespace Jellyfish.Library -{ - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] - public sealed class AssemblyMetadataAttribute : Attribute - { - public AssemblyMetadataAttribute(string key, string value) - { - Key = key; - Value = value; - } - - public string Key { get; private set; } - public string Value { get; private set; } - } -} +using System; + +namespace Jellyfish.Library +{ + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] + public sealed class AssemblyMetadataAttribute : Attribute + { + public AssemblyMetadataAttribute(string key, string value) + { + Key = key; + Value = value; + } + + public string Key { get; private set; } + public string Value { get; private set; } + } +} diff --git a/Library/CustomDictionary.xml b/Library/CustomDictionary.xml index 8f2033b..fa103c8 100644 --- a/Library/CustomDictionary.xml +++ b/Library/CustomDictionary.xml @@ -1,9 +1,9 @@ - - - - - x - y - - - + + + + + x + y + + + diff --git a/Library/DirectSound.cs b/Library/DirectSound.cs index 23025bf..62856b8 100644 --- a/Library/DirectSound.cs +++ b/Library/DirectSound.cs @@ -1,173 +1,173 @@ -using System; -using System.Runtime.InteropServices; -using System.Security; -using System.Threading; - -namespace Jellyfish.Library -{ - public sealed partial class DirectSound : IDisposable - { - [SecurityCritical] - public DirectSound(int sampleRate, int sampleChannels, int sampleBits, int sampleSize, Action updater) - { - _sampleRate = sampleRate; - _sampleChannels = sampleChannels; - _sampleBits = sampleBits; - _sampleSize = sampleSize; - - _thread = new Thread(Run) { Name = "DirectSound" }; - _updater = updater; - } - - public void Dispose() - { - _position1Event.Close(); - _position2Event.Close(); - _stopEvent.Close(); - } - - public void SetVolume(float volume) - { - int attenuation = (volume < 0.01) ? (int)BufferVolume.Min : (int)Math.Floor(100 * 20 * Math.Log10(volume)); // 100 db - lock (_bufferLock) - { - if (_buffer != null) - { - _buffer.SetVolume(attenuation); - } - } - } - - public void Start(IntPtr window) - { - _window = window; - _thread.Start(); - } - - public void Stop() - { - _stopEvent.Set(); - _thread.Join(); - } - - [SecurityCritical] - private void Initialize() - { - int hresult = NativeMethods.DirectSoundCreate(IntPtr.Zero, out _device, IntPtr.Zero); - if (hresult < 0) - { - Marshal.ThrowExceptionForHR(hresult); - } - - _device.SetCooperativeLevel(_window, CooperativeLevel.Normal); - - GCHandleHelpers.Pin(new WaveFormat(_sampleRate, _sampleChannels, _sampleBits), waveFormat => - { - var description = new BufferDescription(BufferCapabilities.CtrlPositionNotify | BufferCapabilities.CtrlVolume, BlockCount * _sampleSize, waveFormat); - _device.CreateSoundBuffer(description, out _buffer, IntPtr.Zero); - }); - ClearBuffer(); - - var positionEvents = new BufferPositionNotify[BlockCount] - { - new BufferPositionNotify(0 * _sampleSize, _position1Event), new BufferPositionNotify(1 * _sampleSize, _position2Event) - }; - ((IDirectSoundNotify)_buffer).SetNotificationPositions(positionEvents.Length, positionEvents); - - _buffer.Play(0, 0, BufferPlay.Looping); - } - - [SecurityCritical] - private void ClearBuffer() - { - UpdateBuffer(0, 0, BufferLock.EntireBuffer, (buffer, bufferSize) => MarshalHelpers.ZeroMemory(buffer, bufferSize)); - } - - private void RestoreBuffer() - { - BufferStatus status; - _buffer.GetStatus(out status); - if ((status & BufferStatus.BufferLost) != 0) - { - _buffer.Restore(); - } - } - - private void UpdateBuffer(int offset, int count, BufferLock flags, Action updater) - { - RestoreBuffer(); - - IntPtr buffer1, buffer2; - int buffer1Size, buffer2Size; - _buffer.Lock(offset, count, out buffer1, out buffer1Size, out buffer2, out buffer2Size, flags); - try - { - if (buffer1 != IntPtr.Zero) - { - updater(buffer1, buffer1Size); - } - if (buffer2 != IntPtr.Zero) - { - updater(buffer2, buffer2Size); - } - } - finally - { - _buffer.Unlock(buffer1, buffer1Size, buffer2, buffer2Size); - } - } - - private void Uninitialize() - { - lock (_bufferLock) - { - if (_buffer != null) - { - _buffer.Stop(); - Marshal.ReleaseComObject(_buffer); - _buffer = null; - } - } - if (_device != null) - { - Marshal.ReleaseComObject(_device); - _device = null; - } - } - - [SecurityCritical] - private void Run() // com mta thread - { - Initialize(); - - var eventHandles = new EventWaitHandle[] { _position1Event, _position2Event, _stopEvent }; - int index = WaitHandle.WaitAny(eventHandles); - - while (index < BlockCount) - { - UpdateBuffer(((index + 1) % BlockCount) * _sampleSize, _sampleSize, BufferLock.None, _updater); // update next block in circular buffer - index = WaitHandle.WaitAny(eventHandles); - } - - Uninitialize(); - } - - private const int BlockCount = 2; - - private int _sampleRate; - private int _sampleChannels; - private int _sampleBits; - private int _sampleSize; - - private Thread _thread; - private IntPtr _window; - private IDirectSound _device; - private IDirectSoundBuffer _buffer; - private readonly object _bufferLock = new object(); - private Action _updater; - - private AutoResetEvent _position1Event = new AutoResetEvent(false); - private AutoResetEvent _position2Event = new AutoResetEvent(false); - private ManualResetEvent _stopEvent = new ManualResetEvent(false); - } -} +using System; +using System.Runtime.InteropServices; +using System.Security; +using System.Threading; + +namespace Jellyfish.Library +{ + public sealed partial class DirectSound : IDisposable + { + [SecurityCritical] + public DirectSound(int sampleRate, int sampleChannels, int sampleBits, int sampleSize, Action updater) + { + _sampleRate = sampleRate; + _sampleChannels = sampleChannels; + _sampleBits = sampleBits; + _sampleSize = sampleSize; + + _thread = new Thread(Run) { Name = "DirectSound" }; + _updater = updater; + } + + public void Dispose() + { + _position1Event.Close(); + _position2Event.Close(); + _stopEvent.Close(); + } + + public void SetVolume(float volume) + { + int attenuation = (volume < 0.01) ? (int)BufferVolume.Min : (int)Math.Floor(100 * 20 * Math.Log10(volume)); // 100 db + lock (_bufferLock) + { + if (_buffer != null) + { + _buffer.SetVolume(attenuation); + } + } + } + + public void Start(IntPtr window) + { + _window = window; + _thread.Start(); + } + + public void Stop() + { + _stopEvent.Set(); + _thread.Join(); + } + + [SecurityCritical] + private void Initialize() + { + int hresult = NativeMethods.DirectSoundCreate(IntPtr.Zero, out _device, IntPtr.Zero); + if (hresult < 0) + { + Marshal.ThrowExceptionForHR(hresult); + } + + _device.SetCooperativeLevel(_window, CooperativeLevel.Normal); + + GCHandleHelpers.Pin(new WaveFormat(_sampleRate, _sampleChannels, _sampleBits), waveFormat => + { + var description = new BufferDescription(BufferCapabilities.CtrlPositionNotify | BufferCapabilities.CtrlVolume, BlockCount * _sampleSize, waveFormat); + _device.CreateSoundBuffer(description, out _buffer, IntPtr.Zero); + }); + ClearBuffer(); + + var positionEvents = new BufferPositionNotify[BlockCount] + { + new BufferPositionNotify(0 * _sampleSize, _position1Event), new BufferPositionNotify(1 * _sampleSize, _position2Event) + }; + ((IDirectSoundNotify)_buffer).SetNotificationPositions(positionEvents.Length, positionEvents); + + _buffer.Play(0, 0, BufferPlay.Looping); + } + + [SecurityCritical] + private void ClearBuffer() + { + UpdateBuffer(0, 0, BufferLock.EntireBuffer, (buffer, bufferSize) => MarshalHelpers.ZeroMemory(buffer, bufferSize)); + } + + private void RestoreBuffer() + { + BufferStatus status; + _buffer.GetStatus(out status); + if ((status & BufferStatus.BufferLost) != 0) + { + _buffer.Restore(); + } + } + + private void UpdateBuffer(int offset, int count, BufferLock flags, Action updater) + { + RestoreBuffer(); + + IntPtr buffer1, buffer2; + int buffer1Size, buffer2Size; + _buffer.Lock(offset, count, out buffer1, out buffer1Size, out buffer2, out buffer2Size, flags); + try + { + if (buffer1 != IntPtr.Zero) + { + updater(buffer1, buffer1Size); + } + if (buffer2 != IntPtr.Zero) + { + updater(buffer2, buffer2Size); + } + } + finally + { + _buffer.Unlock(buffer1, buffer1Size, buffer2, buffer2Size); + } + } + + private void Uninitialize() + { + lock (_bufferLock) + { + if (_buffer != null) + { + _buffer.Stop(); + Marshal.ReleaseComObject(_buffer); + _buffer = null; + } + } + if (_device != null) + { + Marshal.ReleaseComObject(_device); + _device = null; + } + } + + [SecurityCritical] + private void Run() // com mta thread + { + Initialize(); + + var eventHandles = new EventWaitHandle[] { _position1Event, _position2Event, _stopEvent }; + int index = WaitHandle.WaitAny(eventHandles); + + while (index < BlockCount) + { + UpdateBuffer(((index + 1) % BlockCount) * _sampleSize, _sampleSize, BufferLock.None, _updater); // update next block in circular buffer + index = WaitHandle.WaitAny(eventHandles); + } + + Uninitialize(); + } + + private const int BlockCount = 2; + + private int _sampleRate; + private int _sampleChannels; + private int _sampleBits; + private int _sampleSize; + + private Thread _thread; + private IntPtr _window; + private IDirectSound _device; + private IDirectSoundBuffer _buffer; + private readonly object _bufferLock = new object(); + private Action _updater; + + private AutoResetEvent _position1Event = new AutoResetEvent(false); + private AutoResetEvent _position2Event = new AutoResetEvent(false); + private ManualResetEvent _stopEvent = new ManualResetEvent(false); + } +} diff --git a/Library/DirectSoundInterop.cs b/Library/DirectSoundInterop.cs index 455a4fb..275b5e4 100644 --- a/Library/DirectSoundInterop.cs +++ b/Library/DirectSoundInterop.cs @@ -1,110 +1,110 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; -using System.Security; -using System.Threading; - -namespace Jellyfish.Library -{ - public sealed partial class DirectSound - { - [Flags] - private enum BufferCapabilities { PrimaryBuffer = 0x00000001, CtrlVolume = 0x00000080, CtrlPositionNotify = 0x00000100, StickyFocus = 0x00004000, GlobalFocus = 0x00008000 } - - [Flags] - private enum BufferLock { None = 0x00000000, FromWriteCursor = 0x00000001, EntireBuffer = 0x00000002 } - - [Flags] - private enum BufferPlay { Looping = 0x00000001 } - - [Flags] - private enum BufferStatus { Playing = 0x00000001, BufferLost = 0x00000002, Looping = 0x00000004, Terminated = 0x00000020 } - - private enum BufferVolume { Min = -10000, Max = 0 } - - private enum CooperativeLevel { Normal = 1, Priority = 2 } - - [StructLayout(LayoutKind.Sequential)] - private sealed class BufferDescription - { - public BufferDescription(BufferCapabilities capabilities, int size, IntPtr format) - { - dwSize = Marshal.SizeOf(typeof(BufferDescription)); - dwFlags = capabilities; - dwBufferBytes = size; - lpwfxFormat = format; - } - - public int dwSize; - public BufferCapabilities dwFlags; - public int dwBufferBytes; - public int dwReserved; - public IntPtr lpwfxFormat; - public Guid guid3DAlgorithm; - } - - [StructLayout(LayoutKind.Sequential)] - private struct BufferPositionNotify - { - [SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Runtime.InteropServices.SafeHandle.DangerousGetHandle")] - public BufferPositionNotify(int offset, EventWaitHandle notifyEvent) - { - dwOffset = offset; - hEventNotify = notifyEvent.SafeWaitHandle.DangerousGetHandle(); - } - - public int dwOffset; - public IntPtr hEventNotify; - } - - [ComImport, Guid("279AFA83-4981-11CE-A521-0020AF0BE560"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - private interface IDirectSound - { - void CreateSoundBuffer(BufferDescription pcDSBufferDesc, [MarshalAs(UnmanagedType.Interface)] out IDirectSoundBuffer pDSBuffer, IntPtr pUnkOuter); - void GetCaps(IntPtr pDSCaps); - void DuplicateSoundBuffer([MarshalAs(UnmanagedType.Interface)] IDirectSoundBuffer pDSBufferOriginal, [MarshalAs(UnmanagedType.Interface)] out IDirectSoundBuffer pDSBufferDuplicate); - void SetCooperativeLevel(IntPtr hwnd, CooperativeLevel dwLevel); - void Compact(); - void GetSpeakerConfig(out int dwSpeakerConfig); - void SetSpeakerConfig(int dwSpeakerConfig); - void Initialize([MarshalAs(UnmanagedType.LPStruct)] Guid pcGuidDevice); - } - - [ComImport, Guid("279AFA85-4981-11CE-A521-0020AF0BE560"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - private interface IDirectSoundBuffer - { - void GetCaps(IntPtr pDSBufferCaps); - void GetCurrentPosition(out int dwCurrentPlayCursor, out int dwCurrentWriteCursor); - void GetFormat(IntPtr pwfxFormat, int dwSizeAllocated, out int dwSizeWritten); - void GetVolume(out int lVolume); - void GetPan(out int lPan); - void GetFrequency(out int dwFrequency); - void GetStatus(out BufferStatus dwStatus); - void Initialize([MarshalAs(UnmanagedType.Interface)] IDirectSound pDirectSound, BufferDescription pcDSBufferDesc); - void Lock(int dwOffset, int dwBytes, out IntPtr pvAudioPtr1, out int dwAudioBytes1, out IntPtr pvAudioPtr2, out int dwAudioBytes2, BufferLock dwFlags); - void Play(int dwReserved1, int dwPriority, BufferPlay dwFlags); - void SetCurrentPosition(int dwNewPosition); - void SetFormat(WaveFormat pcfxFormat); - void SetVolume(int lVolume); - void SetPan(int lPan); - void SetFrequency(int dwFrequency); - void Stop(); - void Unlock(IntPtr pvAudioPtr1, int dwAudioBytes1, IntPtr pvAudioPtr2, int dwAudioBytes2); - void Restore(); - } - - [ComImport, Guid("B0210783-89CD-11D0-AF08-00A0C925CD16"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - private interface IDirectSoundNotify - { - void SetNotificationPositions(int dwPositionNotifies, [MarshalAs(UnmanagedType.LPArray)] BufferPositionNotify[] pcPositionNotifies); - } - - [SecurityCritical] - [SuppressUnmanagedCodeSecurity] - private static class NativeMethods - { - [DllImport("dsound.dll")] - public static extern int DirectSoundCreate(IntPtr pcGuidDevice, [MarshalAs(UnmanagedType.Interface)] out IDirectSound pDS, IntPtr pUnkOuter); - } - } -} +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using System.Security; +using System.Threading; + +namespace Jellyfish.Library +{ + public sealed partial class DirectSound + { + [Flags] + private enum BufferCapabilities { PrimaryBuffer = 0x00000001, CtrlVolume = 0x00000080, CtrlPositionNotify = 0x00000100, StickyFocus = 0x00004000, GlobalFocus = 0x00008000 } + + [Flags] + private enum BufferLock { None = 0x00000000, FromWriteCursor = 0x00000001, EntireBuffer = 0x00000002 } + + [Flags] + private enum BufferPlay { Looping = 0x00000001 } + + [Flags] + private enum BufferStatus { Playing = 0x00000001, BufferLost = 0x00000002, Looping = 0x00000004, Terminated = 0x00000020 } + + private enum BufferVolume { Min = -10000, Max = 0 } + + private enum CooperativeLevel { Normal = 1, Priority = 2 } + + [StructLayout(LayoutKind.Sequential)] + private sealed class BufferDescription + { + public BufferDescription(BufferCapabilities capabilities, int size, IntPtr format) + { + dwSize = Marshal.SizeOf(typeof(BufferDescription)); + dwFlags = capabilities; + dwBufferBytes = size; + lpwfxFormat = format; + } + + public int dwSize; + public BufferCapabilities dwFlags; + public int dwBufferBytes; + public int dwReserved; + public IntPtr lpwfxFormat; + public Guid guid3DAlgorithm; + } + + [StructLayout(LayoutKind.Sequential)] + private struct BufferPositionNotify + { + [SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Runtime.InteropServices.SafeHandle.DangerousGetHandle")] + public BufferPositionNotify(int offset, EventWaitHandle notifyEvent) + { + dwOffset = offset; + hEventNotify = notifyEvent.SafeWaitHandle.DangerousGetHandle(); + } + + public int dwOffset; + public IntPtr hEventNotify; + } + + [ComImport, Guid("279AFA83-4981-11CE-A521-0020AF0BE560"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface IDirectSound + { + void CreateSoundBuffer(BufferDescription pcDSBufferDesc, [MarshalAs(UnmanagedType.Interface)] out IDirectSoundBuffer pDSBuffer, IntPtr pUnkOuter); + void GetCaps(IntPtr pDSCaps); + void DuplicateSoundBuffer([MarshalAs(UnmanagedType.Interface)] IDirectSoundBuffer pDSBufferOriginal, [MarshalAs(UnmanagedType.Interface)] out IDirectSoundBuffer pDSBufferDuplicate); + void SetCooperativeLevel(IntPtr hwnd, CooperativeLevel dwLevel); + void Compact(); + void GetSpeakerConfig(out int dwSpeakerConfig); + void SetSpeakerConfig(int dwSpeakerConfig); + void Initialize([MarshalAs(UnmanagedType.LPStruct)] Guid pcGuidDevice); + } + + [ComImport, Guid("279AFA85-4981-11CE-A521-0020AF0BE560"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface IDirectSoundBuffer + { + void GetCaps(IntPtr pDSBufferCaps); + void GetCurrentPosition(out int dwCurrentPlayCursor, out int dwCurrentWriteCursor); + void GetFormat(IntPtr pwfxFormat, int dwSizeAllocated, out int dwSizeWritten); + void GetVolume(out int lVolume); + void GetPan(out int lPan); + void GetFrequency(out int dwFrequency); + void GetStatus(out BufferStatus dwStatus); + void Initialize([MarshalAs(UnmanagedType.Interface)] IDirectSound pDirectSound, BufferDescription pcDSBufferDesc); + void Lock(int dwOffset, int dwBytes, out IntPtr pvAudioPtr1, out int dwAudioBytes1, out IntPtr pvAudioPtr2, out int dwAudioBytes2, BufferLock dwFlags); + void Play(int dwReserved1, int dwPriority, BufferPlay dwFlags); + void SetCurrentPosition(int dwNewPosition); + void SetFormat(WaveFormat pcfxFormat); + void SetVolume(int lVolume); + void SetPan(int lPan); + void SetFrequency(int dwFrequency); + void Stop(); + void Unlock(IntPtr pvAudioPtr1, int dwAudioBytes1, IntPtr pvAudioPtr2, int dwAudioBytes2); + void Restore(); + } + + [ComImport, Guid("B0210783-89CD-11D0-AF08-00A0C925CD16"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface IDirectSoundNotify + { + void SetNotificationPositions(int dwPositionNotifies, [MarshalAs(UnmanagedType.LPArray)] BufferPositionNotify[] pcPositionNotifies); + } + + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + private static class NativeMethods + { + [DllImport("dsound.dll")] + public static extern int DirectSoundCreate(IntPtr pcGuidDevice, [MarshalAs(UnmanagedType.Interface)] out IDirectSound pDS, IntPtr pUnkOuter); + } + } +} diff --git a/Library/DispatcherExtensions.cs b/Library/DispatcherExtensions.cs index 0c3fdc0..af497b8 100644 --- a/Library/DispatcherExtensions.cs +++ b/Library/DispatcherExtensions.cs @@ -1,36 +1,36 @@ -using System; -using System.Windows.Threading; - -namespace Jellyfish.Library -{ - public static class DispatcherExtensions - { - public static void Post(this Dispatcher dispatcher, Action action) - { - if (dispatcher == null) - { - throw new ArgumentNullException("dispatcher"); - } - if (action == null) - { - throw new ArgumentNullException("action"); - } - - new DispatcherSynchronizationContext(dispatcher).Post(state => action(), null); - } - - public static void Send(this Dispatcher dispatcher, Action action) - { - if (dispatcher == null) - { - throw new ArgumentNullException("dispatcher"); - } - if (action == null) - { - throw new ArgumentNullException("action"); - } - - new DispatcherSynchronizationContext(dispatcher).Send(state => action(), null); - } - } -} +using System; +using System.Windows.Threading; + +namespace Jellyfish.Library +{ + public static class DispatcherExtensions + { + public static void Post(this Dispatcher dispatcher, Action action) + { + if (dispatcher == null) + { + throw new ArgumentNullException("dispatcher"); + } + if (action == null) + { + throw new ArgumentNullException("action"); + } + + new DispatcherSynchronizationContext(dispatcher).Post(state => action(), null); + } + + public static void Send(this Dispatcher dispatcher, Action action) + { + if (dispatcher == null) + { + throw new ArgumentNullException("dispatcher"); + } + if (action == null) + { + throw new ArgumentNullException("action"); + } + + new DispatcherSynchronizationContext(dispatcher).Send(state => action(), null); + } + } +} diff --git a/Library/DisposableBase.cs b/Library/DisposableBase.cs index 5b9309e..59cee1d 100644 --- a/Library/DisposableBase.cs +++ b/Library/DisposableBase.cs @@ -1,26 +1,26 @@ -using System; - -namespace Jellyfish.Library -{ - public abstract class DisposableBase : IDisposable - { - protected DisposableBase() - { - } - - ~DisposableBase() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - } - } -} +using System; + +namespace Jellyfish.Library +{ + public abstract class DisposableBase : IDisposable + { + protected DisposableBase() + { + } + + ~DisposableBase() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + } + } +} diff --git a/Library/FrameRateCounter.xaml b/Library/FrameRateCounter.xaml index 3064c94..86d9bc9 100644 --- a/Library/FrameRateCounter.xaml +++ b/Library/FrameRateCounter.xaml @@ -1,9 +1,9 @@ - - - - - - - + + + + + + + diff --git a/Library/FrameRateCounter.xaml.cs b/Library/FrameRateCounter.xaml.cs index 3a91b3d..1ccf20d 100644 --- a/Library/FrameRateCounter.xaml.cs +++ b/Library/FrameRateCounter.xaml.cs @@ -1,42 +1,42 @@ -using System; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; - -namespace Jellyfish.Library -{ - public sealed partial class FrameRateCounter : UserControl - { - public FrameRateCounter() - { - InitializeComponent(); - - CompositionTarget.Rendering += OnCompositionTargetRendering; - } - - private void OnCompositionTargetRendering(object sender, EventArgs e) - { - _frameCount++; - - long time = DateTime.UtcNow.Ticks; - if (time - _lastTime >= TimeSpan.TicksPerSecond) - { - _lastTime = time; - FrameRate = _frameCount; - _frameCount = 0; - } - } - - public static readonly DependencyProperty FrameRateProperty = DependencyProperty.Register("FrameRate", typeof(int), typeof(FrameRateCounter), - new PropertyMetadata(0)); - - public int FrameRate - { - get { return (int)GetValue(FrameRateProperty); } - set { SetValue(FrameRateProperty, value); } - } - - private int _frameCount; - private long _lastTime; - } -} +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; + +namespace Jellyfish.Library +{ + public sealed partial class FrameRateCounter : UserControl + { + public FrameRateCounter() + { + InitializeComponent(); + + CompositionTarget.Rendering += OnCompositionTargetRendering; + } + + private void OnCompositionTargetRendering(object sender, EventArgs e) + { + _frameCount++; + + long time = DateTime.UtcNow.Ticks; + if (time - _lastTime >= TimeSpan.TicksPerSecond) + { + _lastTime = time; + FrameRate = _frameCount; + _frameCount = 0; + } + } + + public static readonly DependencyProperty FrameRateProperty = DependencyProperty.Register("FrameRate", typeof(int), typeof(FrameRateCounter), + new PropertyMetadata(0)); + + public int FrameRate + { + get { return (int)GetValue(FrameRateProperty); } + set { SetValue(FrameRateProperty, value); } + } + + private int _frameCount; + private long _lastTime; + } +} diff --git a/Library/GCHandleHelpers.cs b/Library/GCHandleHelpers.cs index 75f02e0..abd9c5c 100644 --- a/Library/GCHandleHelpers.cs +++ b/Library/GCHandleHelpers.cs @@ -1,32 +1,32 @@ -using System; -using System.Runtime.InteropServices; -using System.Security; - -namespace Jellyfish.Library -{ - public static class GCHandleHelpers - { - [SecurityCritical] - public static void Pin(object value, Action action) - { - if (action == null) - { - throw new ArgumentNullException("action"); - } - - var gcHandle = new GCHandle(); - try - { - gcHandle = GCHandle.Alloc(value, GCHandleType.Pinned); - action(gcHandle.AddrOfPinnedObject()); - } - finally - { - if (gcHandle.IsAllocated) - { - gcHandle.Free(); - } - } - } - } -} +using System; +using System.Runtime.InteropServices; +using System.Security; + +namespace Jellyfish.Library +{ + public static class GCHandleHelpers + { + [SecurityCritical] + public static void Pin(object value, Action action) + { + if (action == null) + { + throw new ArgumentNullException("action"); + } + + var gcHandle = new GCHandle(); + try + { + gcHandle = GCHandle.Alloc(value, GCHandleType.Pinned); + action(gcHandle.AddrOfPinnedObject()); + } + finally + { + if (gcHandle.IsAllocated) + { + gcHandle.Free(); + } + } + } + } +} diff --git a/Library/GlobalSuppressions.cs b/Library/GlobalSuppressions.cs index 22ad926..ba618f6 100644 --- a/Library/GlobalSuppressions.cs +++ b/Library/GlobalSuppressions.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; - -[assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")] -[assembly: SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Scope = "member", Target = "Jellyfish.Library.FrameRateCounter.#frameRateControl")] +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")] +[assembly: SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Scope = "member", Target = "Jellyfish.Library.FrameRateCounter.#frameRateControl")] diff --git a/Library/IEnumerableExtensions.cs b/Library/IEnumerableExtensions.cs index 2b1bb46..764ee74 100644 --- a/Library/IEnumerableExtensions.cs +++ b/Library/IEnumerableExtensions.cs @@ -1,25 +1,25 @@ -using System; -using System.Collections.Generic; - -namespace Jellyfish.Library -{ - public static class IEnumerableExtensions - { - public static void ForEach(this IEnumerable source, Action action) - { - if (source == null) - { - throw new ArgumentNullException("source"); - } - if (action == null) - { - throw new ArgumentNullException("action"); - } - - foreach (T item in source) - { - action(item); - } - } - } -} +using System; +using System.Collections.Generic; + +namespace Jellyfish.Library +{ + public static class IEnumerableExtensions + { + public static void ForEach(this IEnumerable source, Action action) + { + if (source == null) + { + throw new ArgumentNullException("source"); + } + if (action == null) + { + throw new ArgumentNullException("action"); + } + + foreach (T item in source) + { + action(item); + } + } + } +} diff --git a/Library/Jellyfish.Library.sln b/Library/Jellyfish.Library.sln index 29538dd..acbf445 100644 --- a/Library/Jellyfish.Library.sln +++ b/Library/Jellyfish.Library.sln @@ -1,26 +1,26 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Library.Silverlight", "Silverlight\Jellyfish.Library.Silverlight.csproj", "{99CA7796-B72A-4F8C-BCDB-0D688220A331}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Library.Wpf", "Wpf\Jellyfish.Library.Wpf.csproj", "{93900841-7250-4D3A-837E-43EE3FD118DC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {93900841-7250-4D3A-837E-43EE3FD118DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {93900841-7250-4D3A-837E-43EE3FD118DC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {93900841-7250-4D3A-837E-43EE3FD118DC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {93900841-7250-4D3A-837E-43EE3FD118DC}.Release|Any CPU.Build.0 = Release|Any CPU - {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Debug|Any CPU.Build.0 = Debug|Any CPU - {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Release|Any CPU.ActiveCfg = Release|Any CPU - {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Library.Silverlight", "Silverlight\Jellyfish.Library.Silverlight.csproj", "{99CA7796-B72A-4F8C-BCDB-0D688220A331}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Library.Wpf", "Wpf\Jellyfish.Library.Wpf.csproj", "{93900841-7250-4D3A-837E-43EE3FD118DC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {93900841-7250-4D3A-837E-43EE3FD118DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {93900841-7250-4D3A-837E-43EE3FD118DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {93900841-7250-4D3A-837E-43EE3FD118DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {93900841-7250-4D3A-837E-43EE3FD118DC}.Release|Any CPU.Build.0 = Release|Any CPU + {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Debug|Any CPU.Build.0 = Debug|Any CPU + {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Release|Any CPU.ActiveCfg = Release|Any CPU + {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Library/MarshalHelpers.cs b/Library/MarshalHelpers.cs index eba5394..2e4beed 100644 --- a/Library/MarshalHelpers.cs +++ b/Library/MarshalHelpers.cs @@ -1,35 +1,35 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; -using System.Security; - -namespace Jellyfish.Library -{ - public static class MarshalHelpers - { - [SecurityCritical] - public static void FillMemory(IntPtr buffer, int bufferSize, byte value) - { - NativeMethods.FillMemory(buffer, (IntPtr)bufferSize, value); - } - - [SecurityCritical] - public static void ZeroMemory(IntPtr buffer, int bufferSize) - { - NativeMethods.ZeroMemory(buffer, (IntPtr)bufferSize); - } - - [SecurityCritical] - [SuppressUnmanagedCodeSecurity] - private static class NativeMethods - { - [SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")] - [DllImport("kernel32.dll", SetLastError = true)] - public static extern void FillMemory(IntPtr destination, IntPtr length, byte fill); - - [SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")] - [DllImport("kernel32.dll", SetLastError = true)] - public static extern void ZeroMemory(IntPtr destination, IntPtr length); - } - } -} +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using System.Security; + +namespace Jellyfish.Library +{ + public static class MarshalHelpers + { + [SecurityCritical] + public static void FillMemory(IntPtr buffer, int bufferSize, byte value) + { + NativeMethods.FillMemory(buffer, (IntPtr)bufferSize, value); + } + + [SecurityCritical] + public static void ZeroMemory(IntPtr buffer, int bufferSize) + { + NativeMethods.ZeroMemory(buffer, (IntPtr)bufferSize); + } + + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + private static class NativeMethods + { + [SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")] + [DllImport("kernel32.dll", SetLastError = true)] + public static extern void FillMemory(IntPtr destination, IntPtr length, byte fill); + + [SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")] + [DllImport("kernel32.dll", SetLastError = true)] + public static extern void ZeroMemory(IntPtr destination, IntPtr length); + } + } +} diff --git a/Library/MathHelpers.cs b/Library/MathHelpers.cs index 3c31801..6ea1a70 100644 --- a/Library/MathHelpers.cs +++ b/Library/MathHelpers.cs @@ -1,15 +1,15 @@ -namespace Jellyfish.Library -{ - public static class MathHelpers - { - public static int Clamp(int value, int min, int max) - { - return (value < min) ? min : (value > max) ? max : value; - } - - public static int ClampByte(int value) - { - return Clamp(value, byte.MinValue, byte.MaxValue); - } - } -} +namespace Jellyfish.Library +{ + public static class MathHelpers + { + public static int Clamp(int value, int min, int max) + { + return (value < min) ? min : (value > max) ? max : value; + } + + public static int ClampByte(int value) + { + return Clamp(value, byte.MinValue, byte.MaxValue); + } + } +} diff --git a/Library/Silverlight/ApplicationBase.cs b/Library/Silverlight/ApplicationBase.cs index d1c085c..4dc648a 100644 --- a/Library/Silverlight/ApplicationBase.cs +++ b/Library/Silverlight/ApplicationBase.cs @@ -1,95 +1,95 @@ -using System; -using System.Diagnostics; -using System.Text; -using System.Windows; - -namespace Jellyfish.Library -{ - public abstract class ApplicationBase : Application - { - protected ApplicationBase() : - this(null) - { - } - - protected ApplicationBase(string name) - { - Name = name; - - UnhandledException += OnApplicationUnhandledException; - //AppDomain.CurrentDomain.UnhandledException += OnAppDomainUnhandledException; - - if (Debugger.IsAttached) - { - var settings = Application.Current.Host.Settings; - settings.EnableFrameRateCounter = true; - //settings.EnableRedrawRegions = true; - //settings.EnableCacheVisualization = true; - } - } - - protected void InitializeOutOfBrowserUpdate() - { - if (IsRunningOutOfBrowser) - { - CheckAndDownloadUpdateCompleted += OnApplicationCheckAndDownloadUpdateCompleted; - CheckAndDownloadUpdateAsync(); - } - } - - private string GetExceptionCaption(string title, bool isTerminating = false) - { - var caption = new StringBuilder(); - if (!string.IsNullOrEmpty(Name)) - { - caption.Append(Name).Append(' '); - } - caption.Append(title); - if (isTerminating) - { - caption.Append(" (Terminating)"); - } - - return caption.ToString(); - } - - private void OnApplicationCheckAndDownloadUpdateCompleted(object sender, CheckAndDownloadUpdateCompletedEventArgs e) - { - if (e.Error != null) - { - if (e.Error is PlatformNotSupportedException) - { - MessageBox.Show("An application update is available, but it requires the latest version of Silverlight."); - } - //else if (Debugger.IsAttached) - //{ - // Debugger.Break(); - //} - } - else if (e.UpdateAvailable) - { - MessageBox.Show("An application update was downloaded. Restart the application to run the latest version."); - } - } - - private void OnApplicationUnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) - { - MessageBox.Show(e.ExceptionObject.ToString(), GetExceptionCaption("Application Exception"), MessageBoxButton.OK); - if (Debugger.IsAttached) - { - Debugger.Break(); - } - } - - //private void OnAppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e) - //{ - // MessageBox.Show(e.ExceptionObject.ToString(), GetExceptionCaption("AppDomain Exception", e.IsTerminating), MessageBoxButton.OK); - // if (Debugger.IsAttached) - // { - // Debugger.Break(); - // } - //} - - public string Name { get; private set; } - } -} +using System; +using System.Diagnostics; +using System.Text; +using System.Windows; + +namespace Jellyfish.Library +{ + public abstract class ApplicationBase : Application + { + protected ApplicationBase() : + this(null) + { + } + + protected ApplicationBase(string name) + { + Name = name; + + UnhandledException += OnApplicationUnhandledException; + //AppDomain.CurrentDomain.UnhandledException += OnAppDomainUnhandledException; + + if (Debugger.IsAttached) + { + var settings = Application.Current.Host.Settings; + settings.EnableFrameRateCounter = true; + //settings.EnableRedrawRegions = true; + //settings.EnableCacheVisualization = true; + } + } + + protected void InitializeOutOfBrowserUpdate() + { + if (IsRunningOutOfBrowser) + { + CheckAndDownloadUpdateCompleted += OnApplicationCheckAndDownloadUpdateCompleted; + CheckAndDownloadUpdateAsync(); + } + } + + private string GetExceptionCaption(string title, bool isTerminating = false) + { + var caption = new StringBuilder(); + if (!string.IsNullOrEmpty(Name)) + { + caption.Append(Name).Append(' '); + } + caption.Append(title); + if (isTerminating) + { + caption.Append(" (Terminating)"); + } + + return caption.ToString(); + } + + private void OnApplicationCheckAndDownloadUpdateCompleted(object sender, CheckAndDownloadUpdateCompletedEventArgs e) + { + if (e.Error != null) + { + if (e.Error is PlatformNotSupportedException) + { + MessageBox.Show("An application update is available, but it requires the latest version of Silverlight."); + } + //else if (Debugger.IsAttached) + //{ + // Debugger.Break(); + //} + } + else if (e.UpdateAvailable) + { + MessageBox.Show("An application update was downloaded. Restart the application to run the latest version."); + } + } + + private void OnApplicationUnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) + { + MessageBox.Show(e.ExceptionObject.ToString(), GetExceptionCaption("Application Exception"), MessageBoxButton.OK); + if (Debugger.IsAttached) + { + Debugger.Break(); + } + } + + //private void OnAppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e) + //{ + // MessageBox.Show(e.ExceptionObject.ToString(), GetExceptionCaption("AppDomain Exception", e.IsTerminating), MessageBoxButton.OK); + // if (Debugger.IsAttached) + // { + // Debugger.Break(); + // } + //} + + public string Name { get; private set; } + } +} diff --git a/Library/Silverlight/Jellyfish.Library.Silverlight.csproj b/Library/Silverlight/Jellyfish.Library.Silverlight.csproj index 87eaadb..3412905 100644 --- a/Library/Silverlight/Jellyfish.Library.Silverlight.csproj +++ b/Library/Silverlight/Jellyfish.Library.Silverlight.csproj @@ -1,133 +1,133 @@ - - - - Debug - AnyCPU - 8.0.50727 - 2.0 - {99CA7796-B72A-4F8C-BCDB-0D688220A331} - {A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - Jellyfish.Library - Jellyfish.Library - Silverlight - v5.0 - - $(TargetFrameworkVersion) - false - true - true - - - - v3.5 - - - true - full - false - bin\ - DEBUG;TRACE;SILVERLIGHT;CODE_ANALYSIS - true - true - prompt - 4 - true - AllRules.ruleset - false - - - pdbonly - true - bin\ - TRACE;SILVERLIGHT;CODE_ANALYSIS - true - true - prompt - 4 - true - AllRules.ruleset - false - - - false - - - ..\..\..\Jellyfish\StrongName.snk - - - - - - - - - - - - - AssemblyMetadataAttribute.cs - - - DispatcherExtensions.cs - - - DisposableBase.cs - - - FrameRateCounter.xaml.cs - FrameRateCounter.xaml - - - GlobalSuppressions.cs - - - IEnumerableExtensions.cs - - - MathHelpers.cs - - - StreamExtensions.cs - - - StringBuilderExtensions.cs - - - WaveFormat.cs - - - - - - - - FrameRateCounter.xaml - MSBuild:Compile - Designer - - - - - CustomDictionary.xml - - - - - - - - - - - + + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {99CA7796-B72A-4F8C-BCDB-0D688220A331} + {A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Jellyfish.Library + Jellyfish.Library + Silverlight + v5.0 + + $(TargetFrameworkVersion) + false + true + true + + + + v3.5 + + + true + full + false + bin\ + DEBUG;TRACE;SILVERLIGHT;CODE_ANALYSIS + true + true + prompt + 4 + true + AllRules.ruleset + false + + + pdbonly + true + bin\ + TRACE;SILVERLIGHT;CODE_ANALYSIS + true + true + prompt + 4 + true + AllRules.ruleset + false + + + false + + + ..\..\..\Jellyfish\StrongName.snk + + + + + + + + + + + + + AssemblyMetadataAttribute.cs + + + DispatcherExtensions.cs + + + DisposableBase.cs + + + FrameRateCounter.xaml.cs + FrameRateCounter.xaml + + + GlobalSuppressions.cs + + + IEnumerableExtensions.cs + + + MathHelpers.cs + + + StreamExtensions.cs + + + StringBuilderExtensions.cs + + + WaveFormat.cs + + + + + + + + FrameRateCounter.xaml + MSBuild:Compile + Designer + + + + + CustomDictionary.xml + + + + + + + + + + + \ No newline at end of file diff --git a/Library/Silverlight/Jellyfish.Library.Silverlight.sln b/Library/Silverlight/Jellyfish.Library.Silverlight.sln index 4c4bae8..9bfc558 100644 --- a/Library/Silverlight/Jellyfish.Library.Silverlight.sln +++ b/Library/Silverlight/Jellyfish.Library.Silverlight.sln @@ -1,20 +1,20 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Library.Silverlight", "Jellyfish.Library.Silverlight.csproj", "{99CA7796-B72A-4F8C-BCDB-0D688220A331}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Debug|Any CPU.Build.0 = Debug|Any CPU - {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Release|Any CPU.ActiveCfg = Release|Any CPU - {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Library.Silverlight", "Jellyfish.Library.Silverlight.csproj", "{99CA7796-B72A-4F8C-BCDB-0D688220A331}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Debug|Any CPU.Build.0 = Debug|Any CPU + {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Release|Any CPU.ActiveCfg = Release|Any CPU + {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Library/Silverlight/Properties/AssemblyInfo.cs b/Library/Silverlight/Properties/AssemblyInfo.cs index 3e6b2b3..cd28e21 100644 --- a/Library/Silverlight/Properties/AssemblyInfo.cs +++ b/Library/Silverlight/Properties/AssemblyInfo.cs @@ -1,22 +1,22 @@ -using System; -using System.Reflection; -using System.Resources; -using System.Runtime.InteropServices; -using Jellyfish.Library; - -[assembly: AssemblyTitle("Library")] -[assembly: AssemblyDescription("Common Library")] -[assembly: AssemblyProduct("Jellyfish.Library.Silverlight")] -[assembly: AssemblyCompany("Digital Jellyfish Design Ltd")] -[assembly: AssemblyCopyright("Copyright © 2009-2012 Digital Jellyfish Design Ltd")] -[assembly: AssemblyMetadata("Developer", "Sean Fausett")] - -[assembly: AssemblyVersion("0.4.0.0")] -[assembly: AssemblyFileVersion("0.4.0.0")] -[assembly: AssemblyInformationalVersion("0.4.0.0")] - -[assembly: CLSCompliant(false)] -[assembly: ComVisible(false)] -[assembly: Guid("66034b9e-9f0b-47b0-aac4-cade9a748891")] - -[assembly: NeutralResourcesLanguage("en")] +using System; +using System.Reflection; +using System.Resources; +using System.Runtime.InteropServices; +using Jellyfish.Library; + +[assembly: AssemblyTitle("Library")] +[assembly: AssemblyDescription("Common Library")] +[assembly: AssemblyProduct("Jellyfish.Library.Silverlight")] +[assembly: AssemblyCompany("Digital Jellyfish Design Ltd")] +[assembly: AssemblyCopyright("Copyright © 2009-2012 Digital Jellyfish Design Ltd")] +[assembly: AssemblyMetadata("Developer", "Sean Fausett")] + +[assembly: AssemblyVersion("0.4.0.0")] +[assembly: AssemblyFileVersion("0.4.0.0")] +[assembly: AssemblyInformationalVersion("0.4.0.0")] + +[assembly: CLSCompliant(false)] +[assembly: ComVisible(false)] +[assembly: Guid("66034b9e-9f0b-47b0-aac4-cade9a748891")] + +[assembly: NeutralResourcesLanguage("en")] diff --git a/Library/Silverlight/WaveMediaStreamSource.cs b/Library/Silverlight/WaveMediaStreamSource.cs index 9aaacd6..fac27ba 100644 --- a/Library/Silverlight/WaveMediaStreamSource.cs +++ b/Library/Silverlight/WaveMediaStreamSource.cs @@ -1,76 +1,76 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Windows.Media; - -namespace Jellyfish.Library -{ - public sealed class WaveMediaStreamSource : MediaStreamSource, IDisposable - { - public WaveMediaStreamSource(int sampleRate, int sampleChannels, int sampleBits, int sampleSize, int sampleLatency, Action updater) - { - _bufferSize = sampleSize; - _buffer = new byte[_bufferSize]; - _bufferStream = new MemoryStream(_buffer); - _waveFormat = new WaveFormat(sampleRate, sampleChannels, sampleBits); - AudioBufferLength = sampleLatency; // ms; avoids audio delay - _updater = updater; - } - - public void Dispose() - { - _bufferStream.Dispose(); - } - - protected override void CloseMedia() - { - _audioDescription = null; - } - - protected override void GetDiagnosticAsync(MediaStreamSourceDiagnosticKind diagnosticKind) - { - throw new NotImplementedException(); - } - - protected override void GetSampleAsync(MediaStreamType mediaStreamType) - { - _updater(_buffer, _bufferSize); - - var sample = new MediaStreamSample(_audioDescription, _bufferStream, 0, _bufferSize, _timestamp, _emptySampleDict); - _timestamp += _bufferSize * 10000000L / _waveFormat.AverageBytesPerSec; // 100 ns - - ReportGetSampleCompleted(sample); - } - - protected override void OpenMediaAsync() - { - _timestamp = 0; - - var sourceAttributes = new Dictionary() { { MediaSourceAttributesKeys.Duration, "0" }, { MediaSourceAttributesKeys.CanSeek, "false" } }; - var streamAttributes = new Dictionary() { { MediaStreamAttributeKeys.CodecPrivateData, _waveFormat.ToHexString() } }; - _audioDescription = new MediaStreamDescription(MediaStreamType.Audio, streamAttributes); - var availableStreams = new List() { _audioDescription }; - - ReportOpenMediaCompleted(sourceAttributes, availableStreams); - } - - protected override void SeekAsync(long seekToTime) - { - ReportSeekCompleted(seekToTime); - } - - protected override void SwitchMediaStreamAsync(MediaStreamDescription mediaStreamDescription) - { - throw new NotImplementedException(); - } - - private byte[] _buffer; - private int _bufferSize; - private MemoryStream _bufferStream; - private Action _updater; - private WaveFormat _waveFormat; - private long _timestamp; - private MediaStreamDescription _audioDescription; - private Dictionary _emptySampleDict = new Dictionary(); - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Windows.Media; + +namespace Jellyfish.Library +{ + public sealed class WaveMediaStreamSource : MediaStreamSource, IDisposable + { + public WaveMediaStreamSource(int sampleRate, int sampleChannels, int sampleBits, int sampleSize, int sampleLatency, Action updater) + { + _bufferSize = sampleSize; + _buffer = new byte[_bufferSize]; + _bufferStream = new MemoryStream(_buffer); + _waveFormat = new WaveFormat(sampleRate, sampleChannels, sampleBits); + AudioBufferLength = sampleLatency; // ms; avoids audio delay + _updater = updater; + } + + public void Dispose() + { + _bufferStream.Dispose(); + } + + protected override void CloseMedia() + { + _audioDescription = null; + } + + protected override void GetDiagnosticAsync(MediaStreamSourceDiagnosticKind diagnosticKind) + { + throw new NotImplementedException(); + } + + protected override void GetSampleAsync(MediaStreamType mediaStreamType) + { + _updater(_buffer, _bufferSize); + + var sample = new MediaStreamSample(_audioDescription, _bufferStream, 0, _bufferSize, _timestamp, _emptySampleDict); + _timestamp += _bufferSize * 10000000L / _waveFormat.AverageBytesPerSec; // 100 ns + + ReportGetSampleCompleted(sample); + } + + protected override void OpenMediaAsync() + { + _timestamp = 0; + + var sourceAttributes = new Dictionary() { { MediaSourceAttributesKeys.Duration, "0" }, { MediaSourceAttributesKeys.CanSeek, "false" } }; + var streamAttributes = new Dictionary() { { MediaStreamAttributeKeys.CodecPrivateData, _waveFormat.ToHexString() } }; + _audioDescription = new MediaStreamDescription(MediaStreamType.Audio, streamAttributes); + var availableStreams = new List() { _audioDescription }; + + ReportOpenMediaCompleted(sourceAttributes, availableStreams); + } + + protected override void SeekAsync(long seekToTime) + { + ReportSeekCompleted(seekToTime); + } + + protected override void SwitchMediaStreamAsync(MediaStreamDescription mediaStreamDescription) + { + throw new NotImplementedException(); + } + + private byte[] _buffer; + private int _bufferSize; + private MemoryStream _bufferStream; + private Action _updater; + private WaveFormat _waveFormat; + private long _timestamp; + private MediaStreamDescription _audioDescription; + private Dictionary _emptySampleDict = new Dictionary(); + } +} diff --git a/Library/StreamExtensions.cs b/Library/StreamExtensions.cs index e55767f..67137e2 100644 --- a/Library/StreamExtensions.cs +++ b/Library/StreamExtensions.cs @@ -1,94 +1,94 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.IO; - -namespace Jellyfish.Library -{ - public static class StreamExtensions - { - [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "3#")] - public static int ReadBlock(this Stream stream, byte[] buffer, int offset, ref int count) - { - int read = ReadBlock(stream, buffer, offset, count, count); - count -= read; - return read; - } - - [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) - { - throw new ArgumentNullException("stream"); - } - if (buffer == null) - { - throw new ArgumentNullException("buffer"); - } - - count = Math.Min(count, buffer.Length - offset); - minCount = Math.Min(minCount, buffer.Length - offset); - - int total = 0; - int read; - do - { - total += read = stream.Read(buffer, offset + total, count - total); - } - while ((read > 0) && (total < count)); - - if (total < minCount) - { - throw new EndOfStreamException(); - } - - 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) - { - throw new ArgumentNullException("stream"); - } - - if (stream.CanSeek) - { - stream.Seek(count, SeekOrigin.Current); - } - else - { - int total = 0; - int read; - do - { - 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]; - } -} +using System; +using System.Diagnostics.CodeAnalysis; +using System.IO; + +namespace Jellyfish.Library +{ + public static class StreamExtensions + { + [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "3#")] + public static int ReadBlock(this Stream stream, byte[] buffer, int offset, ref int count) + { + int read = ReadBlock(stream, buffer, offset, count, count); + count -= read; + return read; + } + + [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) + { + throw new ArgumentNullException("stream"); + } + if (buffer == null) + { + throw new ArgumentNullException("buffer"); + } + + count = Math.Min(count, buffer.Length - offset); + minCount = Math.Min(minCount, buffer.Length - offset); + + int total = 0; + int read; + do + { + total += read = stream.Read(buffer, offset + total, count - total); + } + while ((read > 0) && (total < count)); + + if (total < minCount) + { + throw new EndOfStreamException(); + } + + 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) + { + throw new ArgumentNullException("stream"); + } + + if (stream.CanSeek) + { + stream.Seek(count, SeekOrigin.Current); + } + else + { + int total = 0; + int read; + do + { + 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/Library/StringBuilderExtensions.cs b/Library/StringBuilderExtensions.cs index 5935c60..744400d 100644 --- a/Library/StringBuilderExtensions.cs +++ b/Library/StringBuilderExtensions.cs @@ -1,54 +1,54 @@ -using System; -using System.Globalization; -using System.Text; - -namespace Jellyfish.Library -{ - public static class StringBuilderExtensions - { - public static StringBuilder AppendHex(this StringBuilder builder, short value) // little endian - { - if (builder == null) - { - throw new ArgumentNullException("builder"); - } - - return builder.AppendFormat(CultureInfo.InvariantCulture, "{0:X2}{1:X2}", value & 0xFF, value >> 8); - } - - public static StringBuilder AppendHex(this StringBuilder builder, int value) // little endian - { - if (builder == null) - { - throw new ArgumentNullException("builder"); - } - - return builder.AppendFormat(CultureInfo.InvariantCulture, "{0:X2}{1:X2}{2:X2}{3:X2}", value & 0xFF, (value >> 8) & 0xFF, (value >> 16) & 0xFF, value >> 24); - } - - public static StringBuilder AppendWithoutGarbage(this StringBuilder builder, int value) - { - if (builder == null) - { - throw new ArgumentNullException("builder"); - } - - if (value < 0) - { - builder.Append('-'); - } - - int index = builder.Length; - do - { - builder.Insert(index, Digits, (value % 10) + 9, 1); - value /= 10; - } - while (value != 0); - - return builder; - } - - private static readonly char[] Digits = new char[] { '9', '8', '7', '6', '5', '4', '3', '2', '1', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; - } -} +using System; +using System.Globalization; +using System.Text; + +namespace Jellyfish.Library +{ + public static class StringBuilderExtensions + { + public static StringBuilder AppendHex(this StringBuilder builder, short value) // little endian + { + if (builder == null) + { + throw new ArgumentNullException("builder"); + } + + return builder.AppendFormat(CultureInfo.InvariantCulture, "{0:X2}{1:X2}", value & 0xFF, value >> 8); + } + + public static StringBuilder AppendHex(this StringBuilder builder, int value) // little endian + { + if (builder == null) + { + throw new ArgumentNullException("builder"); + } + + return builder.AppendFormat(CultureInfo.InvariantCulture, "{0:X2}{1:X2}{2:X2}{3:X2}", value & 0xFF, (value >> 8) & 0xFF, (value >> 16) & 0xFF, value >> 24); + } + + public static StringBuilder AppendWithoutGarbage(this StringBuilder builder, int value) + { + if (builder == null) + { + throw new ArgumentNullException("builder"); + } + + if (value < 0) + { + builder.Append('-'); + } + + int index = builder.Length; + do + { + builder.Insert(index, Digits, (value % 10) + 9, 1); + value /= 10; + } + while (value != 0); + + return builder; + } + + private static readonly char[] Digits = new char[] { '9', '8', '7', '6', '5', '4', '3', '2', '1', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; + } +} diff --git a/Library/WaveFormat.cs b/Library/WaveFormat.cs index 132f815..8efb65f 100644 --- a/Library/WaveFormat.cs +++ b/Library/WaveFormat.cs @@ -1,49 +1,49 @@ -using System.Runtime.InteropServices; -using System.Text; - -namespace Jellyfish.Library -{ - [StructLayout(LayoutKind.Sequential)] - public sealed class WaveFormat - { - public WaveFormat(int sampleRate, int sampleChannels, int sampleBits) - { - _formatTag = WaveFormatPcm; - _samplesPerSec = sampleRate; - _channels = (short)sampleChannels; - _bitsPerSample = (short)sampleBits; - _blockAlign = (short)(sampleChannels * sampleBits / 8); - _averageBytesPerSec = sampleRate * _blockAlign; - } - - public string ToHexString() // little endian - { - var builder = new StringBuilder(); - - builder.AppendHex(_formatTag); - builder.AppendHex(_channels); - builder.AppendHex(_samplesPerSec); - builder.AppendHex(_averageBytesPerSec); - builder.AppendHex(_blockAlign); - builder.AppendHex(_bitsPerSample); - builder.AppendHex(_size); - - return builder.ToString(); - } - - public int SamplesPerSec { get { return _samplesPerSec; } } // no auto props - public int Channels { get { return _channels; } } - public int BitsPerSample { get { return _bitsPerSample; } } - public int AverageBytesPerSec { get { return _averageBytesPerSec; } } - - private const int WaveFormatPcm = 1; - - private short _formatTag; - private short _channels; - private int _samplesPerSec; - private int _averageBytesPerSec; - private short _blockAlign; - private short _bitsPerSample; - private short _size; - } -} +using System.Runtime.InteropServices; +using System.Text; + +namespace Jellyfish.Library +{ + [StructLayout(LayoutKind.Sequential)] + public sealed class WaveFormat + { + public WaveFormat(int sampleRate, int sampleChannels, int sampleBits) + { + _formatTag = WaveFormatPcm; + _samplesPerSec = sampleRate; + _channels = (short)sampleChannels; + _bitsPerSample = (short)sampleBits; + _blockAlign = (short)(sampleChannels * sampleBits / 8); + _averageBytesPerSec = sampleRate * _blockAlign; + } + + public string ToHexString() // little endian + { + var builder = new StringBuilder(); + + builder.AppendHex(_formatTag); + builder.AppendHex(_channels); + builder.AppendHex(_samplesPerSec); + builder.AppendHex(_averageBytesPerSec); + builder.AppendHex(_blockAlign); + builder.AppendHex(_bitsPerSample); + builder.AppendHex(_size); + + return builder.ToString(); + } + + public int SamplesPerSec { get { return _samplesPerSec; } } // no auto props + public int Channels { get { return _channels; } } + public int BitsPerSample { get { return _bitsPerSample; } } + public int AverageBytesPerSec { get { return _averageBytesPerSec; } } + + private const int WaveFormatPcm = 1; + + private short _formatTag; + private short _channels; + private int _samplesPerSec; + private int _averageBytesPerSec; + private short _blockAlign; + private short _bitsPerSample; + private short _size; + } +} diff --git a/Library/Wpf/ApplicationBase.cs b/Library/Wpf/ApplicationBase.cs index d1e4a8c..7bd14fc 100644 --- a/Library/Wpf/ApplicationBase.cs +++ b/Library/Wpf/ApplicationBase.cs @@ -1,65 +1,65 @@ -using System; -using System.Diagnostics; -using System.Security; -using System.Text; -using System.Windows; -using System.Windows.Threading; - -namespace Jellyfish.Library -{ - public abstract class ApplicationBase : Application - { - [SecurityCritical] - protected ApplicationBase() : - this(null) - { - } - - [SecurityCritical] - protected ApplicationBase(string name) - { - Name = name; - - DispatcherUnhandledException += OnApplicationDispatcherUnhandledException; - AppDomain.CurrentDomain.UnhandledException += OnAppDomainUnhandledException; - } - - private string GetExceptionCaption(string title, bool isTerminating = false) - { - var caption = new StringBuilder(); - if (!string.IsNullOrEmpty(Name)) - { - caption.Append(Name).Append(' '); - } - caption.Append(title); - if (isTerminating) - { - caption.Append(" (Terminating)"); - } - - return caption.ToString(); - } - - private void OnApplicationDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) - { - MessageBox.Show(e.Exception.ToString(), GetExceptionCaption("Application Dispatcher Exception", isTerminating: true)); - if (Debugger.IsAttached) - { - Debugger.Break(); - } - e.Handled = true; - Shutdown(); - } - - private void OnAppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e) - { - MessageBox.Show(e.ExceptionObject.ToString(), GetExceptionCaption("AppDomain Exception", e.IsTerminating)); - if (Debugger.IsAttached) - { - Debugger.Break(); - } - } - - public string Name { get; private set; } - } -} +using System; +using System.Diagnostics; +using System.Security; +using System.Text; +using System.Windows; +using System.Windows.Threading; + +namespace Jellyfish.Library +{ + public abstract class ApplicationBase : Application + { + [SecurityCritical] + protected ApplicationBase() : + this(null) + { + } + + [SecurityCritical] + protected ApplicationBase(string name) + { + Name = name; + + DispatcherUnhandledException += OnApplicationDispatcherUnhandledException; + AppDomain.CurrentDomain.UnhandledException += OnAppDomainUnhandledException; + } + + private string GetExceptionCaption(string title, bool isTerminating = false) + { + var caption = new StringBuilder(); + if (!string.IsNullOrEmpty(Name)) + { + caption.Append(Name).Append(' '); + } + caption.Append(title); + if (isTerminating) + { + caption.Append(" (Terminating)"); + } + + return caption.ToString(); + } + + private void OnApplicationDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) + { + MessageBox.Show(e.Exception.ToString(), GetExceptionCaption("Application Dispatcher Exception", isTerminating: true)); + if (Debugger.IsAttached) + { + Debugger.Break(); + } + e.Handled = true; + Shutdown(); + } + + private void OnAppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e) + { + MessageBox.Show(e.ExceptionObject.ToString(), GetExceptionCaption("AppDomain Exception", e.IsTerminating)); + if (Debugger.IsAttached) + { + Debugger.Break(); + } + } + + public string Name { get; private set; } + } +} diff --git a/Library/Wpf/Jellyfish.Library.Wpf.csproj b/Library/Wpf/Jellyfish.Library.Wpf.csproj index 4351007..a804482 100644 --- a/Library/Wpf/Jellyfish.Library.Wpf.csproj +++ b/Library/Wpf/Jellyfish.Library.Wpf.csproj @@ -1,120 +1,120 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {93900841-7250-4D3A-837E-43EE3FD118DC} - Library - Properties - Jellyfish.Library - Jellyfish.Library - v4.5 - 512 - - - true - full - false - bin\ - DEBUG;TRACE;WINDOWS;CODE_ANALYSIS - prompt - 4 - true - AllRules.ruleset - false - - - pdbonly - true - bin\ - TRACE;WINDOWS;CODE_ANALYSIS - prompt - 4 - true - AllRules.ruleset - false - - - false - - - ..\..\..\Jellyfish\StrongName.snk - - - - - - - - - - - - - - DirectSound.cs - - - DirectSoundInterop.cs - - - DispatcherExtensions.cs - - - DisposableBase.cs - - - FrameRateCounter.xaml.cs - FrameRateCounter.xaml - - - GCHandleHelpers.cs - - - GlobalSuppressions.cs - - - IEnumerableExtensions.cs - - - MarshalHelpers.cs - - - MathHelpers.cs - - - StreamExtensions.cs - - - StringBuilderExtensions.cs - - - WaveFormat.cs - - - - - - - - FrameRateCounter.xaml - MSBuild:Compile - Designer - - - - - CustomDictionary.xml - - - - + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {93900841-7250-4D3A-837E-43EE3FD118DC} + Library + Properties + Jellyfish.Library + Jellyfish.Library + v4.5 + 512 + + + true + full + false + bin\ + DEBUG;TRACE;WINDOWS;CODE_ANALYSIS + prompt + 4 + true + AllRules.ruleset + false + + + pdbonly + true + bin\ + TRACE;WINDOWS;CODE_ANALYSIS + prompt + 4 + true + AllRules.ruleset + false + + + false + + + ..\..\..\Jellyfish\StrongName.snk + + + + + + + + + + + + + + DirectSound.cs + + + DirectSoundInterop.cs + + + DispatcherExtensions.cs + + + DisposableBase.cs + + + FrameRateCounter.xaml.cs + FrameRateCounter.xaml + + + GCHandleHelpers.cs + + + GlobalSuppressions.cs + + + IEnumerableExtensions.cs + + + MarshalHelpers.cs + + + MathHelpers.cs + + + StreamExtensions.cs + + + StringBuilderExtensions.cs + + + WaveFormat.cs + + + + + + + + FrameRateCounter.xaml + MSBuild:Compile + Designer + + + + + CustomDictionary.xml + + + + \ No newline at end of file diff --git a/Library/Wpf/Jellyfish.Library.Wpf.sln b/Library/Wpf/Jellyfish.Library.Wpf.sln index 063cef4..c13b9d8 100644 --- a/Library/Wpf/Jellyfish.Library.Wpf.sln +++ b/Library/Wpf/Jellyfish.Library.Wpf.sln @@ -1,20 +1,20 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Library.Wpf", "Jellyfish.Library.Wpf.csproj", "{93900841-7250-4D3A-837E-43EE3FD118DC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {93900841-7250-4D3A-837E-43EE3FD118DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {93900841-7250-4D3A-837E-43EE3FD118DC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {93900841-7250-4D3A-837E-43EE3FD118DC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {93900841-7250-4D3A-837E-43EE3FD118DC}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Library.Wpf", "Jellyfish.Library.Wpf.csproj", "{93900841-7250-4D3A-837E-43EE3FD118DC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {93900841-7250-4D3A-837E-43EE3FD118DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {93900841-7250-4D3A-837E-43EE3FD118DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {93900841-7250-4D3A-837E-43EE3FD118DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {93900841-7250-4D3A-837E-43EE3FD118DC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Library/Wpf/Properties/AssemblyInfo.cs b/Library/Wpf/Properties/AssemblyInfo.cs index 614c061..905f607 100644 --- a/Library/Wpf/Properties/AssemblyInfo.cs +++ b/Library/Wpf/Properties/AssemblyInfo.cs @@ -1,22 +1,22 @@ -using System; -using System.Reflection; -using System.Resources; -using System.Runtime.InteropServices; -using Jellyfish.Library; - -[assembly: AssemblyTitle("Library")] -[assembly: AssemblyDescription("Common Library")] -[assembly: AssemblyProduct("Jellyfish.Library.Wpf")] -[assembly: AssemblyCompany("Digital Jellyfish Design Ltd")] -[assembly: AssemblyCopyright("Copyright © 2009-2012 Digital Jellyfish Design Ltd")] -[assembly: AssemblyMetadata("Developer", "Sean Fausett")] - -[assembly: AssemblyVersion("0.4.0.0")] -[assembly: AssemblyFileVersion("0.4.0.0")] -[assembly: AssemblyInformationalVersion("0.4.0.0")] - -[assembly: CLSCompliant(false)] -[assembly: ComVisible(false)] -[assembly: Guid("66034b9e-9f0b-47b0-aac4-cade9a748891")] - -[assembly: NeutralResourcesLanguage("en")] +using System; +using System.Reflection; +using System.Resources; +using System.Runtime.InteropServices; +using Jellyfish.Library; + +[assembly: AssemblyTitle("Library")] +[assembly: AssemblyDescription("Common Library")] +[assembly: AssemblyProduct("Jellyfish.Library.Wpf")] +[assembly: AssemblyCompany("Digital Jellyfish Design Ltd")] +[assembly: AssemblyCopyright("Copyright © 2009-2012 Digital Jellyfish Design Ltd")] +[assembly: AssemblyMetadata("Developer", "Sean Fausett")] + +[assembly: AssemblyVersion("0.4.0.0")] +[assembly: AssemblyFileVersion("0.4.0.0")] +[assembly: AssemblyInformationalVersion("0.4.0.0")] + +[assembly: CLSCompliant(false)] +[assembly: ComVisible(false)] +[assembly: Guid("66034b9e-9f0b-47b0-aac4-cade9a748891")] + +[assembly: NeutralResourcesLanguage("en")] diff --git a/Library/Wpf/WindowExtensions.cs b/Library/Wpf/WindowExtensions.cs index 14d22fe..34b0fec 100644 --- a/Library/Wpf/WindowExtensions.cs +++ b/Library/Wpf/WindowExtensions.cs @@ -1,14 +1,14 @@ -using System; -using System.Windows; -using System.Windows.Interop; - -namespace Jellyfish.Library -{ - public static class WindowExtensions - { - public static IntPtr GetHandle(this Window window) - { - return new WindowInteropHelper(window).Handle; - } - } -} +using System; +using System.Windows; +using System.Windows.Interop; + +namespace Jellyfish.Library +{ + public static class WindowExtensions + { + public static IntPtr GetHandle(this Window window) + { + return new WindowInteropHelper(window).Handle; + } + } +} diff --git a/License.txt b/License.txt index 074a544..f121fec 100644 --- a/License.txt +++ b/License.txt @@ -1,280 +1,280 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/Virtu/Cassette.cs b/Virtu/Cassette.cs index 93abdb9..e4ad339 100644 --- a/Virtu/Cassette.cs +++ b/Virtu/Cassette.cs @@ -1,23 +1,23 @@ -using System.Diagnostics.CodeAnalysis; - -namespace Jellyfish.Virtu -{ - public sealed class Cassette : MachineComponent - { - public Cassette(Machine machine) : - base(machine) - { - } - - [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] - public bool ReadInput() - { - return false; - } - - [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] - public void ToggleOutput() - { - } - } -} +using System.Diagnostics.CodeAnalysis; + +namespace Jellyfish.Virtu +{ + public sealed class Cassette : MachineComponent + { + public Cassette(Machine machine) : + base(machine) + { + } + + [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] + public bool ReadInput() + { + return false; + } + + [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] + public void ToggleOutput() + { + } + } +} diff --git a/Virtu/Cpu.cs b/Virtu/Cpu.cs index a2b9773..973a8b3 100644 --- a/Virtu/Cpu.cs +++ b/Virtu/Cpu.cs @@ -1,3261 +1,3261 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.IO; - -namespace Jellyfish.Virtu -{ - public sealed partial class Cpu : MachineComponent - { - public Cpu(Machine machine) : - base(machine) - { - ExecuteOpCode65N02 = new Action[OpCodeCount] - { - Execute65X02Brk00, Execute65X02Ora01, Execute65N02Nop02, Execute65N02Nop03, - Execute65N02Nop04, Execute65X02Ora05, Execute65X02Asl06, Execute65N02Nop07, - Execute65X02Php08, Execute65X02Ora09, Execute65X02Asl0A, Execute65N02Nop0B, - Execute65N02Nop0C, Execute65X02Ora0D, Execute65X02Asl0E, Execute65N02Nop0F, - Execute65X02Bpl10, Execute65X02Ora11, Execute65N02Nop12, Execute65N02Nop13, - Execute65N02Nop14, Execute65X02Ora15, Execute65X02Asl16, Execute65N02Nop17, - Execute65X02Clc18, Execute65X02Ora19, Execute65N02Nop1A, Execute65N02Nop1B, - Execute65N02Nop1C, Execute65X02Ora1D, Execute65N02Asl1E, Execute65N02Nop1F, - Execute65X02Jsr20, Execute65X02And21, Execute65N02Nop22, Execute65N02Nop23, - Execute65X02Bit24, Execute65X02And25, Execute65X02Rol26, Execute65N02Nop27, - Execute65X02Plp28, Execute65X02And29, Execute65X02Rol2A, Execute65N02Nop2B, - Execute65X02Bit2C, Execute65X02And2D, Execute65X02Rol2E, Execute65N02Nop2F, - Execute65X02Bmi30, Execute65X02And31, Execute65N02Nop32, Execute65N02Nop33, - Execute65N02Nop34, Execute65X02And35, Execute65X02Rol36, Execute65N02Nop37, - Execute65X02Sec38, Execute65X02And39, Execute65N02Nop3A, Execute65N02Nop3B, - Execute65N02Nop3C, Execute65X02And3D, Execute65N02Rol3E, Execute65N02Nop3F, - Execute65X02Rti40, Execute65X02Eor41, Execute65N02Nop42, Execute65N02Nop43, - Execute65N02Nop44, Execute65X02Eor45, Execute65X02Lsr46, Execute65N02Nop47, - Execute65X02Pha48, Execute65X02Eor49, Execute65X02Lsr4A, Execute65N02Nop4B, - Execute65X02Jmp4C, Execute65X02Eor4D, Execute65X02Lsr4E, Execute65N02Nop4F, - Execute65X02Bvc50, Execute65X02Eor51, Execute65N02Nop52, Execute65N02Nop53, - Execute65N02Nop54, Execute65X02Eor55, Execute65X02Lsr56, Execute65N02Nop57, - Execute65X02Cli58, Execute65X02Eor59, Execute65N02Nop5A, Execute65N02Nop5B, - Execute65N02Nop5C, Execute65X02Eor5D, Execute65N02Lsr5E, Execute65N02Nop5F, - Execute65X02Rts60, Execute65N02Adc61, Execute65N02Nop62, Execute65N02Nop63, - Execute65N02Nop64, Execute65N02Adc65, Execute65X02Ror66, Execute65N02Nop67, - Execute65X02Pla68, Execute65N02Adc69, Execute65X02Ror6A, Execute65N02Nop6B, - Execute65N02Jmp6C, Execute65N02Adc6D, Execute65X02Ror6E, Execute65N02Nop6F, - Execute65X02Bvs70, Execute65N02Adc71, Execute65N02Nop72, Execute65N02Nop73, - Execute65N02Nop74, Execute65N02Adc75, Execute65X02Ror76, Execute65N02Nop77, - Execute65X02Sei78, Execute65N02Adc79, Execute65N02Nop7A, Execute65N02Nop7B, - Execute65N02Nop7C, Execute65N02Adc7D, Execute65N02Ror7E, Execute65N02Nop7F, - Execute65N02Nop80, Execute65X02Sta81, Execute65N02Nop82, Execute65N02Nop83, - Execute65X02Sty84, Execute65X02Sta85, Execute65X02Stx86, Execute65N02Nop87, - Execute65X02Dey88, Execute65N02Nop89, Execute65X02Txa8A, Execute65N02Nop8B, - Execute65X02Sty8C, Execute65X02Sta8D, Execute65X02Stx8E, Execute65N02Nop8F, - Execute65X02Bcc90, Execute65X02Sta91, Execute65N02Nop92, Execute65N02Nop93, - Execute65X02Sty94, Execute65X02Sta95, Execute65X02Stx96, Execute65N02Nop97, - Execute65X02Tya98, Execute65X02Sta99, Execute65X02Txs9A, Execute65N02Nop9B, - Execute65N02Nop9C, Execute65X02Sta9D, Execute65N02Nop9E, Execute65N02Nop9F, - Execute65X02LdyA0, Execute65X02LdaA1, Execute65X02LdxA2, Execute65N02NopA3, - Execute65X02LdyA4, Execute65X02LdaA5, Execute65X02LdxA6, Execute65N02NopA7, - Execute65X02TayA8, Execute65X02LdaA9, Execute65X02TaxAA, Execute65N02NopAB, - Execute65X02LdyAC, Execute65X02LdaAD, Execute65X02LdxAE, Execute65N02NopAF, - Execute65X02BcsB0, Execute65X02LdaB1, Execute65N02NopB2, Execute65N02NopB3, - Execute65X02LdyB4, Execute65X02LdaB5, Execute65X02LdxB6, Execute65N02NopB7, - Execute65X02ClvB8, Execute65X02LdaB9, Execute65X02TsxBA, Execute65N02NopBB, - Execute65X02LdyBC, Execute65X02LdaBD, Execute65X02LdxBE, Execute65N02NopBF, - Execute65X02CpyC0, Execute65X02CmpC1, Execute65N02NopC2, Execute65N02NopC3, - Execute65X02CpyC4, Execute65X02CmpC5, Execute65X02DecC6, Execute65N02NopC7, - Execute65X02InyC8, Execute65X02CmpC9, Execute65X02DexCA, Execute65N02NopCB, - Execute65X02CpyCC, Execute65X02CmpCD, Execute65X02DecCE, Execute65N02NopCF, - Execute65X02BneD0, Execute65X02CmpD1, Execute65N02NopD2, Execute65N02NopD3, - Execute65N02NopD4, Execute65X02CmpD5, Execute65X02DecD6, Execute65N02NopD7, - Execute65X02CldD8, Execute65X02CmpD9, Execute65N02NopDA, Execute65N02NopDB, - Execute65N02NopDC, Execute65X02CmpDD, Execute65N02DecDE, Execute65N02NopDF, - Execute65X02CpxE0, Execute65N02SbcE1, Execute65N02NopE2, Execute65N02NopE3, - Execute65X02CpxE4, Execute65N02SbcE5, Execute65X02IncE6, Execute65N02NopE7, - Execute65X02InxE8, Execute65N02SbcE9, Execute65X02NopEA, Execute65N02NopEB, - Execute65X02CpxEC, Execute65N02SbcED, Execute65X02IncEE, Execute65N02NopEF, - Execute65X02BeqF0, Execute65N02SbcF1, Execute65N02NopF2, Execute65N02NopF3, - Execute65N02NopF4, Execute65N02SbcF5, Execute65X02IncF6, Execute65N02NopF7, - Execute65X02SedF8, Execute65N02SbcF9, Execute65N02NopFA, Execute65N02NopFB, - Execute65N02NopFC, Execute65N02SbcFD, Execute65N02IncFE, Execute65N02NopFF - }; - - ExecuteOpCode65C02 = new Action[OpCodeCount] - { - Execute65X02Brk00, Execute65X02Ora01, Execute65C02Nop02, Execute65C02Nop03, - Execute65C02Tsb04, Execute65X02Ora05, Execute65X02Asl06, Execute65C02Nop07, - Execute65X02Php08, Execute65X02Ora09, Execute65X02Asl0A, Execute65C02Nop0B, - Execute65C02Tsb0C, Execute65X02Ora0D, Execute65X02Asl0E, Execute65C02Nop0F, - Execute65X02Bpl10, Execute65X02Ora11, Execute65C02Ora12, Execute65C02Nop13, - Execute65C02Trb14, Execute65X02Ora15, Execute65X02Asl16, Execute65C02Nop17, - Execute65X02Clc18, Execute65X02Ora19, Execute65C02Ina1A, Execute65C02Nop1B, - Execute65C02Trb1C, Execute65X02Ora1D, Execute65C02Asl1E, Execute65C02Nop1F, - Execute65X02Jsr20, Execute65X02And21, Execute65C02Nop22, Execute65C02Nop23, - Execute65X02Bit24, Execute65X02And25, Execute65X02Rol26, Execute65C02Nop27, - Execute65X02Plp28, Execute65X02And29, Execute65X02Rol2A, Execute65C02Nop2B, - Execute65X02Bit2C, Execute65X02And2D, Execute65X02Rol2E, Execute65C02Nop2F, - Execute65X02Bmi30, Execute65X02And31, Execute65C02And32, Execute65C02Nop33, - Execute65C02Bit34, Execute65X02And35, Execute65X02Rol36, Execute65C02Nop37, - Execute65X02Sec38, Execute65X02And39, Execute65C02Dea3A, Execute65C02Nop3B, - Execute65C02Bit3C, Execute65X02And3D, Execute65C02Rol3E, Execute65C02Nop3F, - Execute65X02Rti40, Execute65X02Eor41, Execute65C02Nop42, Execute65C02Nop43, - Execute65C02Nop44, Execute65X02Eor45, Execute65X02Lsr46, Execute65C02Nop47, - Execute65X02Pha48, Execute65X02Eor49, Execute65X02Lsr4A, Execute65C02Nop4B, - Execute65X02Jmp4C, Execute65X02Eor4D, Execute65X02Lsr4E, Execute65C02Nop4F, - Execute65X02Bvc50, Execute65X02Eor51, Execute65C02Eor52, Execute65C02Nop53, - Execute65C02Nop54, Execute65X02Eor55, Execute65X02Lsr56, Execute65C02Nop57, - Execute65X02Cli58, Execute65X02Eor59, Execute65C02Phy5A, Execute65C02Nop5B, - Execute65C02Nop5C, Execute65X02Eor5D, Execute65C02Lsr5E, Execute65C02Nop5F, - Execute65X02Rts60, Execute65C02Adc61, Execute65C02Nop62, Execute65C02Nop63, - Execute65C02Stz64, Execute65C02Adc65, Execute65X02Ror66, Execute65C02Nop67, - Execute65X02Pla68, Execute65C02Adc69, Execute65X02Ror6A, Execute65C02Nop6B, - Execute65C02Jmp6C, Execute65C02Adc6D, Execute65X02Ror6E, Execute65C02Nop6F, - Execute65X02Bvs70, Execute65C02Adc71, Execute65C02Adc72, Execute65C02Nop73, - Execute65C02Stz74, Execute65C02Adc75, Execute65X02Ror76, Execute65C02Nop77, - Execute65X02Sei78, Execute65C02Adc79, Execute65C02Ply7A, Execute65C02Nop7B, - Execute65C02Jmp7C, Execute65C02Adc7D, Execute65C02Ror7E, Execute65C02Nop7F, - Execute65C02Bra80, Execute65X02Sta81, Execute65C02Nop82, Execute65C02Nop83, - Execute65X02Sty84, Execute65X02Sta85, Execute65X02Stx86, Execute65C02Nop87, - Execute65X02Dey88, Execute65C02Bit89, Execute65X02Txa8A, Execute65C02Nop8B, - Execute65X02Sty8C, Execute65X02Sta8D, Execute65X02Stx8E, Execute65C02Nop8F, - Execute65X02Bcc90, Execute65X02Sta91, Execute65C02Sta92, Execute65C02Nop93, - Execute65X02Sty94, Execute65X02Sta95, Execute65X02Stx96, Execute65C02Nop97, - Execute65X02Tya98, Execute65X02Sta99, Execute65X02Txs9A, Execute65C02Nop9B, - Execute65C02Stz9C, Execute65X02Sta9D, Execute65C02Stz9E, Execute65C02Nop9F, - Execute65X02LdyA0, Execute65X02LdaA1, Execute65X02LdxA2, Execute65C02NopA3, - Execute65X02LdyA4, Execute65X02LdaA5, Execute65X02LdxA6, Execute65C02NopA7, - Execute65X02TayA8, Execute65X02LdaA9, Execute65X02TaxAA, Execute65C02NopAB, - Execute65X02LdyAC, Execute65X02LdaAD, Execute65X02LdxAE, Execute65C02NopAF, - Execute65X02BcsB0, Execute65X02LdaB1, Execute65C02LdaB2, Execute65C02NopB3, - Execute65X02LdyB4, Execute65X02LdaB5, Execute65X02LdxB6, Execute65C02NopB7, - Execute65X02ClvB8, Execute65X02LdaB9, Execute65X02TsxBA, Execute65C02NopBB, - Execute65X02LdyBC, Execute65X02LdaBD, Execute65X02LdxBE, Execute65C02NopBF, - Execute65X02CpyC0, Execute65X02CmpC1, Execute65C02NopC2, Execute65C02NopC3, - Execute65X02CpyC4, Execute65X02CmpC5, Execute65X02DecC6, Execute65C02NopC7, - Execute65X02InyC8, Execute65X02CmpC9, Execute65X02DexCA, Execute65C02NopCB, - Execute65X02CpyCC, Execute65X02CmpCD, Execute65X02DecCE, Execute65C02NopCF, - Execute65X02BneD0, Execute65X02CmpD1, Execute65C02CmpD2, Execute65C02NopD3, - Execute65C02NopD4, Execute65X02CmpD5, Execute65X02DecD6, Execute65C02NopD7, - Execute65X02CldD8, Execute65X02CmpD9, Execute65C02PhxDA, Execute65C02NopDB, - Execute65C02NopDC, Execute65X02CmpDD, Execute65C02DecDE, Execute65C02NopDF, - Execute65X02CpxE0, Execute65C02SbcE1, Execute65C02NopE2, Execute65C02NopE3, - Execute65X02CpxE4, Execute65C02SbcE5, Execute65X02IncE6, Execute65C02NopE7, - Execute65X02InxE8, Execute65C02SbcE9, Execute65X02NopEA, Execute65C02NopEB, - Execute65X02CpxEC, Execute65C02SbcED, Execute65X02IncEE, Execute65C02NopEF, - Execute65X02BeqF0, Execute65C02SbcF1, Execute65C02SbcF2, Execute65C02NopF3, - Execute65C02NopF4, Execute65C02SbcF5, Execute65X02IncF6, Execute65C02NopF7, - Execute65X02SedF8, Execute65C02SbcF9, Execute65C02PlxFA, Execute65C02NopFB, - Execute65C02NopFC, Execute65C02SbcFD, Execute65C02IncFE, Execute65C02NopFF - }; - } - - public override void Initialize() - { - _memory = Machine.Memory; - - Is65C02 = true; - IsThrottled = true; - Multiplier = 1; - - RS = 0xFF; - } - - public override void Reset() - { - RS = (RS - 3) & 0xFF; // [4-14] - RPC = _memory.ReadRomRegionE0FF(0xFFFC) | (_memory.ReadRomRegionE0FF(0xFFFD) << 8); - RP |= (PB | PI); - 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.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); - } - - public int Execute() - { - CC = 0; - OpCode = _memory.Read(RPC); - RPC = (RPC + 1) & 0xFFFF; - _executeOpCode[OpCode](); - Cycles += CC; - - return CC; - } - - #region Core Operand Actions - private void GetAddressAbs() // abs - { - EA = _memory.Read(RPC) | (_memory.Read(RPC + 1) << 8); - RPC = (RPC + 2) & 0xFFFF; - } - - private void GetAddressAbsX() // abs, x - { - EA = (_memory.Read(RPC) + RX + (_memory.Read(RPC + 1) << 8)) & 0xFFFF; - RPC = (RPC + 2) & 0xFFFF; - } - - private void GetAddressAbsXCC() // abs, x - { - int ea = _memory.Read(RPC) + RX; - EA = (ea + (_memory.Read(RPC + 1) << 8)) & 0xFFFF; - RPC = (RPC + 2) & 0xFFFF; - CC += (ea >> 8); - } - - private void GetAddressAbsY() // abs, y - { - EA = (_memory.Read(RPC) + RY + (_memory.Read(RPC + 1) << 8)) & 0xFFFF; - RPC = (RPC + 2) & 0xFFFF; - } - - private void GetAddressAbsYCC() // abs, y - { - int ea = _memory.Read(RPC) + RY; - EA = (ea + (_memory.Read(RPC + 1) << 8)) & 0xFFFF; - RPC = (RPC + 2) & 0xFFFF; - CC += (ea >> 8); - } - - private void GetAddressZpg() // zpg - { - EA = _memory.Read(RPC); - RPC = (RPC + 1) & 0xFFFF; - } - - private void GetAddressZpgInd() // (zpg) - { - int zp = _memory.Read(RPC); - EA = _memory.ReadZeroPage(zp) | (_memory.ReadZeroPage((zp + 1) & 0xFF) << 8); - RPC = (RPC + 1) & 0xFFFF; - } - - private void GetAddressZpgIndX() // (zpg, x) - { - int zp = (_memory.Read(RPC) + RX) & 0xFF; - EA = _memory.ReadZeroPage(zp) | (_memory.ReadZeroPage((zp + 1) & 0xFF) << 8); - RPC = (RPC + 1) & 0xFFFF; - } - - private void GetAddressZpgIndY() // (zpg), y - { - int zp = _memory.Read(RPC); - EA = (_memory.ReadZeroPage(zp) + RY + (_memory.ReadZeroPage((zp + 1) & 0xFF) << 8)) & 0xFFFF; - RPC = (RPC + 1) & 0xFFFF; - } - - private void GetAddressZpgIndYCC() // (zpg), y - { - int zp = _memory.Read(RPC); - int ea = _memory.ReadZeroPage(zp) + RY; - EA = (ea + (_memory.ReadZeroPage((zp + 1) & 0xFF) << 8)) & 0xFFFF; - RPC = (RPC + 1) & 0xFFFF; - CC += (ea >> 8); - } - - private void GetAddressZpgX() // zpg, x - { - EA = (_memory.Read(RPC) + RX) & 0xFF; - RPC = (RPC + 1) & 0xFFFF; - } - - private void GetAddressZpgY() // zpg, y - { - EA = (_memory.Read(RPC) + RY) & 0xFF; - RPC = (RPC + 1) & 0xFFFF; - } - - private int Pull() - { - RS = (RS + 1) & 0xFF; - - return _memory.ReadZeroPage(0x0100 + RS); - } - - private void Push(int data) - { - _memory.WriteZeroPage(0x0100 + RS, data); - RS = (RS - 1) & 0xFF; - } - - private int ReadAbs() // abs - { - return _memory.Read(EA); - } - - private int ReadAbsX() // abs, x - { - return _memory.Read(EA); - } - - private int ReadAbsY() // abs, y - { - return _memory.Read(EA); - } - - private int ReadImm() // imm - { - int data = _memory.Read(RPC); - RPC = (RPC + 1) & 0xFFFF; - - return data; - } - - private int ReadZpg() // zpg - { - return _memory.ReadZeroPage(EA); - } - - private int ReadZpgInd() // (zpg) - { - return _memory.Read(EA); - } - - private int ReadZpgIndX() // (zpg, x) - { - return _memory.Read(EA); - } - - private int ReadZpgIndY() // (zpg), y - { - return _memory.Read(EA); - } - - private int ReadZpgX() // zpg, x - { - return _memory.ReadZeroPage(EA); - } - - private int ReadZpgY() // zpg, y - { - return _memory.ReadZeroPage(EA); - } - - private void WriteAbs(int data) // abs - { - _memory.Write(EA, data); - } - - private void WriteAbsX(int data) // abs, x - { - _memory.Write(EA, data); - } - - private void WriteAbsY(int data) // abs, y - { - _memory.Write(EA, data); - } - - private void WriteZpg(int data) // zpg - { - _memory.WriteZeroPage(EA, data); - } - - private void WriteZpgInd(int data) // (zpg) - { - _memory.Write(EA, data); - } - - private void WriteZpgIndX(int data) // (zpg, x) - { - _memory.Write(EA, data); - } - - private void WriteZpgIndY(int data) // (zpg), y - { - _memory.Write(EA, data); - } - - private void WriteZpgX(int data) // zpg, x - { - _memory.WriteZeroPage(EA, data); - } - - private void WriteZpgY(int data) // zpg, y - { - _memory.WriteZeroPage(EA, data); - } - #endregion - - #region Core OpCode Actions - private void ExecuteAdc65N02(int data, int cc) - { - if ((RP & PD) == 0x0) - { - int ra = RA + data + (RP & PC); - RP = RP & ~(PC | PN | PV | PZ) | ((ra >> 8) & PC) | DataPNZ[ra & 0xFF] | (((~(RA ^ data) & (RA ^ (ra & 0xFF))) >> 1) & PV); - RA = ra & 0xFF; - CC += cc; - } - else // decimal - { - int ral = (RA & 0x0F) + (data & 0x0F) + (RP & PC); - int rah = (RA >> 4) + (data >> 4); - if (ral >= 10) - { - ral -= 10; - rah++; - } - int ra = (ral | (rah << 4)) & 0xFF; - RP = RP & ~(PC | PN | PV | PZ) | DataPN[ra] | (((~(RA ^ data) & (RA ^ ra)) >> 1) & PV) | DataPZ[(RA + data + (RP & PC)) & 0xFF]; - if (rah >= 10) - { - rah -= 10; - RP |= PC; - } - RA = (ral | (rah << 4)) & 0xFF; - CC += cc; - } - } - - private void ExecuteAdc65C02(int data, int cc) - { - if ((RP & PD) == 0x0) - { - int ra = RA + data + (RP & PC); - RP = RP & ~(PC | PN | PV | PZ) | ((ra >> 8) & PC) | DataPNZ[ra & 0xFF] | (((~(RA ^ data) & (RA ^ (ra & 0xFF))) >> 1) & PV); - RA = ra & 0xFF; - CC += cc; - } - else // decimal - { - int ral = (RA & 0x0F) + (data & 0x0F) + (RP & PC); - int rah = (RA >> 4) + (data >> 4); - if (ral >= 10) - { - ral -= 10; - rah++; - } - RP &= ~PC; - if (rah >= 10) - { - rah -= 10; - RP |= PC; - } - int ra = (ral | (rah << 4)) & 0xFF; - RP = RP & ~(PN | PV | PZ) | DataPNZ[ra] | (((~(RA ^ data) & (RA ^ ra)) >> 1) & PV); - RA = ra; - CC += cc + 1; - } - } - - private void ExecuteAnd(int data, int cc) - { - RA &= data; - RP = RP & ~(PN | PZ) | DataPNZ[RA]; - CC += cc; - } - - private int ExecuteAsl(int data, int cc) - { - RP = RP & ~PC | ((data >> 7) & PC); - data = (data << 1) & 0xFF; - RP = RP & ~(PN | PZ) | DataPNZ[data]; - CC += cc; - - return data; - } - - private void ExecuteAslImp(int cc) - { - RP = RP & ~PC | ((RA >> 7) & PC); - RA = (RA << 1) & 0xFF; - RP = RP & ~(PN | PZ) | DataPNZ[RA]; - CC += cc; - } - - private void ExecuteBcc(int cc) - { - if ((RP & PC) == 0x0) - { - int rpc = (RPC + 1) & 0xFFFF; - RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; - CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); - } - else - { - RPC = (RPC + 1) & 0xFFFF; - CC += cc; - } - } - - private void ExecuteBcs(int cc) - { - if ((RP & PC) != 0x0) - { - int rpc = (RPC + 1) & 0xFFFF; - RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; - CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); - } - else - { - RPC = (RPC + 1) & 0xFFFF; - CC += cc; - } - } - - private void ExecuteBeq(int cc) - { - if ((RP & PZ) != 0x0) - { - int rpc = (RPC + 1) & 0xFFFF; - RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; - CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); - } - else - { - RPC = (RPC + 1) & 0xFFFF; - CC += cc; - } - } - - private void ExecuteBit(int data, int cc) - { - RP = RP & ~(PN | PV | PZ) | (data & (PN | PV)) | DataPZ[RA & data]; - CC += cc; - } - - private void ExecuteBitImm(int data, int cc) - { - RP = RP & ~PZ | DataPZ[RA & data]; - CC += cc; - } - - private void ExecuteBmi(int cc) - { - if ((RP & PN) != 0x0) - { - int rpc = (RPC + 1) & 0xFFFF; - RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; - CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); - } - else - { - RPC = (RPC + 1) & 0xFFFF; - CC += cc; - } - } - - private void ExecuteBne(int cc) - { - if ((RP & PZ) == 0x0) - { - int rpc = (RPC + 1) & 0xFFFF; - RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; - CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); - } - else - { - RPC = (RPC + 1) & 0xFFFF; - CC += cc; - } - } - - private void ExecuteBpl(int cc) - { - if ((RP & PN) == 0x0) - { - int rpc = (RPC + 1) & 0xFFFF; - RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; - CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); - } - else - { - RPC = (RPC + 1) & 0xFFFF; - CC += cc; - } - } - - private void ExecuteBra(int cc) - { - int rpc = (RPC + 1) & 0xFFFF; - RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; - CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); - } - - private void ExecuteBrk(int cc) - { - int rpc = (RPC + 1) & 0xFFFF; // [4-18] - Push(rpc >> 8); - Push(rpc & 0xFF); - Push(RP | PB); - RP |= PI; - RPC = _memory.Read(0xFFFE) | (_memory.Read(0xFFFF) << 8); - CC += cc; - } - - private void ExecuteBvc(int cc) - { - if ((RP & PV) == 0x0) - { - int rpc = (RPC + 1) & 0xFFFF; - RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; - CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); - } - else - { - RPC = (RPC + 1) & 0xFFFF; - CC += cc; - } - } - - private void ExecuteBvs(int cc) - { - if ((RP & PV) != 0x0) - { - int rpc = (RPC + 1) & 0xFFFF; - RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; - CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); - } - else - { - RPC = (RPC + 1) & 0xFFFF; - CC += cc; - } - } - - private void ExecuteClc(int cc) - { - RP &= ~PC; - CC += cc; - } - - private void ExecuteCld(int cc) - { - RP &= ~PD; - CC += cc; - } - - private void ExecuteCli(int cc) - { - RP &= ~PI; - CC += cc; - } - - private void ExecuteClv(int cc) - { - RP &= ~PV; - CC += cc; - } - - private void ExecuteCmp(int data, int cc) - { - int diff = RA - data; - RP = RP & ~(PC | PN | PZ) | ((~diff >> 8) & PC) | DataPNZ[diff & 0xFF]; - CC += cc; - } - - private void ExecuteCpx(int data, int cc) - { - int diff = RX - data; - RP = RP & ~(PC | PN | PZ) | ((~diff >> 8) & PC) | DataPNZ[diff & 0xFF]; - CC += cc; - } - - private void ExecuteCpy(int data, int cc) - { - int diff = RY - data; - RP = RP & ~(PC | PN | PZ) | ((~diff >> 8) & PC) | DataPNZ[diff & 0xFF]; - CC += cc; - } - - private void ExecuteDea(int cc) - { - RA = (RA - 1) & 0xFF; - RP = RP & ~(PN | PZ) | DataPNZ[RA]; - CC += cc; - } - - private int ExecuteDec(int data, int cc) - { - data = (data - 1) & 0xFF; - RP = RP & ~(PN | PZ) | DataPNZ[data]; - CC += cc; - - return data; - } - - private void ExecuteDex(int cc) - { - RX = (RX - 1) & 0xFF; - RP = RP & ~(PN | PZ) | DataPNZ[RX]; - CC += cc; - } - - private void ExecuteDey(int cc) - { - RY = (RY - 1) & 0xFF; - RP = RP & ~(PN | PZ) | DataPNZ[RY]; - CC += cc; - } - - private void ExecuteEor(int data, int cc) - { - RA ^= data; - RP = RP & ~(PN | PZ) | DataPNZ[RA]; - CC += cc; - } - - private void ExecuteIna(int cc) - { - RA = (RA + 1) & 0xFF; - RP = RP & ~(PN | PZ) | DataPNZ[RA]; - CC += cc; - } - - private int ExecuteInc(int data, int cc) - { - data = (data + 1) & 0xFF; - RP = RP & ~(PN | PZ) | DataPNZ[data]; - CC += cc; - - return data; - } - - private void ExecuteInx(int cc) - { - RX = (RX + 1) & 0xFF; - RP = RP & ~(PN | PZ) | DataPNZ[RX]; - CC += cc; - } - - private void ExecuteIny(int cc) - { - RY = (RY + 1) & 0xFF; - RP = RP & ~(PN | PZ) | DataPNZ[RY]; - CC += cc; - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - private void ExecuteIrq(int cc) - { - Push(RPC >> 8); - Push(RPC & 0xFF); - Push(RP & ~PB); - RP |= PI; - if (Is65C02) // [C-10] - { - RP &= ~PD; - } - RPC = _memory.Read(0xFFFE) | (_memory.Read(0xFFFF) << 8); - CC += cc; - } - - private void ExecuteJmpAbs(int cc) // jmp abs - { - RPC = _memory.Read(RPC) | (_memory.Read(RPC + 1) << 8); - CC += cc; - } - - private void ExecuteJmpAbsInd65N02(int cc) // jmp (abs) - { - int ea = _memory.Read(RPC) | (_memory.Read(RPC + 1) << 8); - RPC = _memory.Read(ea) | (_memory.Read((ea & 0xFF00) | ((ea + 1) & 0x00FF)) << 8); - CC += cc; - } - - private void ExecuteJmpAbsInd65C02(int cc) // jmp (abs) - { - int ea = _memory.Read(RPC) | (_memory.Read(RPC + 1) << 8); - RPC = _memory.Read(ea) | (_memory.Read(ea + 1) << 8); - CC += cc; - } - - private void ExecuteJmpAbsIndX(int cc) // jmp (abs, x) - { - int ea = (_memory.Read(RPC) + RX + (_memory.Read(RPC + 1) << 8)) & 0xFFFF; - RPC = _memory.Read(ea) | (_memory.Read(ea + 1) << 8); - CC += cc; - } - - private void ExecuteJsr(int cc) // jsr abs - { - int rpc = (RPC + 1) & 0xFFFF; - RPC = _memory.Read(RPC) | (_memory.Read(RPC + 1) << 8); - Push(rpc >> 8); - Push(rpc & 0xFF); - CC += cc; - } - - private void ExecuteLda(int data, int cc) - { - RA = data; - RP = RP & ~(PN | PZ) | DataPNZ[RA]; - CC += cc; - } - - private void ExecuteLdx(int data, int cc) - { - RX = data; - RP = RP & ~(PN | PZ) | DataPNZ[RX]; - CC += cc; - } - - private void ExecuteLdy(int data, int cc) - { - RY = data; - RP = RP & ~(PN | PZ) | DataPNZ[RY]; - CC += cc; - } - - private int ExecuteLsr(int data, int cc) - { - RP = RP & ~PC | (data & PC); - data >>= 1; - RP = RP & ~(PN | PZ) | DataPNZ[data]; - CC += cc; - - return data; - } - - private void ExecuteLsrImp(int cc) - { - RP = RP & ~PC | (RA & PC); - RA >>= 1; - RP = RP & ~(PN | PZ) | DataPNZ[RA]; - CC += cc; - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - private void ExecuteNmi(int cc) - { - Push(RPC >> 8); - Push(RPC & 0xFF); - Push(RP & ~PB); - RP |= PI; - if (Is65C02) // [C-10] - { - RP &= ~PD; - } - RPC = _memory.Read(0xFFFA) | (_memory.Read(0xFFFB) << 8); - CC += cc; - } - - private void ExecuteNop(int cc) - { - CC += cc; - } - - private void ExecuteNop(int data, int cc) - { - RPC = (RPC + data) & 0xFFFF; - CC += cc; - } - - private void ExecuteOra(int data, int cc) - { - RA |= data; - RP = RP & ~(PN | PZ) | DataPNZ[RA]; - CC += cc; - } - - private void ExecutePha(int cc) - { - Push(RA); - CC += cc; - } - - private void ExecutePhp(int cc) - { - Push(RP | PB); // [4-18] - CC += cc; - } - - private void ExecutePhx(int cc) - { - Push(RX); - CC += cc; - } - - private void ExecutePhy(int cc) - { - Push(RY); - CC += cc; - } - - private void ExecutePla(int cc) - { - RA = Pull(); - RP = RP & ~(PN | PZ) | DataPNZ[RA]; - CC += cc; - } - - private void ExecutePlp(int cc) - { - RP = Pull(); - CC += cc; - } - - private void ExecutePlx(int cc) - { - RX = Pull(); - RP = RP & ~(PN | PZ) | DataPNZ[RX]; - CC += cc; - } - - private void ExecutePly(int cc) - { - RY = Pull(); - RP = RP & ~(PN | PZ) | DataPNZ[RY]; - CC += cc; - } - - private int ExecuteRol(int data, int cc) - { - int c = RP & PC; - RP = RP & ~PC | ((data >> 7) & PC); - data = ((data << 1) | c) & 0xFF; - RP = RP & ~(PN | PZ) | DataPNZ[data]; - CC += cc; - - return data; - } - - private void ExecuteRolImp(int cc) - { - int c = RP & PC; - RP = RP & ~PC | ((RA >> 7) & PC); - RA = ((RA << 1) | c) & 0xFF; - RP = RP & ~(PN | PZ) | DataPNZ[RA]; - CC += cc; - } - - private int ExecuteRor(int data, int cc) - { - int c = RP & PC; - RP = RP & ~PC | (data & PC); - data = (c << 7) | (data >> 1); - RP = RP & ~(PN | PZ) | DataPNZ[data]; - CC += cc; - - return data; - } - - private void ExecuteRorImp(int cc) - { - int c = RP & PC; - RP = RP & ~PC | (RA & PC); - RA = (c << 7) | (RA >> 1); - RP = RP & ~(PN | PZ) | DataPNZ[RA]; - CC += cc; - } - - private void ExecuteRti(int cc) - { - RP = Pull(); - int rpc = Pull(); - RPC = rpc | (Pull() << 8); - CC += cc; - } - - private void ExecuteRts(int cc) - { - int rpc = Pull(); - RPC = (rpc + 1 + (Pull() << 8)) & 0xFFFF; - CC += cc; - } - - private void ExecuteSbc65N02(int data, int cc) - { - if ((RP & PD) == 0x0) - { - int ra = RA - data - (~RP & PC); - RP = RP & ~(PC | PN | PV | PZ) | ((~ra >> 8) & PC) | DataPNZ[ra & 0xFF] | ((((RA ^ data) & (RA ^ (ra & 0xFF))) >> 1) & PV); - RA = ra & 0xFF; - CC += cc; - } - else // decimal - { - int ral = (RA & 0x0F) - (data & 0x0F) - (~RP & PC); - int rah = (RA >> 4) - (data >> 4); - if (ral < 0) - { - ral += 10; - rah--; - } - int ra = (ral | (rah << 4)) & 0xFF; - RP = RP & ~(PN | PV | PZ) | PC | DataPN[ra] | ((((RA ^ data) & (RA ^ ra)) >> 1) & PV) | DataPZ[(RA - data - (~RP & PC)) & 0xFF]; - if (rah < 0) - { - rah += 10; - RP &= ~PC; - } - RA = (ral | (rah << 4)) & 0xFF; - CC += cc; - } - } - - private void ExecuteSbc65C02(int data, int cc) - { - if ((RP & PD) == 0x0) - { - int ra = RA - data - (~RP & PC); - RP = RP & ~(PC | PN | PV | PZ) | ((~ra >> 8) & PC) | DataPNZ[ra & 0xFF] | ((((RA ^ data) & (RA ^ (ra & 0xFF))) >> 1) & PV); - RA = ra & 0xFF; - CC += cc; - } - else // decimal - { - int ral = (RA & 0x0F) - (data & 0x0F) - (~RP & PC); - int rah = (RA >> 4) - (data >> 4); - if (ral < 0) - { - ral += 10; - rah--; - } - RP |= PC; - if (rah < 0) - { - rah += 10; - RP &= ~PC; - } - int ra = (ral | (rah << 4)) & 0xFF; - RP = RP & ~(PN | PV | PZ) | DataPNZ[ra] | ((((RA ^ data) & (RA ^ ra)) >> 1) & PV); - RA = ra; - CC += cc + 1; - } - } - - private void ExecuteSec(int cc) - { - RP |= PC; - CC += cc; - } - - private void ExecuteSed(int cc) - { - RP |= PD; - CC += cc; - } - - private void ExecuteSei(int cc) - { - RP |= PI; - CC += cc; - } - - private void ExecuteSta(int cc) - { - CC += cc; - } - - private void ExecuteStx(int cc) - { - CC += cc; - } - - private void ExecuteSty(int cc) - { - CC += cc; - } - - private void ExecuteStz(int cc) - { - CC += cc; - } - - private void ExecuteTax(int cc) - { - RX = RA; - RP = RP & ~(PN | PZ) | DataPNZ[RX]; - CC += cc; - } - - private void ExecuteTay(int cc) - { - RY = RA; - RP = RP & ~(PN | PZ) | DataPNZ[RY]; - CC += cc; - } - - private int ExecuteTrb(int data, int cc) - { - RP = RP & ~PZ | DataPZ[RA & data]; - data &= ~RA; - CC += cc; - - return data; - } - - private int ExecuteTsb(int data, int cc) - { - RP = RP & ~PZ | DataPZ[RA & data]; - data |= RA; - CC += cc; - - return data; - } - - private void ExecuteTsx(int cc) - { - RX = RS; - RP = RP & ~(PN | PZ) | DataPNZ[RX]; - CC += cc; - } - - private void ExecuteTxa(int cc) - { - RA = RX; - RP = RP & ~(PN | PZ) | DataPNZ[RA]; - CC += cc; - } - - private void ExecuteTxs(int cc) - { - RS = RX; - CC += cc; - } - - private void ExecuteTya(int cc) - { - RA = RY; - RP = RP & ~(PN | PZ) | DataPNZ[RA]; - CC += cc; - } - #endregion - - #region 6502 OpCode Actions - private void Execute65X02And21() // and (zpg, x) - { - GetAddressZpgIndX(); - ExecuteAnd(ReadZpgIndX(), 6); - } - - private void Execute65X02And25() // and zpg - { - GetAddressZpg(); - ExecuteAnd(ReadZpg(), 3); - } - - private void Execute65X02And29() // and imm - { - ExecuteAnd(ReadImm(), 2); - } - - private void Execute65X02And2D() // and abs - { - GetAddressAbs(); - ExecuteAnd(ReadAbs(), 4); - } - - private void Execute65X02And31() // and (zpg), y - { - GetAddressZpgIndYCC(); - ExecuteAnd(ReadZpgIndY(), 5); - } - - private void Execute65X02And35() // and zpg, x - { - GetAddressZpgX(); - ExecuteAnd(ReadZpgX(), 4); - } - - private void Execute65X02And39() // and abs, y - { - GetAddressAbsYCC(); - ExecuteAnd(ReadAbsY(), 4); - } - - private void Execute65X02And3D() // and abs, x - { - GetAddressAbsXCC(); - ExecuteAnd(ReadAbsX(), 4); - } - - private void Execute65X02Asl06() // asl zpg - { - GetAddressZpg(); - WriteZpg(ExecuteAsl(ReadZpg(), 5)); - } - - private void Execute65X02Asl0A() // asl imp - { - ExecuteAslImp(2); - } - - private void Execute65X02Asl0E() // asl abs - { - GetAddressAbs(); - WriteAbs(ExecuteAsl(ReadAbs(), 6)); - } - - private void Execute65X02Asl16() // asl zpg, x - { - GetAddressZpgX(); - WriteZpgX(ExecuteAsl(ReadZpgX(), 6)); - } - - private void Execute65X02Bcc90() // bcc rel - { - ExecuteBcc(2); - } - - private void Execute65X02BcsB0() // bcs rel - { - ExecuteBcs(2); - } - - private void Execute65X02BeqF0() // beq rel - { - ExecuteBeq(2); - } - - private void Execute65X02Bit24() // bit zpg - { - GetAddressZpg(); - ExecuteBit(ReadZpg(), 3); - } - - private void Execute65X02Bit2C() // bit abs - { - GetAddressAbs(); - ExecuteBit(ReadAbs(), 4); - } - - private void Execute65X02Bmi30() // bmi rel - { - ExecuteBmi(2); - } - - private void Execute65X02BneD0() // bne rel - { - ExecuteBne(2); - } - - private void Execute65X02Bpl10() // bpl rel - { - ExecuteBpl(2); - } - - private void Execute65X02Brk00() // brk imp - { - ExecuteBrk(7); - } - - private void Execute65X02Bvc50() // bvc rel - { - ExecuteBvc(2); - } - - private void Execute65X02Bvs70() // bvs rel - { - ExecuteBvs(2); - } - - private void Execute65X02Clc18() // clc imp - { - ExecuteClc(2); - } - - private void Execute65X02CldD8() // cld imp - { - ExecuteCld(2); - } - - private void Execute65X02Cli58() // cli imp - { - ExecuteCli(2); - } - - private void Execute65X02ClvB8() // clv imp - { - ExecuteClv(2); - } - - private void Execute65X02CmpC1() // cmp (zpg, x) - { - GetAddressZpgIndX(); - ExecuteCmp(ReadZpgIndX(), 6); - } - - private void Execute65X02CmpC5() // cmp zpg - { - GetAddressZpg(); - ExecuteCmp(ReadZpg(), 3); - } - - private void Execute65X02CmpC9() // cmp imm - { - ExecuteCmp(ReadImm(), 2); - } - - private void Execute65X02CmpCD() // cmp abs - { - GetAddressAbs(); - ExecuteCmp(ReadAbs(), 4); - } - - private void Execute65X02CmpD1() // cmp (zpg), y - { - GetAddressZpgIndYCC(); - ExecuteCmp(ReadZpgIndY(), 5); - } - - private void Execute65X02CmpD5() // cmp zpg, x - { - GetAddressZpgX(); - ExecuteCmp(ReadZpgX(), 4); - } - - private void Execute65X02CmpD9() // cmp abs, y - { - GetAddressAbsYCC(); - ExecuteCmp(ReadAbsY(), 4); - } - - private void Execute65X02CmpDD() // cmp abs, x - { - GetAddressAbsXCC(); - ExecuteCmp(ReadAbsX(), 4); - } - - private void Execute65X02CpxE0() // cpx imm - { - ExecuteCpx(ReadImm(), 2); - } - - private void Execute65X02CpxE4() // cpx zpg - { - GetAddressZpg(); - ExecuteCpx(ReadZpg(), 3); - } - - private void Execute65X02CpxEC() // cpx abs - { - GetAddressAbs(); - ExecuteCpx(ReadAbs(), 4); - } - - private void Execute65X02CpyC0() // cpy imm - { - ExecuteCpy(ReadImm(), 2); - } - - private void Execute65X02CpyC4() // cpy zpg - { - GetAddressZpg(); - ExecuteCpy(ReadZpg(), 3); - } - - private void Execute65X02CpyCC() // cpy abs - { - GetAddressAbs(); - ExecuteCpy(ReadAbs(), 4); - } - - private void Execute65X02DecC6() // dec zpg - { - GetAddressZpg(); - WriteZpg(ExecuteDec(ReadZpg(), 5)); - } - - private void Execute65X02DecCE() // dec abs - { - GetAddressAbs(); - WriteAbs(ExecuteDec(ReadAbs(), 6)); - } - - private void Execute65X02DecD6() // dec zpg, x - { - GetAddressZpgX(); - WriteZpgX(ExecuteDec(ReadZpgX(), 6)); - } - - private void Execute65X02DexCA() // dex imp - { - ExecuteDex(2); - } - - private void Execute65X02Dey88() // dey imp - { - ExecuteDey(2); - } - - private void Execute65X02Eor41() // eor (zpg, x) - { - GetAddressZpgIndX(); - ExecuteEor(ReadZpgIndX(), 6); - } - - private void Execute65X02Eor45() // eor zpg - { - GetAddressZpg(); - ExecuteEor(ReadZpg(), 3); - } - - private void Execute65X02Eor49() // eor imm - { - ExecuteEor(ReadImm(), 2); - } - - private void Execute65X02Eor4D() // eor abs - { - GetAddressAbs(); - ExecuteEor(ReadAbs(), 4); - } - - private void Execute65X02Eor51() // eor (zpg), y - { - GetAddressZpgIndYCC(); - ExecuteEor(ReadZpgIndY(), 5); - } - - private void Execute65X02Eor55() // eor zpg, x - { - GetAddressZpgX(); - ExecuteEor(ReadZpgX(), 4); - } - - private void Execute65X02Eor59() // eor abs, y - { - GetAddressAbsYCC(); - ExecuteEor(ReadAbsY(), 4); - } - - private void Execute65X02Eor5D() // eor abs, x - { - GetAddressAbsXCC(); - ExecuteEor(ReadAbsX(), 4); - } - - private void Execute65X02IncE6() // inc zpg - { - GetAddressZpg(); - WriteZpg(ExecuteInc(ReadZpg(), 5)); - } - - private void Execute65X02IncEE() // inc abs - { - GetAddressAbs(); - WriteAbs(ExecuteInc(ReadAbs(), 6)); - } - - private void Execute65X02IncF6() // inc zpg, x - { - GetAddressZpgX(); - WriteZpgX(ExecuteInc(ReadZpgX(), 6)); - } - - private void Execute65X02InxE8() // inx imp - { - ExecuteInx(2); - } - - private void Execute65X02InyC8() // iny imp - { - ExecuteIny(2); - } - - private void Execute65X02Jmp4C() // jmp abs - { - ExecuteJmpAbs(3); - } - - private void Execute65X02Jsr20() // jsr abs - { - ExecuteJsr(6); - } - - private void Execute65X02LdaA1() // lda (zpg, x) - { - GetAddressZpgIndX(); - ExecuteLda(ReadZpgIndX(), 6); - } - - private void Execute65X02LdaA5() // lda zpg - { - GetAddressZpg(); - ExecuteLda(ReadZpg(), 3); - } - - private void Execute65X02LdaA9() // lda imm - { - ExecuteLda(ReadImm(), 2); - } - - private void Execute65X02LdaAD() // lda abs - { - GetAddressAbs(); - ExecuteLda(ReadAbs(), 4); - } - - private void Execute65X02LdaB1() // lda (zpg), y - { - GetAddressZpgIndYCC(); - ExecuteLda(ReadZpgIndY(), 5); - } - - private void Execute65X02LdaB5() // lda zpg, x - { - GetAddressZpgX(); - ExecuteLda(ReadZpgX(), 4); - } - - private void Execute65X02LdaB9() // lda abs, y - { - GetAddressAbsYCC(); - ExecuteLda(ReadAbsY(), 4); - } - - private void Execute65X02LdaBD() // lda abs, x - { - GetAddressAbsXCC(); - ExecuteLda(ReadAbsX(), 4); - } - - private void Execute65X02LdxA2() // ldx imm - { - ExecuteLdx(ReadImm(), 2); - } - - private void Execute65X02LdxA6() // ldx zpg - { - GetAddressZpg(); - ExecuteLdx(ReadZpg(), 3); - } - - private void Execute65X02LdxAE() // ldx abs - { - GetAddressAbs(); - ExecuteLdx(ReadAbs(), 4); - } - - private void Execute65X02LdxB6() // ldx zpg, y - { - GetAddressZpgY(); - ExecuteLdx(ReadZpgY(), 4); - } - - private void Execute65X02LdxBE() // ldx abs, y - { - GetAddressAbsYCC(); - ExecuteLdx(ReadAbsY(), 4); - } - - private void Execute65X02LdyA0() // ldy imm - { - ExecuteLdy(ReadImm(), 2); - } - - private void Execute65X02LdyA4() // ldy zpg - { - GetAddressZpg(); - ExecuteLdy(ReadZpg(), 3); - } - - private void Execute65X02LdyAC() // ldy abs - { - GetAddressAbs(); - ExecuteLdy(ReadAbs(), 4); - } - - private void Execute65X02LdyB4() // ldy zpg, x - { - GetAddressZpgX(); - ExecuteLdy(ReadZpgX(), 4); - } - - private void Execute65X02LdyBC() // ldy abs, x - { - GetAddressAbsXCC(); - ExecuteLdy(ReadAbsX(), 4); - } - - private void Execute65X02Lsr46() // lsr zpg - { - GetAddressZpg(); - WriteZpg(ExecuteLsr(ReadZpg(), 5)); - } - - private void Execute65X02Lsr4A() // lsr imp - { - ExecuteLsrImp(2); - } - - private void Execute65X02Lsr4E() // lsr abs - { - GetAddressAbs(); - WriteAbs(ExecuteLsr(ReadAbs(), 6)); - } - - private void Execute65X02Lsr56() // lsr zpg, x - { - GetAddressZpgX(); - WriteZpgX(ExecuteLsr(ReadZpgX(), 6)); - } - - private void Execute65X02NopEA() // nop imp - { - ExecuteNop(2); - } - - private void Execute65X02Ora01() // ora (zpg, x) - { - GetAddressZpgIndX(); - ExecuteOra(ReadZpgIndX(), 6); - } - - private void Execute65X02Ora05() // ora zpg - { - GetAddressZpg(); - ExecuteOra(ReadZpg(), 3); - } - - private void Execute65X02Ora09() // ora imm - { - ExecuteOra(ReadImm(), 2); - } - - private void Execute65X02Ora0D() // ora abs - { - GetAddressAbs(); - ExecuteOra(ReadAbs(), 4); - } - - private void Execute65X02Ora11() // ora (zpg), y - { - GetAddressZpgIndYCC(); - ExecuteOra(ReadZpgIndY(), 5); - } - - private void Execute65X02Ora15() // ora zpg, x - { - GetAddressZpgX(); - ExecuteOra(ReadZpgX(), 4); - } - - private void Execute65X02Ora19() // ora abs, y - { - GetAddressAbsYCC(); - ExecuteOra(ReadAbsY(), 4); - } - - private void Execute65X02Ora1D() // ora abs, x - { - GetAddressAbsXCC(); - ExecuteOra(ReadAbsX(), 4); - } - - private void Execute65X02Pha48() // pha imp - { - ExecutePha(3); - } - - private void Execute65X02Php08() // php imp - { - ExecutePhp(3); - } - - private void Execute65X02Pla68() // pla imp - { - ExecutePla(4); - } - - private void Execute65X02Plp28() // plp imp - { - ExecutePlp(4); - } - - private void Execute65X02Rol26() // rol zpg - { - GetAddressZpg(); - WriteZpg(ExecuteRol(ReadZpg(), 5)); - } - - private void Execute65X02Rol2A() // rol imp - { - ExecuteRolImp(2); - } - - private void Execute65X02Rol2E() // rol abs - { - GetAddressAbs(); - WriteAbs(ExecuteRol(ReadAbs(), 6)); - } - - private void Execute65X02Rol36() // rol zpg, x - { - GetAddressZpgX(); - WriteZpgX(ExecuteRol(ReadZpgX(), 6)); - } - - private void Execute65X02Ror66() // ror zpg - { - GetAddressZpg(); - WriteZpg(ExecuteRor(ReadZpg(), 5)); - } - - private void Execute65X02Ror6A() // ror imp - { - ExecuteRorImp(2); - } - - private void Execute65X02Ror6E() // ror abs - { - GetAddressAbs(); - WriteAbs(ExecuteRor(ReadAbs(), 6)); - } - - private void Execute65X02Ror76() // ror zpg, x - { - GetAddressZpgX(); - WriteZpgX(ExecuteRor(ReadZpgX(), 6)); - } - - private void Execute65X02Rti40() // rti imp - { - ExecuteRti(6); - } - - private void Execute65X02Rts60() // rts imp - { - ExecuteRts(6); - } - - private void Execute65X02Sec38() // sec imp - { - ExecuteSec(2); - } - - private void Execute65X02SedF8() // sed imp - { - ExecuteSed(2); - } - - private void Execute65X02Sei78() // sei imp - { - ExecuteSei(2); - } - - private void Execute65X02Sta81() // sta (zpg, x) - { - GetAddressZpgIndX(); - WriteZpgIndX(RA); - ExecuteSta(6); - } - - private void Execute65X02Sta85() // sta zpg - { - GetAddressZpg(); - WriteZpg(RA); - ExecuteSta(3); - } - - private void Execute65X02Sta8D() // sta abs - { - GetAddressAbs(); - WriteAbs(RA); - ExecuteSta(4); - } - - private void Execute65X02Sta91() // sta (zpg), y - { - GetAddressZpgIndY(); - WriteZpgIndY(RA); - ExecuteSta(6); - } - - private void Execute65X02Sta95() // sta zpg, x - { - GetAddressZpgX(); - WriteZpgX(RA); - ExecuteSta(4); - } - - private void Execute65X02Sta99() // sta abs, y - { - GetAddressAbsY(); - WriteAbsY(RA); - ExecuteSta(5); - } - - private void Execute65X02Sta9D() // sta abs, x - { - GetAddressAbsX(); - WriteAbsX(RA); - ExecuteSta(5); - } - - private void Execute65X02Stx86() // stx zpg - { - GetAddressZpg(); - WriteZpg(RX); - ExecuteStx(3); - } - - private void Execute65X02Stx8E() // stx abs - { - GetAddressAbs(); - WriteAbs(RX); - ExecuteStx(4); - } - - private void Execute65X02Stx96() // stx zpg, y - { - GetAddressZpgY(); - WriteZpgY(RX); - ExecuteStx(4); - } - - private void Execute65X02Sty84() // sty zpg - { - GetAddressZpg(); - WriteZpg(RY); - ExecuteSty(3); - } - - private void Execute65X02Sty8C() // sty abs - { - GetAddressAbs(); - WriteAbs(RY); - ExecuteSty(4); - } - - private void Execute65X02Sty94() // sty zpg, x - { - GetAddressZpgX(); - WriteZpgX(RY); - ExecuteSty(4); - } - - private void Execute65X02TaxAA() // tax imp - { - ExecuteTax(2); - } - - private void Execute65X02TayA8() // tay imp - { - ExecuteTay(2); - } - - private void Execute65X02TsxBA() // tsx imp - { - ExecuteTsx(2); - } - - private void Execute65X02Txa8A() // txa imp - { - ExecuteTxa(2); - } - - private void Execute65X02Txs9A() // txs imp - { - ExecuteTxs(2); - } - - private void Execute65X02Tya98() // tya imp - { - ExecuteTya(2); - } - #endregion - - #region 65N02 OpCode Actions - private void Execute65N02Adc61() // adc (zpg, x) - { - GetAddressZpgIndX(); - ExecuteAdc65N02(ReadZpgIndX(), 6); - } - - private void Execute65N02Adc65() // adc zpg - { - GetAddressZpg(); - ExecuteAdc65N02(ReadZpg(), 3); - } - - private void Execute65N02Adc69() // adc imm - { - ExecuteAdc65N02(ReadImm(), 2); - } - - private void Execute65N02Adc6D() // adc abs - { - GetAddressAbs(); - ExecuteAdc65N02(ReadAbs(), 4); - } - - private void Execute65N02Adc71() // adc (zpg), y - { - GetAddressZpgIndYCC(); - ExecuteAdc65N02(ReadZpgIndY(), 5); - } - - private void Execute65N02Adc75() // adc zpg, x - { - GetAddressZpgX(); - ExecuteAdc65N02(ReadZpgX(), 4); - } - - private void Execute65N02Adc79() // adc abs, y - { - GetAddressAbsYCC(); - ExecuteAdc65N02(ReadAbsY(), 4); - } - - private void Execute65N02Adc7D() // adc abs, x - { - GetAddressAbsXCC(); - ExecuteAdc65N02(ReadAbsX(), 4); - } - - private void Execute65N02Asl1E() // asl abs, x - { - GetAddressAbsX(); - WriteAbsX(ExecuteAsl(ReadAbsX(), 7)); - } - - private void Execute65N02DecDE() // dec abs, x - { - GetAddressAbsX(); - WriteAbsX(ExecuteDec(ReadAbsX(), 7)); - } - - private void Execute65N02IncFE() // inc abs, x - { - GetAddressAbsX(); - WriteAbsX(ExecuteInc(ReadAbsX(), 7)); - } - - private void Execute65N02Jmp6C() // jmp (abs) - { - ExecuteJmpAbsInd65N02(5); - } - - private void Execute65N02Lsr5E() // lsr abs, x - { - GetAddressAbsX(); - WriteAbsX(ExecuteLsr(ReadAbsX(), 7)); - } - - private void Execute65N02Nop02() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02Nop03() // nop imp1 - { - ExecuteNop(1, 6); - } - - private void Execute65N02Nop04() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02Nop07() // nop imp1 - { - ExecuteNop(1, 5); - } - - private void Execute65N02Nop0B() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02Nop0C() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02Nop0F() // nop imp2 - { - ExecuteNop(2, 6); - } - - private void Execute65N02Nop12() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02Nop13() // nop imp1 - { - ExecuteNop(1, 6); - } - - private void Execute65N02Nop14() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02Nop17() // nop imp1 - { - ExecuteNop(1, 6); - } - - private void Execute65N02Nop1A() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02Nop1B() // nop imp2 - { - ExecuteNop(2, 6); - } - - private void Execute65N02Nop1C() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02Nop1F() // nop imp2 - { - ExecuteNop(2, 6); - } - - private void Execute65N02Nop22() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02Nop23() // nop imp1 - { - ExecuteNop(1, 6); - } - - private void Execute65N02Nop27() // nop imp1 - { - ExecuteNop(1, 3); - } - - private void Execute65N02Nop2B() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02Nop2F() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02Nop32() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02Nop33() // nop imp1 - { - ExecuteNop(1, 5); - } - - private void Execute65N02Nop34() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02Nop37() // nop imp1 - { - ExecuteNop(1, 4); - } - - private void Execute65N02Nop3A() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02Nop3B() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02Nop3C() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02Nop3F() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02Nop42() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02Nop43() // nop imp1 - { - ExecuteNop(1, 6); - } - - private void Execute65N02Nop44() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02Nop47() // nop imp1 - { - ExecuteNop(1, 3); - } - - private void Execute65N02Nop4B() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02Nop4F() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02Nop52() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02Nop53() // nop imp1 - { - ExecuteNop(1, 5); - } - - private void Execute65N02Nop54() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02Nop57() // nop imp1 - { - ExecuteNop(1, 4); - } - - private void Execute65N02Nop5A() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02Nop5B() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02Nop5C() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02Nop5F() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02Nop62() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02Nop63() // nop imp1 - { - ExecuteNop(1, 6); - } - - private void Execute65N02Nop64() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02Nop67() // nop imp1 - { - ExecuteNop(1, 3); - } - - private void Execute65N02Nop6B() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02Nop6F() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02Nop72() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02Nop73() // nop imp1 - { - ExecuteNop(1, 5); - } - - private void Execute65N02Nop74() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02Nop77() // nop imp1 - { - ExecuteNop(1, 4); - } - - private void Execute65N02Nop7A() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02Nop7B() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02Nop7C() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02Nop7F() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02Nop80() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02Nop82() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02Nop83() // nop imp1 - { - ExecuteNop(1, 4); - } - - private void Execute65N02Nop87() // nop imp1 - { - ExecuteNop(1, 3); - } - - private void Execute65N02Nop89() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02Nop8B() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02Nop8F() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02Nop92() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02Nop93() // nop imp1 - { - ExecuteNop(1, 6); - } - - private void Execute65N02Nop97() // nop imp1 - { - ExecuteNop(1, 4); - } - - private void Execute65N02Nop9B() // nop imp2 - { - ExecuteNop(2, 5); - } - - private void Execute65N02Nop9C() // nop imp2 - { - ExecuteNop(2, 5); - } - - private void Execute65N02Nop9E() // nop imp2 - { - ExecuteNop(2, 5); - } - - private void Execute65N02Nop9F() // nop imp2 - { - ExecuteNop(2, 5); - } - - private void Execute65N02NopA3() // nop imp1 - { - ExecuteNop(1, 6); - } - - private void Execute65N02NopA7() // nop imp1 - { - ExecuteNop(1, 3); - } - - private void Execute65N02NopAB() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02NopAF() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02NopB2() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02NopB3() // nop imp1 - { - ExecuteNop(1, 5); - } - - private void Execute65N02NopB7() // nop imp1 - { - ExecuteNop(1, 4); - } - - private void Execute65N02NopBB() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02NopBF() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02NopC2() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02NopC3() // nop imp1 - { - ExecuteNop(1, 6); - } - - private void Execute65N02NopC7() // nop imp1 - { - ExecuteNop(1, 5); - } - - private void Execute65N02NopCB() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02NopCF() // nop imp2 - { - ExecuteNop(2, 6); - } - - private void Execute65N02NopD2() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02NopD3() // nop imp1 - { - ExecuteNop(1, 6); - } - - private void Execute65N02NopD4() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02NopD7() // nop imp1 - { - ExecuteNop(1, 6); - } - - private void Execute65N02NopDA() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02NopDB() // nop imp2 - { - ExecuteNop(2, 6); - } - - private void Execute65N02NopDC() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02NopDF() // nop imp2 - { - ExecuteNop(2, 6); - } - - private void Execute65N02NopE2() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02NopE3() // nop imp1 - { - ExecuteNop(1, 6); - } - - private void Execute65N02NopE7() // nop imp1 - { - ExecuteNop(1, 5); - } - - private void Execute65N02NopEB() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02NopEF() // nop imp2 - { - ExecuteNop(2, 6); - } - - private void Execute65N02NopF2() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02NopF3() // nop imp1 - { - ExecuteNop(1, 6); - } - - private void Execute65N02NopF4() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65N02NopF7() // nop imp1 - { - ExecuteNop(1, 6); - } - - private void Execute65N02NopFA() // nop imp0 - { - ExecuteNop(0, 2); - } - - private void Execute65N02NopFB() // nop imp2 - { - ExecuteNop(2, 6); - } - - private void Execute65N02NopFC() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65N02NopFF() // nop imp2 - { - ExecuteNop(2, 6); - } - - private void Execute65N02Rol3E() // rol abs, x - { - GetAddressAbsX(); - WriteAbsX(ExecuteRol(ReadAbsX(), 7)); - } - - private void Execute65N02Ror7E() // ror abs, x - { - GetAddressAbsX(); - WriteAbsX(ExecuteRor(ReadAbsX(), 7)); - } - - private void Execute65N02SbcE1() // sbc (zpg, x) - { - GetAddressZpgIndX(); - ExecuteSbc65N02(ReadZpgIndX(), 6); - } - - private void Execute65N02SbcE5() // sbc zpg - { - GetAddressZpg(); - ExecuteSbc65N02(ReadZpg(), 3); - } - - private void Execute65N02SbcE9() // sbc imm - { - ExecuteSbc65N02(ReadImm(), 2); - } - - private void Execute65N02SbcED() // sbc abs - { - GetAddressAbs(); - ExecuteSbc65N02(ReadAbs(), 4); - } - - private void Execute65N02SbcF1() // sbc (zpg), y - { - GetAddressZpgIndYCC(); - ExecuteSbc65N02(ReadZpgIndY(), 5); - } - - private void Execute65N02SbcF5() // sbc zpg, x - { - GetAddressZpgX(); - ExecuteSbc65N02(ReadZpgX(), 4); - } - - private void Execute65N02SbcF9() // sbc abs, y - { - GetAddressAbsYCC(); - ExecuteSbc65N02(ReadAbsY(), 4); - } - - private void Execute65N02SbcFD() // sbc abs, x - { - GetAddressAbsXCC(); - ExecuteSbc65N02(ReadAbsX(), 4); - } - #endregion - - #region 65C02 OpCode Actions - private void Execute65C02Adc61() // adc (zpg, x) - { - GetAddressZpgIndX(); - ExecuteAdc65C02(ReadZpgIndX(), 6); - } - - private void Execute65C02Adc65() // adc zpg - { - GetAddressZpg(); - ExecuteAdc65C02(ReadZpg(), 3); - } - - private void Execute65C02Adc69() // adc imm - { - ExecuteAdc65C02(ReadImm(), 2); - } - - private void Execute65C02Adc6D() // adc abs - { - GetAddressAbs(); - ExecuteAdc65C02(ReadAbs(), 4); - } - - private void Execute65C02Adc71() // adc (zpg), y - { - GetAddressZpgIndYCC(); - ExecuteAdc65C02(ReadZpgIndY(), 5); - } - - private void Execute65C02Adc72() // adc (zpg) - { - GetAddressZpgInd(); - ExecuteAdc65C02(ReadZpgInd(), 5); - } - - private void Execute65C02Adc75() // adc zpg, x - { - GetAddressZpgX(); - ExecuteAdc65C02(ReadZpgX(), 4); - } - - private void Execute65C02Adc79() // adc abs, y - { - GetAddressAbsYCC(); - ExecuteAdc65C02(ReadAbsY(), 4); - } - - private void Execute65C02Adc7D() // adc abs, x - { - GetAddressAbsXCC(); - ExecuteAdc65C02(ReadAbsX(), 4); - } - - private void Execute65C02And32() // and (zpg) - { - GetAddressZpgInd(); - ExecuteAnd(ReadZpgInd(), 5); - } - - private void Execute65C02Asl1E() // asl abs, x - { - GetAddressAbsXCC(); - WriteAbsX(ExecuteAsl(ReadAbsX(), 6)); - } - - private void Execute65C02Bit34() // bit zpg, x - { - GetAddressZpgX(); - ExecuteBit(ReadZpgX(), 4); - } - - private void Execute65C02Bit3C() // bit abs, x - { - GetAddressAbsXCC(); - ExecuteBit(ReadAbsX(), 4); - } - - private void Execute65C02Bit89() // bit imm - { - ExecuteBitImm(ReadImm(), 2); - } - - private void Execute65C02Bra80() // bra rel - { - ExecuteBra(2); - } - - private void Execute65C02CmpD2() // cmp (zpg) - { - GetAddressZpgInd(); - ExecuteCmp(ReadZpgInd(), 5); - } - - private void Execute65C02Dea3A() // dea imp - { - ExecuteDea(2); - } - - private void Execute65C02DecDE() // dec abs, x - { - GetAddressAbsXCC(); - WriteAbsX(ExecuteDec(ReadAbsX(), 6)); - } - - private void Execute65C02Eor52() // eor (zpg) - { - GetAddressZpgInd(); - ExecuteEor(ReadZpgInd(), 5); - } - - private void Execute65C02Ina1A() // ina imp - { - ExecuteIna(2); - } - - private void Execute65C02IncFE() // inc abs, x - { - GetAddressAbsXCC(); - WriteAbsX(ExecuteInc(ReadAbsX(), 6)); - } - - private void Execute65C02Jmp6C() // jmp (abs) - { - ExecuteJmpAbsInd65C02(6); - } - - private void Execute65C02Jmp7C() // jmp (abs, x) - { - ExecuteJmpAbsIndX(6); - } - - private void Execute65C02LdaB2() // lda (zpg) - { - GetAddressZpgInd(); - ExecuteLda(ReadZpgInd(), 5); - } - - private void Execute65C02Lsr5E() // lsr abs, x - { - GetAddressAbsXCC(); - WriteAbsX(ExecuteLsr(ReadAbsX(), 6)); - } - - private void Execute65C02Nop02() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65C02Nop03() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop07() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop0B() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop0F() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop13() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop17() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop1B() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop1F() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop22() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65C02Nop23() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop27() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop2B() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop2F() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop33() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop37() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop3B() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop3F() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop42() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65C02Nop43() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop44() // nop imp1 - { - ExecuteNop(1, 3); - } - - private void Execute65C02Nop47() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop4B() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop4F() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop53() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop54() // nop imp1 - { - ExecuteNop(1, 4); - } - - private void Execute65C02Nop57() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop5B() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop5C() // nop imp2 - { - ExecuteNop(2, 8); - } - - private void Execute65C02Nop5F() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop62() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65C02Nop63() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop67() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop6B() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop6F() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop73() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop77() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop7B() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop7F() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop82() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65C02Nop83() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop87() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop8B() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop8F() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop93() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop97() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop9B() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Nop9F() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopA3() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopA7() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopAB() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopAF() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopB3() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopB7() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopBB() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopBF() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopC2() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65C02NopC3() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopC7() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopCB() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopCF() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopD3() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopD4() // nop imp1 - { - ExecuteNop(1, 4); - } - - private void Execute65C02NopD7() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopDB() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopDC() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65C02NopDF() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopE2() // nop imp1 - { - ExecuteNop(1, 2); - } - - private void Execute65C02NopE3() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopE7() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopEB() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopEF() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopF3() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopF4() // nop imp1 - { - ExecuteNop(1, 4); - } - - private void Execute65C02NopF7() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopFB() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02NopFC() // nop imp2 - { - ExecuteNop(2, 4); - } - - private void Execute65C02NopFF() // nop imp0 - { - ExecuteNop(0, 1); - } - - private void Execute65C02Ora12() // ora (zpg) - { - GetAddressZpgInd(); - ExecuteOra(ReadZpgInd(), 5); - } - - private void Execute65C02PhxDA() // phx imp - { - ExecutePhx(3); - } - - private void Execute65C02Phy5A() // phy imp - { - ExecutePhy(3); - } - - private void Execute65C02PlxFA() // plx imp - { - ExecutePlx(4); - } - - private void Execute65C02Ply7A() // ply imp - { - ExecutePly(4); - } - - private void Execute65C02Rol3E() // rol abs, x - { - GetAddressAbsXCC(); - WriteAbsX(ExecuteRol(ReadAbsX(), 6)); - } - - private void Execute65C02Ror7E() // ror abs, x - { - GetAddressAbsXCC(); - WriteAbsX(ExecuteRor(ReadAbsX(), 6)); - } - - private void Execute65C02SbcE1() // sbc (zpg, x) - { - GetAddressZpgIndX(); - ExecuteSbc65C02(ReadZpgIndX(), 6); - } - - private void Execute65C02SbcE5() // sbc zpg - { - GetAddressZpg(); - ExecuteSbc65C02(ReadZpg(), 3); - } - - private void Execute65C02SbcE9() // sbc imm - { - ExecuteSbc65C02(ReadImm(), 2); - } - - private void Execute65C02SbcED() // sbc abs - { - GetAddressAbs(); - ExecuteSbc65C02(ReadAbs(), 4); - } - - private void Execute65C02SbcF1() // sbc (zpg), y - { - GetAddressZpgIndYCC(); - ExecuteSbc65C02(ReadZpgIndY(), 5); - } - - private void Execute65C02SbcF2() // sbc (zpg) - { - GetAddressZpgInd(); - ExecuteSbc65C02(ReadZpgInd(), 5); - } - - private void Execute65C02SbcF5() // sbc zpg, x - { - GetAddressZpgX(); - ExecuteSbc65C02(ReadZpgX(), 4); - } - - private void Execute65C02SbcF9() // sbc abs, y - { - GetAddressAbsYCC(); - ExecuteSbc65C02(ReadAbsY(), 4); - } - - private void Execute65C02SbcFD() // sbc abs, x - { - GetAddressAbsXCC(); - ExecuteSbc65C02(ReadAbsX(), 4); - } - - private void Execute65C02Sta92() // sta (zpg) - { - GetAddressZpgInd(); - WriteZpgInd(RA); - ExecuteSta(5); - } - - private void Execute65C02Stz64() // stz zpg - { - GetAddressZpg(); - WriteZpg(0x00); - ExecuteStz(3); - } - - private void Execute65C02Stz74() // stz zpg, x - { - GetAddressZpgX(); - WriteZpgX(0x00); - ExecuteStz(4); - } - - private void Execute65C02Stz9C() // stz abs - { - GetAddressAbs(); - WriteAbs(0x00); - ExecuteStz(4); - } - - private void Execute65C02Stz9E() // stz abs, x - { - GetAddressAbsX(); - WriteAbsX(0x00); - ExecuteStz(5); - } - - private void Execute65C02Trb14() // trb zpg - { - GetAddressZpg(); - WriteZpg(ExecuteTrb(ReadZpg(), 5)); - } - - private void Execute65C02Trb1C() // trb abs - { - GetAddressAbs(); - WriteAbs(ExecuteTrb(ReadAbs(), 6)); - } - - private void Execute65C02Tsb04() // tsb zpg - { - GetAddressZpg(); - WriteZpg(ExecuteTsb(ReadZpg(), 5)); - } - - private void Execute65C02Tsb0C() // tsb abs - { - GetAddressAbs(); - WriteAbs(ExecuteTsb(ReadAbs(), 6)); - } - #endregion - - 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; } - public int RY { get; private set; } - public int RS { get; private set; } - public int RP { get; private set; } - public int RPC { get; private set; } - public int EA { get; private set; } - public int CC { get; private set; } - public int OpCode { get; private set; } - public long Cycles { get; private set; } - - private Memory _memory; - - private bool _is65C02; - private Action[] _executeOpCode; - } -} +using System; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.IO; + +namespace Jellyfish.Virtu +{ + public sealed partial class Cpu : MachineComponent + { + public Cpu(Machine machine) : + base(machine) + { + ExecuteOpCode65N02 = new Action[OpCodeCount] + { + Execute65X02Brk00, Execute65X02Ora01, Execute65N02Nop02, Execute65N02Nop03, + Execute65N02Nop04, Execute65X02Ora05, Execute65X02Asl06, Execute65N02Nop07, + Execute65X02Php08, Execute65X02Ora09, Execute65X02Asl0A, Execute65N02Nop0B, + Execute65N02Nop0C, Execute65X02Ora0D, Execute65X02Asl0E, Execute65N02Nop0F, + Execute65X02Bpl10, Execute65X02Ora11, Execute65N02Nop12, Execute65N02Nop13, + Execute65N02Nop14, Execute65X02Ora15, Execute65X02Asl16, Execute65N02Nop17, + Execute65X02Clc18, Execute65X02Ora19, Execute65N02Nop1A, Execute65N02Nop1B, + Execute65N02Nop1C, Execute65X02Ora1D, Execute65N02Asl1E, Execute65N02Nop1F, + Execute65X02Jsr20, Execute65X02And21, Execute65N02Nop22, Execute65N02Nop23, + Execute65X02Bit24, Execute65X02And25, Execute65X02Rol26, Execute65N02Nop27, + Execute65X02Plp28, Execute65X02And29, Execute65X02Rol2A, Execute65N02Nop2B, + Execute65X02Bit2C, Execute65X02And2D, Execute65X02Rol2E, Execute65N02Nop2F, + Execute65X02Bmi30, Execute65X02And31, Execute65N02Nop32, Execute65N02Nop33, + Execute65N02Nop34, Execute65X02And35, Execute65X02Rol36, Execute65N02Nop37, + Execute65X02Sec38, Execute65X02And39, Execute65N02Nop3A, Execute65N02Nop3B, + Execute65N02Nop3C, Execute65X02And3D, Execute65N02Rol3E, Execute65N02Nop3F, + Execute65X02Rti40, Execute65X02Eor41, Execute65N02Nop42, Execute65N02Nop43, + Execute65N02Nop44, Execute65X02Eor45, Execute65X02Lsr46, Execute65N02Nop47, + Execute65X02Pha48, Execute65X02Eor49, Execute65X02Lsr4A, Execute65N02Nop4B, + Execute65X02Jmp4C, Execute65X02Eor4D, Execute65X02Lsr4E, Execute65N02Nop4F, + Execute65X02Bvc50, Execute65X02Eor51, Execute65N02Nop52, Execute65N02Nop53, + Execute65N02Nop54, Execute65X02Eor55, Execute65X02Lsr56, Execute65N02Nop57, + Execute65X02Cli58, Execute65X02Eor59, Execute65N02Nop5A, Execute65N02Nop5B, + Execute65N02Nop5C, Execute65X02Eor5D, Execute65N02Lsr5E, Execute65N02Nop5F, + Execute65X02Rts60, Execute65N02Adc61, Execute65N02Nop62, Execute65N02Nop63, + Execute65N02Nop64, Execute65N02Adc65, Execute65X02Ror66, Execute65N02Nop67, + Execute65X02Pla68, Execute65N02Adc69, Execute65X02Ror6A, Execute65N02Nop6B, + Execute65N02Jmp6C, Execute65N02Adc6D, Execute65X02Ror6E, Execute65N02Nop6F, + Execute65X02Bvs70, Execute65N02Adc71, Execute65N02Nop72, Execute65N02Nop73, + Execute65N02Nop74, Execute65N02Adc75, Execute65X02Ror76, Execute65N02Nop77, + Execute65X02Sei78, Execute65N02Adc79, Execute65N02Nop7A, Execute65N02Nop7B, + Execute65N02Nop7C, Execute65N02Adc7D, Execute65N02Ror7E, Execute65N02Nop7F, + Execute65N02Nop80, Execute65X02Sta81, Execute65N02Nop82, Execute65N02Nop83, + Execute65X02Sty84, Execute65X02Sta85, Execute65X02Stx86, Execute65N02Nop87, + Execute65X02Dey88, Execute65N02Nop89, Execute65X02Txa8A, Execute65N02Nop8B, + Execute65X02Sty8C, Execute65X02Sta8D, Execute65X02Stx8E, Execute65N02Nop8F, + Execute65X02Bcc90, Execute65X02Sta91, Execute65N02Nop92, Execute65N02Nop93, + Execute65X02Sty94, Execute65X02Sta95, Execute65X02Stx96, Execute65N02Nop97, + Execute65X02Tya98, Execute65X02Sta99, Execute65X02Txs9A, Execute65N02Nop9B, + Execute65N02Nop9C, Execute65X02Sta9D, Execute65N02Nop9E, Execute65N02Nop9F, + Execute65X02LdyA0, Execute65X02LdaA1, Execute65X02LdxA2, Execute65N02NopA3, + Execute65X02LdyA4, Execute65X02LdaA5, Execute65X02LdxA6, Execute65N02NopA7, + Execute65X02TayA8, Execute65X02LdaA9, Execute65X02TaxAA, Execute65N02NopAB, + Execute65X02LdyAC, Execute65X02LdaAD, Execute65X02LdxAE, Execute65N02NopAF, + Execute65X02BcsB0, Execute65X02LdaB1, Execute65N02NopB2, Execute65N02NopB3, + Execute65X02LdyB4, Execute65X02LdaB5, Execute65X02LdxB6, Execute65N02NopB7, + Execute65X02ClvB8, Execute65X02LdaB9, Execute65X02TsxBA, Execute65N02NopBB, + Execute65X02LdyBC, Execute65X02LdaBD, Execute65X02LdxBE, Execute65N02NopBF, + Execute65X02CpyC0, Execute65X02CmpC1, Execute65N02NopC2, Execute65N02NopC3, + Execute65X02CpyC4, Execute65X02CmpC5, Execute65X02DecC6, Execute65N02NopC7, + Execute65X02InyC8, Execute65X02CmpC9, Execute65X02DexCA, Execute65N02NopCB, + Execute65X02CpyCC, Execute65X02CmpCD, Execute65X02DecCE, Execute65N02NopCF, + Execute65X02BneD0, Execute65X02CmpD1, Execute65N02NopD2, Execute65N02NopD3, + Execute65N02NopD4, Execute65X02CmpD5, Execute65X02DecD6, Execute65N02NopD7, + Execute65X02CldD8, Execute65X02CmpD9, Execute65N02NopDA, Execute65N02NopDB, + Execute65N02NopDC, Execute65X02CmpDD, Execute65N02DecDE, Execute65N02NopDF, + Execute65X02CpxE0, Execute65N02SbcE1, Execute65N02NopE2, Execute65N02NopE3, + Execute65X02CpxE4, Execute65N02SbcE5, Execute65X02IncE6, Execute65N02NopE7, + Execute65X02InxE8, Execute65N02SbcE9, Execute65X02NopEA, Execute65N02NopEB, + Execute65X02CpxEC, Execute65N02SbcED, Execute65X02IncEE, Execute65N02NopEF, + Execute65X02BeqF0, Execute65N02SbcF1, Execute65N02NopF2, Execute65N02NopF3, + Execute65N02NopF4, Execute65N02SbcF5, Execute65X02IncF6, Execute65N02NopF7, + Execute65X02SedF8, Execute65N02SbcF9, Execute65N02NopFA, Execute65N02NopFB, + Execute65N02NopFC, Execute65N02SbcFD, Execute65N02IncFE, Execute65N02NopFF + }; + + ExecuteOpCode65C02 = new Action[OpCodeCount] + { + Execute65X02Brk00, Execute65X02Ora01, Execute65C02Nop02, Execute65C02Nop03, + Execute65C02Tsb04, Execute65X02Ora05, Execute65X02Asl06, Execute65C02Nop07, + Execute65X02Php08, Execute65X02Ora09, Execute65X02Asl0A, Execute65C02Nop0B, + Execute65C02Tsb0C, Execute65X02Ora0D, Execute65X02Asl0E, Execute65C02Nop0F, + Execute65X02Bpl10, Execute65X02Ora11, Execute65C02Ora12, Execute65C02Nop13, + Execute65C02Trb14, Execute65X02Ora15, Execute65X02Asl16, Execute65C02Nop17, + Execute65X02Clc18, Execute65X02Ora19, Execute65C02Ina1A, Execute65C02Nop1B, + Execute65C02Trb1C, Execute65X02Ora1D, Execute65C02Asl1E, Execute65C02Nop1F, + Execute65X02Jsr20, Execute65X02And21, Execute65C02Nop22, Execute65C02Nop23, + Execute65X02Bit24, Execute65X02And25, Execute65X02Rol26, Execute65C02Nop27, + Execute65X02Plp28, Execute65X02And29, Execute65X02Rol2A, Execute65C02Nop2B, + Execute65X02Bit2C, Execute65X02And2D, Execute65X02Rol2E, Execute65C02Nop2F, + Execute65X02Bmi30, Execute65X02And31, Execute65C02And32, Execute65C02Nop33, + Execute65C02Bit34, Execute65X02And35, Execute65X02Rol36, Execute65C02Nop37, + Execute65X02Sec38, Execute65X02And39, Execute65C02Dea3A, Execute65C02Nop3B, + Execute65C02Bit3C, Execute65X02And3D, Execute65C02Rol3E, Execute65C02Nop3F, + Execute65X02Rti40, Execute65X02Eor41, Execute65C02Nop42, Execute65C02Nop43, + Execute65C02Nop44, Execute65X02Eor45, Execute65X02Lsr46, Execute65C02Nop47, + Execute65X02Pha48, Execute65X02Eor49, Execute65X02Lsr4A, Execute65C02Nop4B, + Execute65X02Jmp4C, Execute65X02Eor4D, Execute65X02Lsr4E, Execute65C02Nop4F, + Execute65X02Bvc50, Execute65X02Eor51, Execute65C02Eor52, Execute65C02Nop53, + Execute65C02Nop54, Execute65X02Eor55, Execute65X02Lsr56, Execute65C02Nop57, + Execute65X02Cli58, Execute65X02Eor59, Execute65C02Phy5A, Execute65C02Nop5B, + Execute65C02Nop5C, Execute65X02Eor5D, Execute65C02Lsr5E, Execute65C02Nop5F, + Execute65X02Rts60, Execute65C02Adc61, Execute65C02Nop62, Execute65C02Nop63, + Execute65C02Stz64, Execute65C02Adc65, Execute65X02Ror66, Execute65C02Nop67, + Execute65X02Pla68, Execute65C02Adc69, Execute65X02Ror6A, Execute65C02Nop6B, + Execute65C02Jmp6C, Execute65C02Adc6D, Execute65X02Ror6E, Execute65C02Nop6F, + Execute65X02Bvs70, Execute65C02Adc71, Execute65C02Adc72, Execute65C02Nop73, + Execute65C02Stz74, Execute65C02Adc75, Execute65X02Ror76, Execute65C02Nop77, + Execute65X02Sei78, Execute65C02Adc79, Execute65C02Ply7A, Execute65C02Nop7B, + Execute65C02Jmp7C, Execute65C02Adc7D, Execute65C02Ror7E, Execute65C02Nop7F, + Execute65C02Bra80, Execute65X02Sta81, Execute65C02Nop82, Execute65C02Nop83, + Execute65X02Sty84, Execute65X02Sta85, Execute65X02Stx86, Execute65C02Nop87, + Execute65X02Dey88, Execute65C02Bit89, Execute65X02Txa8A, Execute65C02Nop8B, + Execute65X02Sty8C, Execute65X02Sta8D, Execute65X02Stx8E, Execute65C02Nop8F, + Execute65X02Bcc90, Execute65X02Sta91, Execute65C02Sta92, Execute65C02Nop93, + Execute65X02Sty94, Execute65X02Sta95, Execute65X02Stx96, Execute65C02Nop97, + Execute65X02Tya98, Execute65X02Sta99, Execute65X02Txs9A, Execute65C02Nop9B, + Execute65C02Stz9C, Execute65X02Sta9D, Execute65C02Stz9E, Execute65C02Nop9F, + Execute65X02LdyA0, Execute65X02LdaA1, Execute65X02LdxA2, Execute65C02NopA3, + Execute65X02LdyA4, Execute65X02LdaA5, Execute65X02LdxA6, Execute65C02NopA7, + Execute65X02TayA8, Execute65X02LdaA9, Execute65X02TaxAA, Execute65C02NopAB, + Execute65X02LdyAC, Execute65X02LdaAD, Execute65X02LdxAE, Execute65C02NopAF, + Execute65X02BcsB0, Execute65X02LdaB1, Execute65C02LdaB2, Execute65C02NopB3, + Execute65X02LdyB4, Execute65X02LdaB5, Execute65X02LdxB6, Execute65C02NopB7, + Execute65X02ClvB8, Execute65X02LdaB9, Execute65X02TsxBA, Execute65C02NopBB, + Execute65X02LdyBC, Execute65X02LdaBD, Execute65X02LdxBE, Execute65C02NopBF, + Execute65X02CpyC0, Execute65X02CmpC1, Execute65C02NopC2, Execute65C02NopC3, + Execute65X02CpyC4, Execute65X02CmpC5, Execute65X02DecC6, Execute65C02NopC7, + Execute65X02InyC8, Execute65X02CmpC9, Execute65X02DexCA, Execute65C02NopCB, + Execute65X02CpyCC, Execute65X02CmpCD, Execute65X02DecCE, Execute65C02NopCF, + Execute65X02BneD0, Execute65X02CmpD1, Execute65C02CmpD2, Execute65C02NopD3, + Execute65C02NopD4, Execute65X02CmpD5, Execute65X02DecD6, Execute65C02NopD7, + Execute65X02CldD8, Execute65X02CmpD9, Execute65C02PhxDA, Execute65C02NopDB, + Execute65C02NopDC, Execute65X02CmpDD, Execute65C02DecDE, Execute65C02NopDF, + Execute65X02CpxE0, Execute65C02SbcE1, Execute65C02NopE2, Execute65C02NopE3, + Execute65X02CpxE4, Execute65C02SbcE5, Execute65X02IncE6, Execute65C02NopE7, + Execute65X02InxE8, Execute65C02SbcE9, Execute65X02NopEA, Execute65C02NopEB, + Execute65X02CpxEC, Execute65C02SbcED, Execute65X02IncEE, Execute65C02NopEF, + Execute65X02BeqF0, Execute65C02SbcF1, Execute65C02SbcF2, Execute65C02NopF3, + Execute65C02NopF4, Execute65C02SbcF5, Execute65X02IncF6, Execute65C02NopF7, + Execute65X02SedF8, Execute65C02SbcF9, Execute65C02PlxFA, Execute65C02NopFB, + Execute65C02NopFC, Execute65C02SbcFD, Execute65C02IncFE, Execute65C02NopFF + }; + } + + public override void Initialize() + { + _memory = Machine.Memory; + + Is65C02 = true; + IsThrottled = true; + Multiplier = 1; + + RS = 0xFF; + } + + public override void Reset() + { + RS = (RS - 3) & 0xFF; // [4-14] + RPC = _memory.ReadRomRegionE0FF(0xFFFC) | (_memory.ReadRomRegionE0FF(0xFFFD) << 8); + RP |= (PB | PI); + 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.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); + } + + public int Execute() + { + CC = 0; + OpCode = _memory.Read(RPC); + RPC = (RPC + 1) & 0xFFFF; + _executeOpCode[OpCode](); + Cycles += CC; + + return CC; + } + + #region Core Operand Actions + private void GetAddressAbs() // abs + { + EA = _memory.Read(RPC) | (_memory.Read(RPC + 1) << 8); + RPC = (RPC + 2) & 0xFFFF; + } + + private void GetAddressAbsX() // abs, x + { + EA = (_memory.Read(RPC) + RX + (_memory.Read(RPC + 1) << 8)) & 0xFFFF; + RPC = (RPC + 2) & 0xFFFF; + } + + private void GetAddressAbsXCC() // abs, x + { + int ea = _memory.Read(RPC) + RX; + EA = (ea + (_memory.Read(RPC + 1) << 8)) & 0xFFFF; + RPC = (RPC + 2) & 0xFFFF; + CC += (ea >> 8); + } + + private void GetAddressAbsY() // abs, y + { + EA = (_memory.Read(RPC) + RY + (_memory.Read(RPC + 1) << 8)) & 0xFFFF; + RPC = (RPC + 2) & 0xFFFF; + } + + private void GetAddressAbsYCC() // abs, y + { + int ea = _memory.Read(RPC) + RY; + EA = (ea + (_memory.Read(RPC + 1) << 8)) & 0xFFFF; + RPC = (RPC + 2) & 0xFFFF; + CC += (ea >> 8); + } + + private void GetAddressZpg() // zpg + { + EA = _memory.Read(RPC); + RPC = (RPC + 1) & 0xFFFF; + } + + private void GetAddressZpgInd() // (zpg) + { + int zp = _memory.Read(RPC); + EA = _memory.ReadZeroPage(zp) | (_memory.ReadZeroPage((zp + 1) & 0xFF) << 8); + RPC = (RPC + 1) & 0xFFFF; + } + + private void GetAddressZpgIndX() // (zpg, x) + { + int zp = (_memory.Read(RPC) + RX) & 0xFF; + EA = _memory.ReadZeroPage(zp) | (_memory.ReadZeroPage((zp + 1) & 0xFF) << 8); + RPC = (RPC + 1) & 0xFFFF; + } + + private void GetAddressZpgIndY() // (zpg), y + { + int zp = _memory.Read(RPC); + EA = (_memory.ReadZeroPage(zp) + RY + (_memory.ReadZeroPage((zp + 1) & 0xFF) << 8)) & 0xFFFF; + RPC = (RPC + 1) & 0xFFFF; + } + + private void GetAddressZpgIndYCC() // (zpg), y + { + int zp = _memory.Read(RPC); + int ea = _memory.ReadZeroPage(zp) + RY; + EA = (ea + (_memory.ReadZeroPage((zp + 1) & 0xFF) << 8)) & 0xFFFF; + RPC = (RPC + 1) & 0xFFFF; + CC += (ea >> 8); + } + + private void GetAddressZpgX() // zpg, x + { + EA = (_memory.Read(RPC) + RX) & 0xFF; + RPC = (RPC + 1) & 0xFFFF; + } + + private void GetAddressZpgY() // zpg, y + { + EA = (_memory.Read(RPC) + RY) & 0xFF; + RPC = (RPC + 1) & 0xFFFF; + } + + private int Pull() + { + RS = (RS + 1) & 0xFF; + + return _memory.ReadZeroPage(0x0100 + RS); + } + + private void Push(int data) + { + _memory.WriteZeroPage(0x0100 + RS, data); + RS = (RS - 1) & 0xFF; + } + + private int ReadAbs() // abs + { + return _memory.Read(EA); + } + + private int ReadAbsX() // abs, x + { + return _memory.Read(EA); + } + + private int ReadAbsY() // abs, y + { + return _memory.Read(EA); + } + + private int ReadImm() // imm + { + int data = _memory.Read(RPC); + RPC = (RPC + 1) & 0xFFFF; + + return data; + } + + private int ReadZpg() // zpg + { + return _memory.ReadZeroPage(EA); + } + + private int ReadZpgInd() // (zpg) + { + return _memory.Read(EA); + } + + private int ReadZpgIndX() // (zpg, x) + { + return _memory.Read(EA); + } + + private int ReadZpgIndY() // (zpg), y + { + return _memory.Read(EA); + } + + private int ReadZpgX() // zpg, x + { + return _memory.ReadZeroPage(EA); + } + + private int ReadZpgY() // zpg, y + { + return _memory.ReadZeroPage(EA); + } + + private void WriteAbs(int data) // abs + { + _memory.Write(EA, data); + } + + private void WriteAbsX(int data) // abs, x + { + _memory.Write(EA, data); + } + + private void WriteAbsY(int data) // abs, y + { + _memory.Write(EA, data); + } + + private void WriteZpg(int data) // zpg + { + _memory.WriteZeroPage(EA, data); + } + + private void WriteZpgInd(int data) // (zpg) + { + _memory.Write(EA, data); + } + + private void WriteZpgIndX(int data) // (zpg, x) + { + _memory.Write(EA, data); + } + + private void WriteZpgIndY(int data) // (zpg), y + { + _memory.Write(EA, data); + } + + private void WriteZpgX(int data) // zpg, x + { + _memory.WriteZeroPage(EA, data); + } + + private void WriteZpgY(int data) // zpg, y + { + _memory.WriteZeroPage(EA, data); + } + #endregion + + #region Core OpCode Actions + private void ExecuteAdc65N02(int data, int cc) + { + if ((RP & PD) == 0x0) + { + int ra = RA + data + (RP & PC); + RP = RP & ~(PC | PN | PV | PZ) | ((ra >> 8) & PC) | DataPNZ[ra & 0xFF] | (((~(RA ^ data) & (RA ^ (ra & 0xFF))) >> 1) & PV); + RA = ra & 0xFF; + CC += cc; + } + else // decimal + { + int ral = (RA & 0x0F) + (data & 0x0F) + (RP & PC); + int rah = (RA >> 4) + (data >> 4); + if (ral >= 10) + { + ral -= 10; + rah++; + } + int ra = (ral | (rah << 4)) & 0xFF; + RP = RP & ~(PC | PN | PV | PZ) | DataPN[ra] | (((~(RA ^ data) & (RA ^ ra)) >> 1) & PV) | DataPZ[(RA + data + (RP & PC)) & 0xFF]; + if (rah >= 10) + { + rah -= 10; + RP |= PC; + } + RA = (ral | (rah << 4)) & 0xFF; + CC += cc; + } + } + + private void ExecuteAdc65C02(int data, int cc) + { + if ((RP & PD) == 0x0) + { + int ra = RA + data + (RP & PC); + RP = RP & ~(PC | PN | PV | PZ) | ((ra >> 8) & PC) | DataPNZ[ra & 0xFF] | (((~(RA ^ data) & (RA ^ (ra & 0xFF))) >> 1) & PV); + RA = ra & 0xFF; + CC += cc; + } + else // decimal + { + int ral = (RA & 0x0F) + (data & 0x0F) + (RP & PC); + int rah = (RA >> 4) + (data >> 4); + if (ral >= 10) + { + ral -= 10; + rah++; + } + RP &= ~PC; + if (rah >= 10) + { + rah -= 10; + RP |= PC; + } + int ra = (ral | (rah << 4)) & 0xFF; + RP = RP & ~(PN | PV | PZ) | DataPNZ[ra] | (((~(RA ^ data) & (RA ^ ra)) >> 1) & PV); + RA = ra; + CC += cc + 1; + } + } + + private void ExecuteAnd(int data, int cc) + { + RA &= data; + RP = RP & ~(PN | PZ) | DataPNZ[RA]; + CC += cc; + } + + private int ExecuteAsl(int data, int cc) + { + RP = RP & ~PC | ((data >> 7) & PC); + data = (data << 1) & 0xFF; + RP = RP & ~(PN | PZ) | DataPNZ[data]; + CC += cc; + + return data; + } + + private void ExecuteAslImp(int cc) + { + RP = RP & ~PC | ((RA >> 7) & PC); + RA = (RA << 1) & 0xFF; + RP = RP & ~(PN | PZ) | DataPNZ[RA]; + CC += cc; + } + + private void ExecuteBcc(int cc) + { + if ((RP & PC) == 0x0) + { + int rpc = (RPC + 1) & 0xFFFF; + RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; + CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); + } + else + { + RPC = (RPC + 1) & 0xFFFF; + CC += cc; + } + } + + private void ExecuteBcs(int cc) + { + if ((RP & PC) != 0x0) + { + int rpc = (RPC + 1) & 0xFFFF; + RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; + CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); + } + else + { + RPC = (RPC + 1) & 0xFFFF; + CC += cc; + } + } + + private void ExecuteBeq(int cc) + { + if ((RP & PZ) != 0x0) + { + int rpc = (RPC + 1) & 0xFFFF; + RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; + CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); + } + else + { + RPC = (RPC + 1) & 0xFFFF; + CC += cc; + } + } + + private void ExecuteBit(int data, int cc) + { + RP = RP & ~(PN | PV | PZ) | (data & (PN | PV)) | DataPZ[RA & data]; + CC += cc; + } + + private void ExecuteBitImm(int data, int cc) + { + RP = RP & ~PZ | DataPZ[RA & data]; + CC += cc; + } + + private void ExecuteBmi(int cc) + { + if ((RP & PN) != 0x0) + { + int rpc = (RPC + 1) & 0xFFFF; + RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; + CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); + } + else + { + RPC = (RPC + 1) & 0xFFFF; + CC += cc; + } + } + + private void ExecuteBne(int cc) + { + if ((RP & PZ) == 0x0) + { + int rpc = (RPC + 1) & 0xFFFF; + RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; + CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); + } + else + { + RPC = (RPC + 1) & 0xFFFF; + CC += cc; + } + } + + private void ExecuteBpl(int cc) + { + if ((RP & PN) == 0x0) + { + int rpc = (RPC + 1) & 0xFFFF; + RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; + CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); + } + else + { + RPC = (RPC + 1) & 0xFFFF; + CC += cc; + } + } + + private void ExecuteBra(int cc) + { + int rpc = (RPC + 1) & 0xFFFF; + RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; + CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); + } + + private void ExecuteBrk(int cc) + { + int rpc = (RPC + 1) & 0xFFFF; // [4-18] + Push(rpc >> 8); + Push(rpc & 0xFF); + Push(RP | PB); + RP |= PI; + RPC = _memory.Read(0xFFFE) | (_memory.Read(0xFFFF) << 8); + CC += cc; + } + + private void ExecuteBvc(int cc) + { + if ((RP & PV) == 0x0) + { + int rpc = (RPC + 1) & 0xFFFF; + RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; + CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); + } + else + { + RPC = (RPC + 1) & 0xFFFF; + CC += cc; + } + } + + private void ExecuteBvs(int cc) + { + if ((RP & PV) != 0x0) + { + int rpc = (RPC + 1) & 0xFFFF; + RPC = (RPC + 1 + (sbyte)_memory.Read(RPC)) & 0xFFFF; + CC += cc + 1 + (((RPC ^ rpc) >> 8) & 0x01); + } + else + { + RPC = (RPC + 1) & 0xFFFF; + CC += cc; + } + } + + private void ExecuteClc(int cc) + { + RP &= ~PC; + CC += cc; + } + + private void ExecuteCld(int cc) + { + RP &= ~PD; + CC += cc; + } + + private void ExecuteCli(int cc) + { + RP &= ~PI; + CC += cc; + } + + private void ExecuteClv(int cc) + { + RP &= ~PV; + CC += cc; + } + + private void ExecuteCmp(int data, int cc) + { + int diff = RA - data; + RP = RP & ~(PC | PN | PZ) | ((~diff >> 8) & PC) | DataPNZ[diff & 0xFF]; + CC += cc; + } + + private void ExecuteCpx(int data, int cc) + { + int diff = RX - data; + RP = RP & ~(PC | PN | PZ) | ((~diff >> 8) & PC) | DataPNZ[diff & 0xFF]; + CC += cc; + } + + private void ExecuteCpy(int data, int cc) + { + int diff = RY - data; + RP = RP & ~(PC | PN | PZ) | ((~diff >> 8) & PC) | DataPNZ[diff & 0xFF]; + CC += cc; + } + + private void ExecuteDea(int cc) + { + RA = (RA - 1) & 0xFF; + RP = RP & ~(PN | PZ) | DataPNZ[RA]; + CC += cc; + } + + private int ExecuteDec(int data, int cc) + { + data = (data - 1) & 0xFF; + RP = RP & ~(PN | PZ) | DataPNZ[data]; + CC += cc; + + return data; + } + + private void ExecuteDex(int cc) + { + RX = (RX - 1) & 0xFF; + RP = RP & ~(PN | PZ) | DataPNZ[RX]; + CC += cc; + } + + private void ExecuteDey(int cc) + { + RY = (RY - 1) & 0xFF; + RP = RP & ~(PN | PZ) | DataPNZ[RY]; + CC += cc; + } + + private void ExecuteEor(int data, int cc) + { + RA ^= data; + RP = RP & ~(PN | PZ) | DataPNZ[RA]; + CC += cc; + } + + private void ExecuteIna(int cc) + { + RA = (RA + 1) & 0xFF; + RP = RP & ~(PN | PZ) | DataPNZ[RA]; + CC += cc; + } + + private int ExecuteInc(int data, int cc) + { + data = (data + 1) & 0xFF; + RP = RP & ~(PN | PZ) | DataPNZ[data]; + CC += cc; + + return data; + } + + private void ExecuteInx(int cc) + { + RX = (RX + 1) & 0xFF; + RP = RP & ~(PN | PZ) | DataPNZ[RX]; + CC += cc; + } + + private void ExecuteIny(int cc) + { + RY = (RY + 1) & 0xFF; + RP = RP & ~(PN | PZ) | DataPNZ[RY]; + CC += cc; + } + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + private void ExecuteIrq(int cc) + { + Push(RPC >> 8); + Push(RPC & 0xFF); + Push(RP & ~PB); + RP |= PI; + if (Is65C02) // [C-10] + { + RP &= ~PD; + } + RPC = _memory.Read(0xFFFE) | (_memory.Read(0xFFFF) << 8); + CC += cc; + } + + private void ExecuteJmpAbs(int cc) // jmp abs + { + RPC = _memory.Read(RPC) | (_memory.Read(RPC + 1) << 8); + CC += cc; + } + + private void ExecuteJmpAbsInd65N02(int cc) // jmp (abs) + { + int ea = _memory.Read(RPC) | (_memory.Read(RPC + 1) << 8); + RPC = _memory.Read(ea) | (_memory.Read((ea & 0xFF00) | ((ea + 1) & 0x00FF)) << 8); + CC += cc; + } + + private void ExecuteJmpAbsInd65C02(int cc) // jmp (abs) + { + int ea = _memory.Read(RPC) | (_memory.Read(RPC + 1) << 8); + RPC = _memory.Read(ea) | (_memory.Read(ea + 1) << 8); + CC += cc; + } + + private void ExecuteJmpAbsIndX(int cc) // jmp (abs, x) + { + int ea = (_memory.Read(RPC) + RX + (_memory.Read(RPC + 1) << 8)) & 0xFFFF; + RPC = _memory.Read(ea) | (_memory.Read(ea + 1) << 8); + CC += cc; + } + + private void ExecuteJsr(int cc) // jsr abs + { + int rpc = (RPC + 1) & 0xFFFF; + RPC = _memory.Read(RPC) | (_memory.Read(RPC + 1) << 8); + Push(rpc >> 8); + Push(rpc & 0xFF); + CC += cc; + } + + private void ExecuteLda(int data, int cc) + { + RA = data; + RP = RP & ~(PN | PZ) | DataPNZ[RA]; + CC += cc; + } + + private void ExecuteLdx(int data, int cc) + { + RX = data; + RP = RP & ~(PN | PZ) | DataPNZ[RX]; + CC += cc; + } + + private void ExecuteLdy(int data, int cc) + { + RY = data; + RP = RP & ~(PN | PZ) | DataPNZ[RY]; + CC += cc; + } + + private int ExecuteLsr(int data, int cc) + { + RP = RP & ~PC | (data & PC); + data >>= 1; + RP = RP & ~(PN | PZ) | DataPNZ[data]; + CC += cc; + + return data; + } + + private void ExecuteLsrImp(int cc) + { + RP = RP & ~PC | (RA & PC); + RA >>= 1; + RP = RP & ~(PN | PZ) | DataPNZ[RA]; + CC += cc; + } + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + private void ExecuteNmi(int cc) + { + Push(RPC >> 8); + Push(RPC & 0xFF); + Push(RP & ~PB); + RP |= PI; + if (Is65C02) // [C-10] + { + RP &= ~PD; + } + RPC = _memory.Read(0xFFFA) | (_memory.Read(0xFFFB) << 8); + CC += cc; + } + + private void ExecuteNop(int cc) + { + CC += cc; + } + + private void ExecuteNop(int data, int cc) + { + RPC = (RPC + data) & 0xFFFF; + CC += cc; + } + + private void ExecuteOra(int data, int cc) + { + RA |= data; + RP = RP & ~(PN | PZ) | DataPNZ[RA]; + CC += cc; + } + + private void ExecutePha(int cc) + { + Push(RA); + CC += cc; + } + + private void ExecutePhp(int cc) + { + Push(RP | PB); // [4-18] + CC += cc; + } + + private void ExecutePhx(int cc) + { + Push(RX); + CC += cc; + } + + private void ExecutePhy(int cc) + { + Push(RY); + CC += cc; + } + + private void ExecutePla(int cc) + { + RA = Pull(); + RP = RP & ~(PN | PZ) | DataPNZ[RA]; + CC += cc; + } + + private void ExecutePlp(int cc) + { + RP = Pull(); + CC += cc; + } + + private void ExecutePlx(int cc) + { + RX = Pull(); + RP = RP & ~(PN | PZ) | DataPNZ[RX]; + CC += cc; + } + + private void ExecutePly(int cc) + { + RY = Pull(); + RP = RP & ~(PN | PZ) | DataPNZ[RY]; + CC += cc; + } + + private int ExecuteRol(int data, int cc) + { + int c = RP & PC; + RP = RP & ~PC | ((data >> 7) & PC); + data = ((data << 1) | c) & 0xFF; + RP = RP & ~(PN | PZ) | DataPNZ[data]; + CC += cc; + + return data; + } + + private void ExecuteRolImp(int cc) + { + int c = RP & PC; + RP = RP & ~PC | ((RA >> 7) & PC); + RA = ((RA << 1) | c) & 0xFF; + RP = RP & ~(PN | PZ) | DataPNZ[RA]; + CC += cc; + } + + private int ExecuteRor(int data, int cc) + { + int c = RP & PC; + RP = RP & ~PC | (data & PC); + data = (c << 7) | (data >> 1); + RP = RP & ~(PN | PZ) | DataPNZ[data]; + CC += cc; + + return data; + } + + private void ExecuteRorImp(int cc) + { + int c = RP & PC; + RP = RP & ~PC | (RA & PC); + RA = (c << 7) | (RA >> 1); + RP = RP & ~(PN | PZ) | DataPNZ[RA]; + CC += cc; + } + + private void ExecuteRti(int cc) + { + RP = Pull(); + int rpc = Pull(); + RPC = rpc | (Pull() << 8); + CC += cc; + } + + private void ExecuteRts(int cc) + { + int rpc = Pull(); + RPC = (rpc + 1 + (Pull() << 8)) & 0xFFFF; + CC += cc; + } + + private void ExecuteSbc65N02(int data, int cc) + { + if ((RP & PD) == 0x0) + { + int ra = RA - data - (~RP & PC); + RP = RP & ~(PC | PN | PV | PZ) | ((~ra >> 8) & PC) | DataPNZ[ra & 0xFF] | ((((RA ^ data) & (RA ^ (ra & 0xFF))) >> 1) & PV); + RA = ra & 0xFF; + CC += cc; + } + else // decimal + { + int ral = (RA & 0x0F) - (data & 0x0F) - (~RP & PC); + int rah = (RA >> 4) - (data >> 4); + if (ral < 0) + { + ral += 10; + rah--; + } + int ra = (ral | (rah << 4)) & 0xFF; + RP = RP & ~(PN | PV | PZ) | PC | DataPN[ra] | ((((RA ^ data) & (RA ^ ra)) >> 1) & PV) | DataPZ[(RA - data - (~RP & PC)) & 0xFF]; + if (rah < 0) + { + rah += 10; + RP &= ~PC; + } + RA = (ral | (rah << 4)) & 0xFF; + CC += cc; + } + } + + private void ExecuteSbc65C02(int data, int cc) + { + if ((RP & PD) == 0x0) + { + int ra = RA - data - (~RP & PC); + RP = RP & ~(PC | PN | PV | PZ) | ((~ra >> 8) & PC) | DataPNZ[ra & 0xFF] | ((((RA ^ data) & (RA ^ (ra & 0xFF))) >> 1) & PV); + RA = ra & 0xFF; + CC += cc; + } + else // decimal + { + int ral = (RA & 0x0F) - (data & 0x0F) - (~RP & PC); + int rah = (RA >> 4) - (data >> 4); + if (ral < 0) + { + ral += 10; + rah--; + } + RP |= PC; + if (rah < 0) + { + rah += 10; + RP &= ~PC; + } + int ra = (ral | (rah << 4)) & 0xFF; + RP = RP & ~(PN | PV | PZ) | DataPNZ[ra] | ((((RA ^ data) & (RA ^ ra)) >> 1) & PV); + RA = ra; + CC += cc + 1; + } + } + + private void ExecuteSec(int cc) + { + RP |= PC; + CC += cc; + } + + private void ExecuteSed(int cc) + { + RP |= PD; + CC += cc; + } + + private void ExecuteSei(int cc) + { + RP |= PI; + CC += cc; + } + + private void ExecuteSta(int cc) + { + CC += cc; + } + + private void ExecuteStx(int cc) + { + CC += cc; + } + + private void ExecuteSty(int cc) + { + CC += cc; + } + + private void ExecuteStz(int cc) + { + CC += cc; + } + + private void ExecuteTax(int cc) + { + RX = RA; + RP = RP & ~(PN | PZ) | DataPNZ[RX]; + CC += cc; + } + + private void ExecuteTay(int cc) + { + RY = RA; + RP = RP & ~(PN | PZ) | DataPNZ[RY]; + CC += cc; + } + + private int ExecuteTrb(int data, int cc) + { + RP = RP & ~PZ | DataPZ[RA & data]; + data &= ~RA; + CC += cc; + + return data; + } + + private int ExecuteTsb(int data, int cc) + { + RP = RP & ~PZ | DataPZ[RA & data]; + data |= RA; + CC += cc; + + return data; + } + + private void ExecuteTsx(int cc) + { + RX = RS; + RP = RP & ~(PN | PZ) | DataPNZ[RX]; + CC += cc; + } + + private void ExecuteTxa(int cc) + { + RA = RX; + RP = RP & ~(PN | PZ) | DataPNZ[RA]; + CC += cc; + } + + private void ExecuteTxs(int cc) + { + RS = RX; + CC += cc; + } + + private void ExecuteTya(int cc) + { + RA = RY; + RP = RP & ~(PN | PZ) | DataPNZ[RA]; + CC += cc; + } + #endregion + + #region 6502 OpCode Actions + private void Execute65X02And21() // and (zpg, x) + { + GetAddressZpgIndX(); + ExecuteAnd(ReadZpgIndX(), 6); + } + + private void Execute65X02And25() // and zpg + { + GetAddressZpg(); + ExecuteAnd(ReadZpg(), 3); + } + + private void Execute65X02And29() // and imm + { + ExecuteAnd(ReadImm(), 2); + } + + private void Execute65X02And2D() // and abs + { + GetAddressAbs(); + ExecuteAnd(ReadAbs(), 4); + } + + private void Execute65X02And31() // and (zpg), y + { + GetAddressZpgIndYCC(); + ExecuteAnd(ReadZpgIndY(), 5); + } + + private void Execute65X02And35() // and zpg, x + { + GetAddressZpgX(); + ExecuteAnd(ReadZpgX(), 4); + } + + private void Execute65X02And39() // and abs, y + { + GetAddressAbsYCC(); + ExecuteAnd(ReadAbsY(), 4); + } + + private void Execute65X02And3D() // and abs, x + { + GetAddressAbsXCC(); + ExecuteAnd(ReadAbsX(), 4); + } + + private void Execute65X02Asl06() // asl zpg + { + GetAddressZpg(); + WriteZpg(ExecuteAsl(ReadZpg(), 5)); + } + + private void Execute65X02Asl0A() // asl imp + { + ExecuteAslImp(2); + } + + private void Execute65X02Asl0E() // asl abs + { + GetAddressAbs(); + WriteAbs(ExecuteAsl(ReadAbs(), 6)); + } + + private void Execute65X02Asl16() // asl zpg, x + { + GetAddressZpgX(); + WriteZpgX(ExecuteAsl(ReadZpgX(), 6)); + } + + private void Execute65X02Bcc90() // bcc rel + { + ExecuteBcc(2); + } + + private void Execute65X02BcsB0() // bcs rel + { + ExecuteBcs(2); + } + + private void Execute65X02BeqF0() // beq rel + { + ExecuteBeq(2); + } + + private void Execute65X02Bit24() // bit zpg + { + GetAddressZpg(); + ExecuteBit(ReadZpg(), 3); + } + + private void Execute65X02Bit2C() // bit abs + { + GetAddressAbs(); + ExecuteBit(ReadAbs(), 4); + } + + private void Execute65X02Bmi30() // bmi rel + { + ExecuteBmi(2); + } + + private void Execute65X02BneD0() // bne rel + { + ExecuteBne(2); + } + + private void Execute65X02Bpl10() // bpl rel + { + ExecuteBpl(2); + } + + private void Execute65X02Brk00() // brk imp + { + ExecuteBrk(7); + } + + private void Execute65X02Bvc50() // bvc rel + { + ExecuteBvc(2); + } + + private void Execute65X02Bvs70() // bvs rel + { + ExecuteBvs(2); + } + + private void Execute65X02Clc18() // clc imp + { + ExecuteClc(2); + } + + private void Execute65X02CldD8() // cld imp + { + ExecuteCld(2); + } + + private void Execute65X02Cli58() // cli imp + { + ExecuteCli(2); + } + + private void Execute65X02ClvB8() // clv imp + { + ExecuteClv(2); + } + + private void Execute65X02CmpC1() // cmp (zpg, x) + { + GetAddressZpgIndX(); + ExecuteCmp(ReadZpgIndX(), 6); + } + + private void Execute65X02CmpC5() // cmp zpg + { + GetAddressZpg(); + ExecuteCmp(ReadZpg(), 3); + } + + private void Execute65X02CmpC9() // cmp imm + { + ExecuteCmp(ReadImm(), 2); + } + + private void Execute65X02CmpCD() // cmp abs + { + GetAddressAbs(); + ExecuteCmp(ReadAbs(), 4); + } + + private void Execute65X02CmpD1() // cmp (zpg), y + { + GetAddressZpgIndYCC(); + ExecuteCmp(ReadZpgIndY(), 5); + } + + private void Execute65X02CmpD5() // cmp zpg, x + { + GetAddressZpgX(); + ExecuteCmp(ReadZpgX(), 4); + } + + private void Execute65X02CmpD9() // cmp abs, y + { + GetAddressAbsYCC(); + ExecuteCmp(ReadAbsY(), 4); + } + + private void Execute65X02CmpDD() // cmp abs, x + { + GetAddressAbsXCC(); + ExecuteCmp(ReadAbsX(), 4); + } + + private void Execute65X02CpxE0() // cpx imm + { + ExecuteCpx(ReadImm(), 2); + } + + private void Execute65X02CpxE4() // cpx zpg + { + GetAddressZpg(); + ExecuteCpx(ReadZpg(), 3); + } + + private void Execute65X02CpxEC() // cpx abs + { + GetAddressAbs(); + ExecuteCpx(ReadAbs(), 4); + } + + private void Execute65X02CpyC0() // cpy imm + { + ExecuteCpy(ReadImm(), 2); + } + + private void Execute65X02CpyC4() // cpy zpg + { + GetAddressZpg(); + ExecuteCpy(ReadZpg(), 3); + } + + private void Execute65X02CpyCC() // cpy abs + { + GetAddressAbs(); + ExecuteCpy(ReadAbs(), 4); + } + + private void Execute65X02DecC6() // dec zpg + { + GetAddressZpg(); + WriteZpg(ExecuteDec(ReadZpg(), 5)); + } + + private void Execute65X02DecCE() // dec abs + { + GetAddressAbs(); + WriteAbs(ExecuteDec(ReadAbs(), 6)); + } + + private void Execute65X02DecD6() // dec zpg, x + { + GetAddressZpgX(); + WriteZpgX(ExecuteDec(ReadZpgX(), 6)); + } + + private void Execute65X02DexCA() // dex imp + { + ExecuteDex(2); + } + + private void Execute65X02Dey88() // dey imp + { + ExecuteDey(2); + } + + private void Execute65X02Eor41() // eor (zpg, x) + { + GetAddressZpgIndX(); + ExecuteEor(ReadZpgIndX(), 6); + } + + private void Execute65X02Eor45() // eor zpg + { + GetAddressZpg(); + ExecuteEor(ReadZpg(), 3); + } + + private void Execute65X02Eor49() // eor imm + { + ExecuteEor(ReadImm(), 2); + } + + private void Execute65X02Eor4D() // eor abs + { + GetAddressAbs(); + ExecuteEor(ReadAbs(), 4); + } + + private void Execute65X02Eor51() // eor (zpg), y + { + GetAddressZpgIndYCC(); + ExecuteEor(ReadZpgIndY(), 5); + } + + private void Execute65X02Eor55() // eor zpg, x + { + GetAddressZpgX(); + ExecuteEor(ReadZpgX(), 4); + } + + private void Execute65X02Eor59() // eor abs, y + { + GetAddressAbsYCC(); + ExecuteEor(ReadAbsY(), 4); + } + + private void Execute65X02Eor5D() // eor abs, x + { + GetAddressAbsXCC(); + ExecuteEor(ReadAbsX(), 4); + } + + private void Execute65X02IncE6() // inc zpg + { + GetAddressZpg(); + WriteZpg(ExecuteInc(ReadZpg(), 5)); + } + + private void Execute65X02IncEE() // inc abs + { + GetAddressAbs(); + WriteAbs(ExecuteInc(ReadAbs(), 6)); + } + + private void Execute65X02IncF6() // inc zpg, x + { + GetAddressZpgX(); + WriteZpgX(ExecuteInc(ReadZpgX(), 6)); + } + + private void Execute65X02InxE8() // inx imp + { + ExecuteInx(2); + } + + private void Execute65X02InyC8() // iny imp + { + ExecuteIny(2); + } + + private void Execute65X02Jmp4C() // jmp abs + { + ExecuteJmpAbs(3); + } + + private void Execute65X02Jsr20() // jsr abs + { + ExecuteJsr(6); + } + + private void Execute65X02LdaA1() // lda (zpg, x) + { + GetAddressZpgIndX(); + ExecuteLda(ReadZpgIndX(), 6); + } + + private void Execute65X02LdaA5() // lda zpg + { + GetAddressZpg(); + ExecuteLda(ReadZpg(), 3); + } + + private void Execute65X02LdaA9() // lda imm + { + ExecuteLda(ReadImm(), 2); + } + + private void Execute65X02LdaAD() // lda abs + { + GetAddressAbs(); + ExecuteLda(ReadAbs(), 4); + } + + private void Execute65X02LdaB1() // lda (zpg), y + { + GetAddressZpgIndYCC(); + ExecuteLda(ReadZpgIndY(), 5); + } + + private void Execute65X02LdaB5() // lda zpg, x + { + GetAddressZpgX(); + ExecuteLda(ReadZpgX(), 4); + } + + private void Execute65X02LdaB9() // lda abs, y + { + GetAddressAbsYCC(); + ExecuteLda(ReadAbsY(), 4); + } + + private void Execute65X02LdaBD() // lda abs, x + { + GetAddressAbsXCC(); + ExecuteLda(ReadAbsX(), 4); + } + + private void Execute65X02LdxA2() // ldx imm + { + ExecuteLdx(ReadImm(), 2); + } + + private void Execute65X02LdxA6() // ldx zpg + { + GetAddressZpg(); + ExecuteLdx(ReadZpg(), 3); + } + + private void Execute65X02LdxAE() // ldx abs + { + GetAddressAbs(); + ExecuteLdx(ReadAbs(), 4); + } + + private void Execute65X02LdxB6() // ldx zpg, y + { + GetAddressZpgY(); + ExecuteLdx(ReadZpgY(), 4); + } + + private void Execute65X02LdxBE() // ldx abs, y + { + GetAddressAbsYCC(); + ExecuteLdx(ReadAbsY(), 4); + } + + private void Execute65X02LdyA0() // ldy imm + { + ExecuteLdy(ReadImm(), 2); + } + + private void Execute65X02LdyA4() // ldy zpg + { + GetAddressZpg(); + ExecuteLdy(ReadZpg(), 3); + } + + private void Execute65X02LdyAC() // ldy abs + { + GetAddressAbs(); + ExecuteLdy(ReadAbs(), 4); + } + + private void Execute65X02LdyB4() // ldy zpg, x + { + GetAddressZpgX(); + ExecuteLdy(ReadZpgX(), 4); + } + + private void Execute65X02LdyBC() // ldy abs, x + { + GetAddressAbsXCC(); + ExecuteLdy(ReadAbsX(), 4); + } + + private void Execute65X02Lsr46() // lsr zpg + { + GetAddressZpg(); + WriteZpg(ExecuteLsr(ReadZpg(), 5)); + } + + private void Execute65X02Lsr4A() // lsr imp + { + ExecuteLsrImp(2); + } + + private void Execute65X02Lsr4E() // lsr abs + { + GetAddressAbs(); + WriteAbs(ExecuteLsr(ReadAbs(), 6)); + } + + private void Execute65X02Lsr56() // lsr zpg, x + { + GetAddressZpgX(); + WriteZpgX(ExecuteLsr(ReadZpgX(), 6)); + } + + private void Execute65X02NopEA() // nop imp + { + ExecuteNop(2); + } + + private void Execute65X02Ora01() // ora (zpg, x) + { + GetAddressZpgIndX(); + ExecuteOra(ReadZpgIndX(), 6); + } + + private void Execute65X02Ora05() // ora zpg + { + GetAddressZpg(); + ExecuteOra(ReadZpg(), 3); + } + + private void Execute65X02Ora09() // ora imm + { + ExecuteOra(ReadImm(), 2); + } + + private void Execute65X02Ora0D() // ora abs + { + GetAddressAbs(); + ExecuteOra(ReadAbs(), 4); + } + + private void Execute65X02Ora11() // ora (zpg), y + { + GetAddressZpgIndYCC(); + ExecuteOra(ReadZpgIndY(), 5); + } + + private void Execute65X02Ora15() // ora zpg, x + { + GetAddressZpgX(); + ExecuteOra(ReadZpgX(), 4); + } + + private void Execute65X02Ora19() // ora abs, y + { + GetAddressAbsYCC(); + ExecuteOra(ReadAbsY(), 4); + } + + private void Execute65X02Ora1D() // ora abs, x + { + GetAddressAbsXCC(); + ExecuteOra(ReadAbsX(), 4); + } + + private void Execute65X02Pha48() // pha imp + { + ExecutePha(3); + } + + private void Execute65X02Php08() // php imp + { + ExecutePhp(3); + } + + private void Execute65X02Pla68() // pla imp + { + ExecutePla(4); + } + + private void Execute65X02Plp28() // plp imp + { + ExecutePlp(4); + } + + private void Execute65X02Rol26() // rol zpg + { + GetAddressZpg(); + WriteZpg(ExecuteRol(ReadZpg(), 5)); + } + + private void Execute65X02Rol2A() // rol imp + { + ExecuteRolImp(2); + } + + private void Execute65X02Rol2E() // rol abs + { + GetAddressAbs(); + WriteAbs(ExecuteRol(ReadAbs(), 6)); + } + + private void Execute65X02Rol36() // rol zpg, x + { + GetAddressZpgX(); + WriteZpgX(ExecuteRol(ReadZpgX(), 6)); + } + + private void Execute65X02Ror66() // ror zpg + { + GetAddressZpg(); + WriteZpg(ExecuteRor(ReadZpg(), 5)); + } + + private void Execute65X02Ror6A() // ror imp + { + ExecuteRorImp(2); + } + + private void Execute65X02Ror6E() // ror abs + { + GetAddressAbs(); + WriteAbs(ExecuteRor(ReadAbs(), 6)); + } + + private void Execute65X02Ror76() // ror zpg, x + { + GetAddressZpgX(); + WriteZpgX(ExecuteRor(ReadZpgX(), 6)); + } + + private void Execute65X02Rti40() // rti imp + { + ExecuteRti(6); + } + + private void Execute65X02Rts60() // rts imp + { + ExecuteRts(6); + } + + private void Execute65X02Sec38() // sec imp + { + ExecuteSec(2); + } + + private void Execute65X02SedF8() // sed imp + { + ExecuteSed(2); + } + + private void Execute65X02Sei78() // sei imp + { + ExecuteSei(2); + } + + private void Execute65X02Sta81() // sta (zpg, x) + { + GetAddressZpgIndX(); + WriteZpgIndX(RA); + ExecuteSta(6); + } + + private void Execute65X02Sta85() // sta zpg + { + GetAddressZpg(); + WriteZpg(RA); + ExecuteSta(3); + } + + private void Execute65X02Sta8D() // sta abs + { + GetAddressAbs(); + WriteAbs(RA); + ExecuteSta(4); + } + + private void Execute65X02Sta91() // sta (zpg), y + { + GetAddressZpgIndY(); + WriteZpgIndY(RA); + ExecuteSta(6); + } + + private void Execute65X02Sta95() // sta zpg, x + { + GetAddressZpgX(); + WriteZpgX(RA); + ExecuteSta(4); + } + + private void Execute65X02Sta99() // sta abs, y + { + GetAddressAbsY(); + WriteAbsY(RA); + ExecuteSta(5); + } + + private void Execute65X02Sta9D() // sta abs, x + { + GetAddressAbsX(); + WriteAbsX(RA); + ExecuteSta(5); + } + + private void Execute65X02Stx86() // stx zpg + { + GetAddressZpg(); + WriteZpg(RX); + ExecuteStx(3); + } + + private void Execute65X02Stx8E() // stx abs + { + GetAddressAbs(); + WriteAbs(RX); + ExecuteStx(4); + } + + private void Execute65X02Stx96() // stx zpg, y + { + GetAddressZpgY(); + WriteZpgY(RX); + ExecuteStx(4); + } + + private void Execute65X02Sty84() // sty zpg + { + GetAddressZpg(); + WriteZpg(RY); + ExecuteSty(3); + } + + private void Execute65X02Sty8C() // sty abs + { + GetAddressAbs(); + WriteAbs(RY); + ExecuteSty(4); + } + + private void Execute65X02Sty94() // sty zpg, x + { + GetAddressZpgX(); + WriteZpgX(RY); + ExecuteSty(4); + } + + private void Execute65X02TaxAA() // tax imp + { + ExecuteTax(2); + } + + private void Execute65X02TayA8() // tay imp + { + ExecuteTay(2); + } + + private void Execute65X02TsxBA() // tsx imp + { + ExecuteTsx(2); + } + + private void Execute65X02Txa8A() // txa imp + { + ExecuteTxa(2); + } + + private void Execute65X02Txs9A() // txs imp + { + ExecuteTxs(2); + } + + private void Execute65X02Tya98() // tya imp + { + ExecuteTya(2); + } + #endregion + + #region 65N02 OpCode Actions + private void Execute65N02Adc61() // adc (zpg, x) + { + GetAddressZpgIndX(); + ExecuteAdc65N02(ReadZpgIndX(), 6); + } + + private void Execute65N02Adc65() // adc zpg + { + GetAddressZpg(); + ExecuteAdc65N02(ReadZpg(), 3); + } + + private void Execute65N02Adc69() // adc imm + { + ExecuteAdc65N02(ReadImm(), 2); + } + + private void Execute65N02Adc6D() // adc abs + { + GetAddressAbs(); + ExecuteAdc65N02(ReadAbs(), 4); + } + + private void Execute65N02Adc71() // adc (zpg), y + { + GetAddressZpgIndYCC(); + ExecuteAdc65N02(ReadZpgIndY(), 5); + } + + private void Execute65N02Adc75() // adc zpg, x + { + GetAddressZpgX(); + ExecuteAdc65N02(ReadZpgX(), 4); + } + + private void Execute65N02Adc79() // adc abs, y + { + GetAddressAbsYCC(); + ExecuteAdc65N02(ReadAbsY(), 4); + } + + private void Execute65N02Adc7D() // adc abs, x + { + GetAddressAbsXCC(); + ExecuteAdc65N02(ReadAbsX(), 4); + } + + private void Execute65N02Asl1E() // asl abs, x + { + GetAddressAbsX(); + WriteAbsX(ExecuteAsl(ReadAbsX(), 7)); + } + + private void Execute65N02DecDE() // dec abs, x + { + GetAddressAbsX(); + WriteAbsX(ExecuteDec(ReadAbsX(), 7)); + } + + private void Execute65N02IncFE() // inc abs, x + { + GetAddressAbsX(); + WriteAbsX(ExecuteInc(ReadAbsX(), 7)); + } + + private void Execute65N02Jmp6C() // jmp (abs) + { + ExecuteJmpAbsInd65N02(5); + } + + private void Execute65N02Lsr5E() // lsr abs, x + { + GetAddressAbsX(); + WriteAbsX(ExecuteLsr(ReadAbsX(), 7)); + } + + private void Execute65N02Nop02() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02Nop03() // nop imp1 + { + ExecuteNop(1, 6); + } + + private void Execute65N02Nop04() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02Nop07() // nop imp1 + { + ExecuteNop(1, 5); + } + + private void Execute65N02Nop0B() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02Nop0C() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02Nop0F() // nop imp2 + { + ExecuteNop(2, 6); + } + + private void Execute65N02Nop12() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02Nop13() // nop imp1 + { + ExecuteNop(1, 6); + } + + private void Execute65N02Nop14() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02Nop17() // nop imp1 + { + ExecuteNop(1, 6); + } + + private void Execute65N02Nop1A() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02Nop1B() // nop imp2 + { + ExecuteNop(2, 6); + } + + private void Execute65N02Nop1C() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02Nop1F() // nop imp2 + { + ExecuteNop(2, 6); + } + + private void Execute65N02Nop22() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02Nop23() // nop imp1 + { + ExecuteNop(1, 6); + } + + private void Execute65N02Nop27() // nop imp1 + { + ExecuteNop(1, 3); + } + + private void Execute65N02Nop2B() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02Nop2F() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02Nop32() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02Nop33() // nop imp1 + { + ExecuteNop(1, 5); + } + + private void Execute65N02Nop34() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02Nop37() // nop imp1 + { + ExecuteNop(1, 4); + } + + private void Execute65N02Nop3A() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02Nop3B() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02Nop3C() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02Nop3F() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02Nop42() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02Nop43() // nop imp1 + { + ExecuteNop(1, 6); + } + + private void Execute65N02Nop44() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02Nop47() // nop imp1 + { + ExecuteNop(1, 3); + } + + private void Execute65N02Nop4B() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02Nop4F() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02Nop52() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02Nop53() // nop imp1 + { + ExecuteNop(1, 5); + } + + private void Execute65N02Nop54() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02Nop57() // nop imp1 + { + ExecuteNop(1, 4); + } + + private void Execute65N02Nop5A() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02Nop5B() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02Nop5C() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02Nop5F() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02Nop62() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02Nop63() // nop imp1 + { + ExecuteNop(1, 6); + } + + private void Execute65N02Nop64() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02Nop67() // nop imp1 + { + ExecuteNop(1, 3); + } + + private void Execute65N02Nop6B() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02Nop6F() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02Nop72() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02Nop73() // nop imp1 + { + ExecuteNop(1, 5); + } + + private void Execute65N02Nop74() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02Nop77() // nop imp1 + { + ExecuteNop(1, 4); + } + + private void Execute65N02Nop7A() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02Nop7B() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02Nop7C() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02Nop7F() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02Nop80() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02Nop82() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02Nop83() // nop imp1 + { + ExecuteNop(1, 4); + } + + private void Execute65N02Nop87() // nop imp1 + { + ExecuteNop(1, 3); + } + + private void Execute65N02Nop89() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02Nop8B() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02Nop8F() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02Nop92() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02Nop93() // nop imp1 + { + ExecuteNop(1, 6); + } + + private void Execute65N02Nop97() // nop imp1 + { + ExecuteNop(1, 4); + } + + private void Execute65N02Nop9B() // nop imp2 + { + ExecuteNop(2, 5); + } + + private void Execute65N02Nop9C() // nop imp2 + { + ExecuteNop(2, 5); + } + + private void Execute65N02Nop9E() // nop imp2 + { + ExecuteNop(2, 5); + } + + private void Execute65N02Nop9F() // nop imp2 + { + ExecuteNop(2, 5); + } + + private void Execute65N02NopA3() // nop imp1 + { + ExecuteNop(1, 6); + } + + private void Execute65N02NopA7() // nop imp1 + { + ExecuteNop(1, 3); + } + + private void Execute65N02NopAB() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02NopAF() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02NopB2() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02NopB3() // nop imp1 + { + ExecuteNop(1, 5); + } + + private void Execute65N02NopB7() // nop imp1 + { + ExecuteNop(1, 4); + } + + private void Execute65N02NopBB() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02NopBF() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02NopC2() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02NopC3() // nop imp1 + { + ExecuteNop(1, 6); + } + + private void Execute65N02NopC7() // nop imp1 + { + ExecuteNop(1, 5); + } + + private void Execute65N02NopCB() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02NopCF() // nop imp2 + { + ExecuteNop(2, 6); + } + + private void Execute65N02NopD2() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02NopD3() // nop imp1 + { + ExecuteNop(1, 6); + } + + private void Execute65N02NopD4() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02NopD7() // nop imp1 + { + ExecuteNop(1, 6); + } + + private void Execute65N02NopDA() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02NopDB() // nop imp2 + { + ExecuteNop(2, 6); + } + + private void Execute65N02NopDC() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02NopDF() // nop imp2 + { + ExecuteNop(2, 6); + } + + private void Execute65N02NopE2() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02NopE3() // nop imp1 + { + ExecuteNop(1, 6); + } + + private void Execute65N02NopE7() // nop imp1 + { + ExecuteNop(1, 5); + } + + private void Execute65N02NopEB() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02NopEF() // nop imp2 + { + ExecuteNop(2, 6); + } + + private void Execute65N02NopF2() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02NopF3() // nop imp1 + { + ExecuteNop(1, 6); + } + + private void Execute65N02NopF4() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65N02NopF7() // nop imp1 + { + ExecuteNop(1, 6); + } + + private void Execute65N02NopFA() // nop imp0 + { + ExecuteNop(0, 2); + } + + private void Execute65N02NopFB() // nop imp2 + { + ExecuteNop(2, 6); + } + + private void Execute65N02NopFC() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65N02NopFF() // nop imp2 + { + ExecuteNop(2, 6); + } + + private void Execute65N02Rol3E() // rol abs, x + { + GetAddressAbsX(); + WriteAbsX(ExecuteRol(ReadAbsX(), 7)); + } + + private void Execute65N02Ror7E() // ror abs, x + { + GetAddressAbsX(); + WriteAbsX(ExecuteRor(ReadAbsX(), 7)); + } + + private void Execute65N02SbcE1() // sbc (zpg, x) + { + GetAddressZpgIndX(); + ExecuteSbc65N02(ReadZpgIndX(), 6); + } + + private void Execute65N02SbcE5() // sbc zpg + { + GetAddressZpg(); + ExecuteSbc65N02(ReadZpg(), 3); + } + + private void Execute65N02SbcE9() // sbc imm + { + ExecuteSbc65N02(ReadImm(), 2); + } + + private void Execute65N02SbcED() // sbc abs + { + GetAddressAbs(); + ExecuteSbc65N02(ReadAbs(), 4); + } + + private void Execute65N02SbcF1() // sbc (zpg), y + { + GetAddressZpgIndYCC(); + ExecuteSbc65N02(ReadZpgIndY(), 5); + } + + private void Execute65N02SbcF5() // sbc zpg, x + { + GetAddressZpgX(); + ExecuteSbc65N02(ReadZpgX(), 4); + } + + private void Execute65N02SbcF9() // sbc abs, y + { + GetAddressAbsYCC(); + ExecuteSbc65N02(ReadAbsY(), 4); + } + + private void Execute65N02SbcFD() // sbc abs, x + { + GetAddressAbsXCC(); + ExecuteSbc65N02(ReadAbsX(), 4); + } + #endregion + + #region 65C02 OpCode Actions + private void Execute65C02Adc61() // adc (zpg, x) + { + GetAddressZpgIndX(); + ExecuteAdc65C02(ReadZpgIndX(), 6); + } + + private void Execute65C02Adc65() // adc zpg + { + GetAddressZpg(); + ExecuteAdc65C02(ReadZpg(), 3); + } + + private void Execute65C02Adc69() // adc imm + { + ExecuteAdc65C02(ReadImm(), 2); + } + + private void Execute65C02Adc6D() // adc abs + { + GetAddressAbs(); + ExecuteAdc65C02(ReadAbs(), 4); + } + + private void Execute65C02Adc71() // adc (zpg), y + { + GetAddressZpgIndYCC(); + ExecuteAdc65C02(ReadZpgIndY(), 5); + } + + private void Execute65C02Adc72() // adc (zpg) + { + GetAddressZpgInd(); + ExecuteAdc65C02(ReadZpgInd(), 5); + } + + private void Execute65C02Adc75() // adc zpg, x + { + GetAddressZpgX(); + ExecuteAdc65C02(ReadZpgX(), 4); + } + + private void Execute65C02Adc79() // adc abs, y + { + GetAddressAbsYCC(); + ExecuteAdc65C02(ReadAbsY(), 4); + } + + private void Execute65C02Adc7D() // adc abs, x + { + GetAddressAbsXCC(); + ExecuteAdc65C02(ReadAbsX(), 4); + } + + private void Execute65C02And32() // and (zpg) + { + GetAddressZpgInd(); + ExecuteAnd(ReadZpgInd(), 5); + } + + private void Execute65C02Asl1E() // asl abs, x + { + GetAddressAbsXCC(); + WriteAbsX(ExecuteAsl(ReadAbsX(), 6)); + } + + private void Execute65C02Bit34() // bit zpg, x + { + GetAddressZpgX(); + ExecuteBit(ReadZpgX(), 4); + } + + private void Execute65C02Bit3C() // bit abs, x + { + GetAddressAbsXCC(); + ExecuteBit(ReadAbsX(), 4); + } + + private void Execute65C02Bit89() // bit imm + { + ExecuteBitImm(ReadImm(), 2); + } + + private void Execute65C02Bra80() // bra rel + { + ExecuteBra(2); + } + + private void Execute65C02CmpD2() // cmp (zpg) + { + GetAddressZpgInd(); + ExecuteCmp(ReadZpgInd(), 5); + } + + private void Execute65C02Dea3A() // dea imp + { + ExecuteDea(2); + } + + private void Execute65C02DecDE() // dec abs, x + { + GetAddressAbsXCC(); + WriteAbsX(ExecuteDec(ReadAbsX(), 6)); + } + + private void Execute65C02Eor52() // eor (zpg) + { + GetAddressZpgInd(); + ExecuteEor(ReadZpgInd(), 5); + } + + private void Execute65C02Ina1A() // ina imp + { + ExecuteIna(2); + } + + private void Execute65C02IncFE() // inc abs, x + { + GetAddressAbsXCC(); + WriteAbsX(ExecuteInc(ReadAbsX(), 6)); + } + + private void Execute65C02Jmp6C() // jmp (abs) + { + ExecuteJmpAbsInd65C02(6); + } + + private void Execute65C02Jmp7C() // jmp (abs, x) + { + ExecuteJmpAbsIndX(6); + } + + private void Execute65C02LdaB2() // lda (zpg) + { + GetAddressZpgInd(); + ExecuteLda(ReadZpgInd(), 5); + } + + private void Execute65C02Lsr5E() // lsr abs, x + { + GetAddressAbsXCC(); + WriteAbsX(ExecuteLsr(ReadAbsX(), 6)); + } + + private void Execute65C02Nop02() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65C02Nop03() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop07() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop0B() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop0F() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop13() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop17() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop1B() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop1F() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop22() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65C02Nop23() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop27() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop2B() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop2F() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop33() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop37() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop3B() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop3F() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop42() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65C02Nop43() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop44() // nop imp1 + { + ExecuteNop(1, 3); + } + + private void Execute65C02Nop47() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop4B() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop4F() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop53() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop54() // nop imp1 + { + ExecuteNop(1, 4); + } + + private void Execute65C02Nop57() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop5B() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop5C() // nop imp2 + { + ExecuteNop(2, 8); + } + + private void Execute65C02Nop5F() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop62() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65C02Nop63() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop67() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop6B() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop6F() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop73() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop77() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop7B() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop7F() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop82() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65C02Nop83() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop87() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop8B() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop8F() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop93() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop97() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop9B() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Nop9F() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopA3() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopA7() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopAB() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopAF() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopB3() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopB7() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopBB() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopBF() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopC2() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65C02NopC3() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopC7() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopCB() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopCF() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopD3() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopD4() // nop imp1 + { + ExecuteNop(1, 4); + } + + private void Execute65C02NopD7() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopDB() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopDC() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65C02NopDF() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopE2() // nop imp1 + { + ExecuteNop(1, 2); + } + + private void Execute65C02NopE3() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopE7() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopEB() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopEF() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopF3() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopF4() // nop imp1 + { + ExecuteNop(1, 4); + } + + private void Execute65C02NopF7() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopFB() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02NopFC() // nop imp2 + { + ExecuteNop(2, 4); + } + + private void Execute65C02NopFF() // nop imp0 + { + ExecuteNop(0, 1); + } + + private void Execute65C02Ora12() // ora (zpg) + { + GetAddressZpgInd(); + ExecuteOra(ReadZpgInd(), 5); + } + + private void Execute65C02PhxDA() // phx imp + { + ExecutePhx(3); + } + + private void Execute65C02Phy5A() // phy imp + { + ExecutePhy(3); + } + + private void Execute65C02PlxFA() // plx imp + { + ExecutePlx(4); + } + + private void Execute65C02Ply7A() // ply imp + { + ExecutePly(4); + } + + private void Execute65C02Rol3E() // rol abs, x + { + GetAddressAbsXCC(); + WriteAbsX(ExecuteRol(ReadAbsX(), 6)); + } + + private void Execute65C02Ror7E() // ror abs, x + { + GetAddressAbsXCC(); + WriteAbsX(ExecuteRor(ReadAbsX(), 6)); + } + + private void Execute65C02SbcE1() // sbc (zpg, x) + { + GetAddressZpgIndX(); + ExecuteSbc65C02(ReadZpgIndX(), 6); + } + + private void Execute65C02SbcE5() // sbc zpg + { + GetAddressZpg(); + ExecuteSbc65C02(ReadZpg(), 3); + } + + private void Execute65C02SbcE9() // sbc imm + { + ExecuteSbc65C02(ReadImm(), 2); + } + + private void Execute65C02SbcED() // sbc abs + { + GetAddressAbs(); + ExecuteSbc65C02(ReadAbs(), 4); + } + + private void Execute65C02SbcF1() // sbc (zpg), y + { + GetAddressZpgIndYCC(); + ExecuteSbc65C02(ReadZpgIndY(), 5); + } + + private void Execute65C02SbcF2() // sbc (zpg) + { + GetAddressZpgInd(); + ExecuteSbc65C02(ReadZpgInd(), 5); + } + + private void Execute65C02SbcF5() // sbc zpg, x + { + GetAddressZpgX(); + ExecuteSbc65C02(ReadZpgX(), 4); + } + + private void Execute65C02SbcF9() // sbc abs, y + { + GetAddressAbsYCC(); + ExecuteSbc65C02(ReadAbsY(), 4); + } + + private void Execute65C02SbcFD() // sbc abs, x + { + GetAddressAbsXCC(); + ExecuteSbc65C02(ReadAbsX(), 4); + } + + private void Execute65C02Sta92() // sta (zpg) + { + GetAddressZpgInd(); + WriteZpgInd(RA); + ExecuteSta(5); + } + + private void Execute65C02Stz64() // stz zpg + { + GetAddressZpg(); + WriteZpg(0x00); + ExecuteStz(3); + } + + private void Execute65C02Stz74() // stz zpg, x + { + GetAddressZpgX(); + WriteZpgX(0x00); + ExecuteStz(4); + } + + private void Execute65C02Stz9C() // stz abs + { + GetAddressAbs(); + WriteAbs(0x00); + ExecuteStz(4); + } + + private void Execute65C02Stz9E() // stz abs, x + { + GetAddressAbsX(); + WriteAbsX(0x00); + ExecuteStz(5); + } + + private void Execute65C02Trb14() // trb zpg + { + GetAddressZpg(); + WriteZpg(ExecuteTrb(ReadZpg(), 5)); + } + + private void Execute65C02Trb1C() // trb abs + { + GetAddressAbs(); + WriteAbs(ExecuteTrb(ReadAbs(), 6)); + } + + private void Execute65C02Tsb04() // tsb zpg + { + GetAddressZpg(); + WriteZpg(ExecuteTsb(ReadZpg(), 5)); + } + + private void Execute65C02Tsb0C() // tsb abs + { + GetAddressAbs(); + WriteAbs(ExecuteTsb(ReadAbs(), 6)); + } + #endregion + + 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; } + public int RY { get; private set; } + public int RS { get; private set; } + public int RP { get; private set; } + public int RPC { get; private set; } + public int EA { get; private set; } + public int CC { get; private set; } + public int OpCode { get; private set; } + public long Cycles { get; private set; } + + private Memory _memory; + + private bool _is65C02; + private Action[] _executeOpCode; + } +} diff --git a/Virtu/CpuData.cs b/Virtu/CpuData.cs index b0baaef..361aa55 100644 --- a/Virtu/CpuData.cs +++ b/Virtu/CpuData.cs @@ -1,83 +1,83 @@ -using System; - -namespace Jellyfish.Virtu -{ - public partial class Cpu - { - private const int OpCodeCount = 256; - - private readonly Action[] ExecuteOpCode65N02; - private readonly Action[] ExecuteOpCode65C02; - - private const int PC = 0x01; - private const int PZ = 0x02; - private const int PI = 0x04; - private const int PD = 0x08; - private const int PB = 0x10; - private const int PR = 0x20; - private const int PV = 0x40; - private const int PN = 0x80; - - private const int DataCount = 256; - - private static readonly int[] DataPN = new int[DataCount] - { - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, - PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, - PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, - PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, - PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, - PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, - PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, - PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN - }; - - private static readonly int[] DataPZ = new int[DataCount] - { - PZ, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 - }; - - private static readonly int[] DataPNZ = new int[DataCount] - { - PZ, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, - PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, - PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, - PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, - PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, - PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, - PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, - PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN - }; - } -} +using System; + +namespace Jellyfish.Virtu +{ + public partial class Cpu + { + private const int OpCodeCount = 256; + + private readonly Action[] ExecuteOpCode65N02; + private readonly Action[] ExecuteOpCode65C02; + + private const int PC = 0x01; + private const int PZ = 0x02; + private const int PI = 0x04; + private const int PD = 0x08; + private const int PB = 0x10; + private const int PR = 0x20; + private const int PV = 0x40; + private const int PN = 0x80; + + private const int DataCount = 256; + + private static readonly int[] DataPN = new int[DataCount] + { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, + PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, + PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, + PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, + PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, + PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, + PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, + PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN + }; + + private static readonly int[] DataPZ = new int[DataCount] + { + PZ, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 + }; + + private static readonly int[] DataPNZ = new int[DataCount] + { + PZ, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, + PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, + PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, + PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, + PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, + PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, + PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, + PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN, PN + }; + } +} diff --git a/Virtu/CustomDictionary.xml b/Virtu/CustomDictionary.xml index c706f7a..f31a749 100644 --- a/Virtu/CustomDictionary.xml +++ b/Virtu/CustomDictionary.xml @@ -1,28 +1,28 @@ - - - - - Io - RPC - - - - - Annunciator - Cpu - Dsk - Prg - Unpause - Virtu - Xex - Xna - x - y - - - DownRight - GamePad - UpRight - - - + + + + + Io + RPC + + + + + Annunciator + Cpu + Dsk + Prg + Unpause + Virtu + Xex + Xna + x + y + + + DownRight + GamePad + UpRight + + + diff --git a/Virtu/Disk525.cs b/Virtu/Disk525.cs index 6f9c92c..a21e39c 100644 --- a/Virtu/Disk525.cs +++ b/Virtu/Disk525.cs @@ -1,97 +1,97 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Text.RegularExpressions; -using Jellyfish.Library; - -namespace Jellyfish.Virtu -{ - public abstract class Disk525 - { - protected Disk525(string name, byte[] data, bool isWriteProtected) - { - Name = name; - Data = data; - IsWriteProtected = isWriteProtected; - } - - public static Disk525 CreateDisk(string name, Stream stream, bool isWriteProtected) - { - if (name == null) - { - throw new ArgumentNullException("name"); - } - - if (name.EndsWith(".do", StringComparison.OrdinalIgnoreCase) || - name.EndsWith(".dsk", StringComparison.OrdinalIgnoreCase)) // assumes dos sector skew - { - return new DiskDsk(name, stream, isWriteProtected, SectorSkew.Dos); - } - else if (name.EndsWith(".nib", StringComparison.OrdinalIgnoreCase)) - { - return new DiskNib(name, stream, isWriteProtected); - } - else if (name.EndsWith(".po", StringComparison.OrdinalIgnoreCase)) - { - return new DiskDsk(name, stream, isWriteProtected, SectorSkew.ProDos); - } - - 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(); - var data = reader.ReadBytes(reader.ReadInt32()); - bool isWriteProtected = reader.ReadBoolean(); - - if (name.EndsWith(".do", StringComparison.OrdinalIgnoreCase) || - name.EndsWith(".dsk", StringComparison.OrdinalIgnoreCase)) // assumes dos sector skew - { - return new DiskDsk(name, data, isWriteProtected, SectorSkew.Dos); - } - else if (name.EndsWith(".nib", StringComparison.OrdinalIgnoreCase)) - { - return new DiskNib(name, data, isWriteProtected); - } - else if (name.EndsWith(".po", StringComparison.OrdinalIgnoreCase)) - { - return new DiskDsk(name, data, isWriteProtected, SectorSkew.ProDos); - } - - return null; - } - - public void SaveState(BinaryWriter writer) - { - if (writer == null) - { - throw new ArgumentNullException("writer"); - } - - writer.Write(Name); - writer.Write(Data.Length); - writer.Write(Data); - writer.Write(IsWriteProtected); - } - - public abstract void ReadTrack(int number, int fraction, byte[] buffer); - public abstract void WriteTrack(int number, int fraction, byte[] buffer); - - public string Name { get; private set; } - [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] - public byte[] Data { get; protected set; } - public bool IsWriteProtected { get; private set; } - - public const int SectorCount = 16; - public const int SectorSize = 0x100; - public const int TrackCount = 35; - public const int TrackSize = 0x1A00; - } -} +using System; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Text.RegularExpressions; +using Jellyfish.Library; + +namespace Jellyfish.Virtu +{ + public abstract class Disk525 + { + protected Disk525(string name, byte[] data, bool isWriteProtected) + { + Name = name; + Data = data; + IsWriteProtected = isWriteProtected; + } + + public static Disk525 CreateDisk(string name, Stream stream, bool isWriteProtected) + { + if (name == null) + { + throw new ArgumentNullException("name"); + } + + if (name.EndsWith(".do", StringComparison.OrdinalIgnoreCase) || + name.EndsWith(".dsk", StringComparison.OrdinalIgnoreCase)) // assumes dos sector skew + { + return new DiskDsk(name, stream, isWriteProtected, SectorSkew.Dos); + } + else if (name.EndsWith(".nib", StringComparison.OrdinalIgnoreCase)) + { + return new DiskNib(name, stream, isWriteProtected); + } + else if (name.EndsWith(".po", StringComparison.OrdinalIgnoreCase)) + { + return new DiskDsk(name, stream, isWriteProtected, SectorSkew.ProDos); + } + + 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(); + var data = reader.ReadBytes(reader.ReadInt32()); + bool isWriteProtected = reader.ReadBoolean(); + + if (name.EndsWith(".do", StringComparison.OrdinalIgnoreCase) || + name.EndsWith(".dsk", StringComparison.OrdinalIgnoreCase)) // assumes dos sector skew + { + return new DiskDsk(name, data, isWriteProtected, SectorSkew.Dos); + } + else if (name.EndsWith(".nib", StringComparison.OrdinalIgnoreCase)) + { + return new DiskNib(name, data, isWriteProtected); + } + else if (name.EndsWith(".po", StringComparison.OrdinalIgnoreCase)) + { + return new DiskDsk(name, data, isWriteProtected, SectorSkew.ProDos); + } + + return null; + } + + public void SaveState(BinaryWriter writer) + { + if (writer == null) + { + throw new ArgumentNullException("writer"); + } + + writer.Write(Name); + writer.Write(Data.Length); + writer.Write(Data); + writer.Write(IsWriteProtected); + } + + public abstract void ReadTrack(int number, int fraction, byte[] buffer); + public abstract void WriteTrack(int number, int fraction, byte[] buffer); + + public string Name { get; private set; } + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public byte[] Data { get; protected set; } + public bool IsWriteProtected { get; private set; } + + public const int SectorCount = 16; + public const int SectorSize = 0x100; + public const int TrackCount = 35; + public const int TrackSize = 0x1A00; + } +} diff --git a/Virtu/DiskDsk.cs b/Virtu/DiskDsk.cs index 90cc81a..6ebc967 100644 --- a/Virtu/DiskDsk.cs +++ b/Virtu/DiskDsk.cs @@ -1,324 +1,324 @@ -using System; -using System.IO; -using Jellyfish.Library; - -namespace Jellyfish.Virtu -{ - public enum SectorSkew { None = 0, Dos, ProDos }; - - public sealed class DiskDsk : Disk525 - { - public DiskDsk(string name, byte[] data, bool isWriteProtected, SectorSkew sectorSkew) : - base(name, data, isWriteProtected) - { - _sectorSkew = SectorSkewMode[(int)sectorSkew]; - } - - public DiskDsk(string name, Stream stream, bool isWriteProtected, SectorSkew sectorSkew) : - base(name, new byte[TrackCount * SectorCount * SectorSize], isWriteProtected) - { - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - - stream.ReadBlock(Data); - _sectorSkew = SectorSkewMode[(int)sectorSkew]; - } - - public override void ReadTrack(int number, int fraction, byte[] buffer) - { - int track = number / 2; - - _trackBuffer = buffer; - _trackOffset = 0; - - WriteNibble(0xFF, 48); // gap 0 - - for (int sector = 0; sector < SectorCount; sector++) - { - WriteNibble(0xD5); // address prologue - WriteNibble(0xAA); - WriteNibble(0x96); - - WriteNibble44(Volume); - WriteNibble44(track); - WriteNibble44(sector); - WriteNibble44(Volume ^ track ^ sector); - - WriteNibble(0xDE); // address epilogue - WriteNibble(0xAA); - WriteNibble(0xEB); - WriteNibble(0xFF, 8); - - WriteNibble(0xD5); // data prologue - WriteNibble(0xAA); - WriteNibble(0xAD); - - WriteDataNibbles((track * SectorCount + _sectorSkew[sector]) * SectorSize); - - WriteNibble(0xDE); // data epilogue - WriteNibble(0xAA); - WriteNibble(0xEB); - WriteNibble(0xFF, 16); - } - } - - public override void WriteTrack(int number, int fraction, byte[] buffer) - { - if (IsWriteProtected) - return; - - int track = number / 2; - - _trackBuffer = buffer; - _trackOffset = 0; - int sectorsDone = 0; - - for (int sector = 0; sector < SectorCount; sector++) - { - if (!Read3Nibbles(0xD5, 0xAA, 0x96, 0x304)) - break; // no address prologue - - /*int readVolume = */ReadNibble44(); - - int readTrack = ReadNibble44(); - if (readTrack != track) - break; // bad track number - - int readSector = ReadNibble44(); - if (readSector > SectorCount) - break; // bad sector number - if ((sectorsDone & (0x1 << readSector)) != 0) - break; // already done this sector - - if (ReadNibble44() != (Volume ^ readTrack ^ readSector)) - break; // bad address checksum - - if ((ReadNibble() != 0xDE) || (ReadNibble() != 0xAA)) - break; // bad address epilogue - - if (!Read3Nibbles(0xD5, 0xAA, 0xAD, 0x20)) - break; // no data prologue - - if (!ReadDataNibbles((track * SectorCount + _sectorSkew[sector]) * SectorSize)) - break; // bad data checksum - - if ((ReadNibble() != 0xDE) || (ReadNibble() != 0xAA)) - break; // bad data epilogue - - sectorsDone |= 0x1 << sector; - } - - if (sectorsDone != 0xFFFF) - throw new InvalidOperationException("disk error"); // TODO: we should alert the user and "dump" a NIB - } - - private byte ReadNibble() - { - byte data = _trackBuffer[_trackOffset]; - if (_trackOffset++ == TrackSize) - { - _trackOffset = 0; - } - return data; - } - - private bool Read3Nibbles(byte data1, byte data2, byte data3, int maxReads) - { - bool result = false; - while (--maxReads > 0) - { - if (ReadNibble() != data1) - continue; - - if (ReadNibble() != data2) - continue; - - if (ReadNibble() != data3) - continue; - - result = true; - break; - } - return result; - } - - private int ReadNibble44() - { - return (((ReadNibble() << 1) | 0x1) & ReadNibble()); - } - - private byte ReadTranslatedNibble() - { - byte data = NibbleToByte[ReadNibble()]; - // TODO: check that invalid nibbles aren't used - // (put 0xFFs for invalid nibbles in the table) - //if (data == 0xFF) - //{ - //throw an exception - //} - return data; - } - - private bool ReadDataNibbles(int sectorOffset) - { - byte a, x, y; - - y = SecondaryBufferLength; - a = 0; - do // fill and de-nibblize secondary buffer - { - a = _secondaryBuffer[--y] = (byte)(a ^ ReadTranslatedNibble()); - } - while (y > 0); - - do // fill and de-nibblize secondary buffer - { - a = _primaryBuffer[y++] = (byte)(a ^ ReadTranslatedNibble()); - } - while (y != 0); - - int checksum = a ^ ReadTranslatedNibble(); // should be 0 - - x = y = 0; - do // decode data - { - if (x == 0) - { - x = SecondaryBufferLength; - } - a = (byte)((_primaryBuffer[y] << 2) | SwapBits[_secondaryBuffer[--x] & 0x03]); - _secondaryBuffer[x] >>= 2; - Data[sectorOffset + y] = a; - } - while (++y != 0); - - return (checksum == 0); - } - - private void WriteNibble(int data) - { - _trackBuffer[_trackOffset++] = (byte)data; - } - - private void WriteNibble(int data, int count) - { - while (count-- > 0) - { - WriteNibble(data); - } - } - - private void WriteNibble44(int data) - { - WriteNibble((data >> 1) | 0xAA); - WriteNibble(data | 0xAA); - } - - private void WriteDataNibbles(int sectorOffset) - { - byte a, x, y; - - for (x = 0; x < SecondaryBufferLength; x++) - { - _secondaryBuffer[x] = 0; // zero secondary buffer - } - - y = 2; - do // fill buffers - { - x = 0; - do - { - a = Data[sectorOffset + --y]; - _secondaryBuffer[x] = (byte)((_secondaryBuffer[x] << 2) | SwapBits[a & 0x03]); // b1,b0 -> secondary buffer - _primaryBuffer[y] = (byte)(a >> 2); // b7-b2 -> primary buffer - } - while (++x < SecondaryBufferLength); - } - while (y != 0); - - y = SecondaryBufferLength; - do // write secondary buffer - { - WriteNibble(ByteToNibble[_secondaryBuffer[y] ^ _secondaryBuffer[y - 1]]); - } - while (--y != 0); - - a = _secondaryBuffer[0]; - do // write primary buffer - { - WriteNibble(ByteToNibble[a ^ _primaryBuffer[y]]); - a = _primaryBuffer[y]; - } - while (++y != 0); - - WriteNibble(ByteToNibble[a]); // data checksum - } - - private byte[] _trackBuffer; - private int _trackOffset; - private byte[] _primaryBuffer = new byte[0x100]; - private const int SecondaryBufferLength = 0x56; - private byte[] _secondaryBuffer = new byte[SecondaryBufferLength + 1]; - private int[] _sectorSkew; - private const int Volume = 0xFE; - - private static readonly byte[] SwapBits = { 0, 2, 1, 3 }; - - private static readonly int[] SectorSkewNone = new int[SectorCount] - { - 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF - }; - - private static readonly int[] SectorSkewDos = new int[SectorCount] - { - 0x0, 0x7, 0xE, 0x6, 0xD, 0x5, 0xC, 0x4, 0xB, 0x3, 0xA, 0x2, 0x9, 0x1, 0x8, 0xF - }; - - private static readonly int[] SectorSkewProDos = new int[SectorCount] - { - 0x0, 0x8, 0x1, 0x9, 0x2, 0xA, 0x3, 0xB, 0x4, 0xC, 0x5, 0xD, 0x6, 0xE, 0x7, 0xF - }; - - private const int SectorSkewCount = 3; - - private static readonly int[][] SectorSkewMode = new int[SectorSkewCount][] - { - SectorSkewNone, SectorSkewDos, SectorSkewProDos - }; - - private static readonly byte[] ByteToNibble = new byte[] - { - 0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6, 0xA7, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB2, 0xB3, - 0xB4, 0xB5, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xCB, 0xCD, 0xCE, 0xCF, 0xD3, - 0xD6, 0xD7, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE5, 0xE6, 0xE7, 0xE9, 0xEA, 0xEB, 0xEC, - 0xED, 0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF - }; - - private static readonly byte[] NibbleToByte = new byte[] - { - // padding for offset (not used) - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, - - // nibble translate table - 0x00, 0x01, 0x98, 0x99, 0x02, 0x03, 0x9C, 0x04, 0x05, 0x06, - 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x07, 0x08, 0xA8, 0xA9, 0xAA, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, - 0xB0, 0xB1, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0xB8, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, - 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0x1B, 0xCC, 0x1C, 0x1D, 0x1E, - 0xD0, 0xD1, 0xD2, 0x1F, 0xD4, 0xD5, 0x20, 0x21, 0xD8, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0x29, 0x2A, 0x2B, 0xE8, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, - 0xF0, 0xF1, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0xF8, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F - }; - } -} +using System; +using System.IO; +using Jellyfish.Library; + +namespace Jellyfish.Virtu +{ + public enum SectorSkew { None = 0, Dos, ProDos }; + + public sealed class DiskDsk : Disk525 + { + public DiskDsk(string name, byte[] data, bool isWriteProtected, SectorSkew sectorSkew) : + base(name, data, isWriteProtected) + { + _sectorSkew = SectorSkewMode[(int)sectorSkew]; + } + + public DiskDsk(string name, Stream stream, bool isWriteProtected, SectorSkew sectorSkew) : + base(name, new byte[TrackCount * SectorCount * SectorSize], isWriteProtected) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + + stream.ReadBlock(Data); + _sectorSkew = SectorSkewMode[(int)sectorSkew]; + } + + public override void ReadTrack(int number, int fraction, byte[] buffer) + { + int track = number / 2; + + _trackBuffer = buffer; + _trackOffset = 0; + + WriteNibble(0xFF, 48); // gap 0 + + for (int sector = 0; sector < SectorCount; sector++) + { + WriteNibble(0xD5); // address prologue + WriteNibble(0xAA); + WriteNibble(0x96); + + WriteNibble44(Volume); + WriteNibble44(track); + WriteNibble44(sector); + WriteNibble44(Volume ^ track ^ sector); + + WriteNibble(0xDE); // address epilogue + WriteNibble(0xAA); + WriteNibble(0xEB); + WriteNibble(0xFF, 8); + + WriteNibble(0xD5); // data prologue + WriteNibble(0xAA); + WriteNibble(0xAD); + + WriteDataNibbles((track * SectorCount + _sectorSkew[sector]) * SectorSize); + + WriteNibble(0xDE); // data epilogue + WriteNibble(0xAA); + WriteNibble(0xEB); + WriteNibble(0xFF, 16); + } + } + + public override void WriteTrack(int number, int fraction, byte[] buffer) + { + if (IsWriteProtected) + return; + + int track = number / 2; + + _trackBuffer = buffer; + _trackOffset = 0; + int sectorsDone = 0; + + for (int sector = 0; sector < SectorCount; sector++) + { + if (!Read3Nibbles(0xD5, 0xAA, 0x96, 0x304)) + break; // no address prologue + + /*int readVolume = */ReadNibble44(); + + int readTrack = ReadNibble44(); + if (readTrack != track) + break; // bad track number + + int readSector = ReadNibble44(); + if (readSector > SectorCount) + break; // bad sector number + if ((sectorsDone & (0x1 << readSector)) != 0) + break; // already done this sector + + if (ReadNibble44() != (Volume ^ readTrack ^ readSector)) + break; // bad address checksum + + if ((ReadNibble() != 0xDE) || (ReadNibble() != 0xAA)) + break; // bad address epilogue + + if (!Read3Nibbles(0xD5, 0xAA, 0xAD, 0x20)) + break; // no data prologue + + if (!ReadDataNibbles((track * SectorCount + _sectorSkew[sector]) * SectorSize)) + break; // bad data checksum + + if ((ReadNibble() != 0xDE) || (ReadNibble() != 0xAA)) + break; // bad data epilogue + + sectorsDone |= 0x1 << sector; + } + + if (sectorsDone != 0xFFFF) + throw new InvalidOperationException("disk error"); // TODO: we should alert the user and "dump" a NIB + } + + private byte ReadNibble() + { + byte data = _trackBuffer[_trackOffset]; + if (_trackOffset++ == TrackSize) + { + _trackOffset = 0; + } + return data; + } + + private bool Read3Nibbles(byte data1, byte data2, byte data3, int maxReads) + { + bool result = false; + while (--maxReads > 0) + { + if (ReadNibble() != data1) + continue; + + if (ReadNibble() != data2) + continue; + + if (ReadNibble() != data3) + continue; + + result = true; + break; + } + return result; + } + + private int ReadNibble44() + { + return (((ReadNibble() << 1) | 0x1) & ReadNibble()); + } + + private byte ReadTranslatedNibble() + { + byte data = NibbleToByte[ReadNibble()]; + // TODO: check that invalid nibbles aren't used + // (put 0xFFs for invalid nibbles in the table) + //if (data == 0xFF) + //{ + //throw an exception + //} + return data; + } + + private bool ReadDataNibbles(int sectorOffset) + { + byte a, x, y; + + y = SecondaryBufferLength; + a = 0; + do // fill and de-nibblize secondary buffer + { + a = _secondaryBuffer[--y] = (byte)(a ^ ReadTranslatedNibble()); + } + while (y > 0); + + do // fill and de-nibblize secondary buffer + { + a = _primaryBuffer[y++] = (byte)(a ^ ReadTranslatedNibble()); + } + while (y != 0); + + int checksum = a ^ ReadTranslatedNibble(); // should be 0 + + x = y = 0; + do // decode data + { + if (x == 0) + { + x = SecondaryBufferLength; + } + a = (byte)((_primaryBuffer[y] << 2) | SwapBits[_secondaryBuffer[--x] & 0x03]); + _secondaryBuffer[x] >>= 2; + Data[sectorOffset + y] = a; + } + while (++y != 0); + + return (checksum == 0); + } + + private void WriteNibble(int data) + { + _trackBuffer[_trackOffset++] = (byte)data; + } + + private void WriteNibble(int data, int count) + { + while (count-- > 0) + { + WriteNibble(data); + } + } + + private void WriteNibble44(int data) + { + WriteNibble((data >> 1) | 0xAA); + WriteNibble(data | 0xAA); + } + + private void WriteDataNibbles(int sectorOffset) + { + byte a, x, y; + + for (x = 0; x < SecondaryBufferLength; x++) + { + _secondaryBuffer[x] = 0; // zero secondary buffer + } + + y = 2; + do // fill buffers + { + x = 0; + do + { + a = Data[sectorOffset + --y]; + _secondaryBuffer[x] = (byte)((_secondaryBuffer[x] << 2) | SwapBits[a & 0x03]); // b1,b0 -> secondary buffer + _primaryBuffer[y] = (byte)(a >> 2); // b7-b2 -> primary buffer + } + while (++x < SecondaryBufferLength); + } + while (y != 0); + + y = SecondaryBufferLength; + do // write secondary buffer + { + WriteNibble(ByteToNibble[_secondaryBuffer[y] ^ _secondaryBuffer[y - 1]]); + } + while (--y != 0); + + a = _secondaryBuffer[0]; + do // write primary buffer + { + WriteNibble(ByteToNibble[a ^ _primaryBuffer[y]]); + a = _primaryBuffer[y]; + } + while (++y != 0); + + WriteNibble(ByteToNibble[a]); // data checksum + } + + private byte[] _trackBuffer; + private int _trackOffset; + private byte[] _primaryBuffer = new byte[0x100]; + private const int SecondaryBufferLength = 0x56; + private byte[] _secondaryBuffer = new byte[SecondaryBufferLength + 1]; + private int[] _sectorSkew; + private const int Volume = 0xFE; + + private static readonly byte[] SwapBits = { 0, 2, 1, 3 }; + + private static readonly int[] SectorSkewNone = new int[SectorCount] + { + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF + }; + + private static readonly int[] SectorSkewDos = new int[SectorCount] + { + 0x0, 0x7, 0xE, 0x6, 0xD, 0x5, 0xC, 0x4, 0xB, 0x3, 0xA, 0x2, 0x9, 0x1, 0x8, 0xF + }; + + private static readonly int[] SectorSkewProDos = new int[SectorCount] + { + 0x0, 0x8, 0x1, 0x9, 0x2, 0xA, 0x3, 0xB, 0x4, 0xC, 0x5, 0xD, 0x6, 0xE, 0x7, 0xF + }; + + private const int SectorSkewCount = 3; + + private static readonly int[][] SectorSkewMode = new int[SectorSkewCount][] + { + SectorSkewNone, SectorSkewDos, SectorSkewProDos + }; + + private static readonly byte[] ByteToNibble = new byte[] + { + 0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6, 0xA7, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xCB, 0xCD, 0xCE, 0xCF, 0xD3, + 0xD6, 0xD7, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE5, 0xE6, 0xE7, 0xE9, 0xEA, 0xEB, 0xEC, + 0xED, 0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF + }; + + private static readonly byte[] NibbleToByte = new byte[] + { + // padding for offset (not used) + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, + + // nibble translate table + 0x00, 0x01, 0x98, 0x99, 0x02, 0x03, 0x9C, 0x04, 0x05, 0x06, + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x07, 0x08, 0xA8, 0xA9, 0xAA, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0xB0, 0xB1, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0xB8, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0x1B, 0xCC, 0x1C, 0x1D, 0x1E, + 0xD0, 0xD1, 0xD2, 0x1F, 0xD4, 0xD5, 0x20, 0x21, 0xD8, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0x29, 0x2A, 0x2B, 0xE8, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, + 0xF0, 0xF1, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0xF8, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F + }; + } +} diff --git a/Virtu/DiskIIController.cs b/Virtu/DiskIIController.cs index d082a11..e81637e 100644 --- a/Virtu/DiskIIController.cs +++ b/Virtu/DiskIIController.cs @@ -1,287 +1,287 @@ -using System; -using System.Collections.ObjectModel; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using Jellyfish.Library; -using Jellyfish.Virtu.Services; - -namespace Jellyfish.Virtu -{ - 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() - { - StorageService.LoadResource("Roms/DiskII.rom", stream => stream.ReadBlock(_romRegionC1C7)); - } - - public override void Reset() - { - _phaseStates = 0; - SetMotorOn(false); - SetDriveNumber(0); - _loadMode = false; - _writeMode = false; - } - - public override void LoadState(BinaryReader reader, Version version) - { - 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(); - 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) - { - 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); - 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")] - public override int ReadIoRegionC0C0(int address) - { - switch (address & 0xF) - { - case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7: - SetPhase(address); - break; - - case 0x8: - SetMotorOn(false); - break; - - case 0x9: - SetMotorOn(true); - break; - - case 0xA: - SetDriveNumber(0); - break; - - case 0xB: - SetDriveNumber(1); - break; - - case 0xC: - _loadMode = false; - if (_motorOn) - { - if (!_writeMode) - { - return _latch = Drives[_driveNumber].Read(); - } - else - { - WriteLatch(); - } - } - break; - - case 0xD: - _loadMode = true; - if (_motorOn && !_writeMode) - { - // write protect is forced if phase 1 is on [F9.7] - _latch &= 0x7F; - if (Drives[_driveNumber].IsWriteProtected || - (_phaseStates & Phase1On) != 0) - { - _latch |= 0x80; - } - } - break; - - case 0xE: - _writeMode = false; - break; - - case 0xF: - _writeMode = true; - break; - } - - if ((address & 1) == 0) - { - // only even addresses return the latch - if (_motorOn) - { - return _latch; - } - - // simple hack to fool DOS SAMESLOT drive spin check (usually at $BD34) - _driveSpin = !_driveSpin; - return _driveSpin ? 0x7E : 0x7F; - } - - return ReadFloatingBus(); - } - - public override int ReadIoRegionC1C7(int address) - { - return _romRegionC1C7[address & 0xFF]; - } - - public override void WriteIoRegionC0C0(int address, int data) - { - switch (address & 0xF) - { - case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7: - SetPhase(address); - break; - - case 0x8: - SetMotorOn(false); - break; - - case 0x9: - SetMotorOn(true); - break; - - case 0xA: - SetDriveNumber(0); - break; - - case 0xB: - SetDriveNumber(1); - break; - - case 0xC: - _loadMode = false; - if (_writeMode) - { - WriteLatch(); - } - break; - - case 0xD: - _loadMode = true; - break; - - case 0xE: - _writeMode = false; - break; - - case 0xF: - _writeMode = true; - break; - } - - if (_motorOn && _writeMode) - { - if (_loadMode) - { - // any address writes latch for sequencer LD; OE1/2 irrelevant ['323 datasheet] - _latch = data; - } - } - } - - private void WriteLatch() - { - // write protect is forced if phase 1 is on [F9.7] - if ((_phaseStates & Phase1On) == 0) - { - Drives[_driveNumber].Write(_latch); - } - } - - private void Flush() - { - Drives[_driveNumber].FlushTrack(); - } - - private void SetDriveNumber(int driveNumber) - { - if (_driveNumber != driveNumber) - { - Flush(); - _driveNumber = driveNumber; - } - } - - private void SetMotorOn(bool state) - { - if (_motorOn && !state) - { - Flush(); - } - _motorOn = state; - } - - private void SetPhase(int address) - { - int phase = (address >> 1) & 0x3; - int state = address & 1; - _phaseStates &= ~(1 << phase); - _phaseStates |= (state << phase); - - if (_motorOn) - { - Drives[_driveNumber].ApplyPhaseChange(_phaseStates); - } - } - - 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 int _latch; - private int _phaseStates; - private bool _motorOn; - private int _driveNumber; - private bool _loadMode; - private bool _writeMode; - private bool _driveSpin; - - private byte[] _romRegionC1C7 = new byte[0x0100]; - } -} +using System; +using System.Collections.ObjectModel; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using Jellyfish.Library; +using Jellyfish.Virtu.Services; + +namespace Jellyfish.Virtu +{ + 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() + { + StorageService.LoadResource("Roms/DiskII.rom", stream => stream.ReadBlock(_romRegionC1C7)); + } + + public override void Reset() + { + _phaseStates = 0; + SetMotorOn(false); + SetDriveNumber(0); + _loadMode = false; + _writeMode = false; + } + + public override void LoadState(BinaryReader reader, Version version) + { + 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(); + 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) + { + 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); + 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")] + public override int ReadIoRegionC0C0(int address) + { + switch (address & 0xF) + { + case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7: + SetPhase(address); + break; + + case 0x8: + SetMotorOn(false); + break; + + case 0x9: + SetMotorOn(true); + break; + + case 0xA: + SetDriveNumber(0); + break; + + case 0xB: + SetDriveNumber(1); + break; + + case 0xC: + _loadMode = false; + if (_motorOn) + { + if (!_writeMode) + { + return _latch = Drives[_driveNumber].Read(); + } + else + { + WriteLatch(); + } + } + break; + + case 0xD: + _loadMode = true; + if (_motorOn && !_writeMode) + { + // write protect is forced if phase 1 is on [F9.7] + _latch &= 0x7F; + if (Drives[_driveNumber].IsWriteProtected || + (_phaseStates & Phase1On) != 0) + { + _latch |= 0x80; + } + } + break; + + case 0xE: + _writeMode = false; + break; + + case 0xF: + _writeMode = true; + break; + } + + if ((address & 1) == 0) + { + // only even addresses return the latch + if (_motorOn) + { + return _latch; + } + + // simple hack to fool DOS SAMESLOT drive spin check (usually at $BD34) + _driveSpin = !_driveSpin; + return _driveSpin ? 0x7E : 0x7F; + } + + return ReadFloatingBus(); + } + + public override int ReadIoRegionC1C7(int address) + { + return _romRegionC1C7[address & 0xFF]; + } + + public override void WriteIoRegionC0C0(int address, int data) + { + switch (address & 0xF) + { + case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7: + SetPhase(address); + break; + + case 0x8: + SetMotorOn(false); + break; + + case 0x9: + SetMotorOn(true); + break; + + case 0xA: + SetDriveNumber(0); + break; + + case 0xB: + SetDriveNumber(1); + break; + + case 0xC: + _loadMode = false; + if (_writeMode) + { + WriteLatch(); + } + break; + + case 0xD: + _loadMode = true; + break; + + case 0xE: + _writeMode = false; + break; + + case 0xF: + _writeMode = true; + break; + } + + if (_motorOn && _writeMode) + { + if (_loadMode) + { + // any address writes latch for sequencer LD; OE1/2 irrelevant ['323 datasheet] + _latch = data; + } + } + } + + private void WriteLatch() + { + // write protect is forced if phase 1 is on [F9.7] + if ((_phaseStates & Phase1On) == 0) + { + Drives[_driveNumber].Write(_latch); + } + } + + private void Flush() + { + Drives[_driveNumber].FlushTrack(); + } + + private void SetDriveNumber(int driveNumber) + { + if (_driveNumber != driveNumber) + { + Flush(); + _driveNumber = driveNumber; + } + } + + private void SetMotorOn(bool state) + { + if (_motorOn && !state) + { + Flush(); + } + _motorOn = state; + } + + private void SetPhase(int address) + { + int phase = (address >> 1) & 0x3; + int state = address & 1; + _phaseStates &= ~(1 << phase); + _phaseStates |= (state << phase); + + if (_motorOn) + { + Drives[_driveNumber].ApplyPhaseChange(_phaseStates); + } + } + + 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 int _latch; + private int _phaseStates; + private bool _motorOn; + private int _driveNumber; + private bool _loadMode; + private bool _writeMode; + private bool _driveSpin; + + private byte[] _romRegionC1C7 = new byte[0x0100]; + } +} diff --git a/Virtu/DiskIIDrive.cs b/Virtu/DiskIIDrive.cs index c59c2cf..a01e676 100644 --- a/Virtu/DiskIIDrive.cs +++ b/Virtu/DiskIIDrive.cs @@ -1,172 +1,172 @@ -using System; -using System.IO; -using Jellyfish.Library; -using Jellyfish.Virtu.Services; - -namespace Jellyfish.Virtu -{ - public sealed class DiskIIDrive : MachineComponent - { - 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 - DriveArmStepDelta[2] = new int[] { 0, 0, -1, -1, 0, 0, -1, -1, 1, 1, 0, 0, 1, 1, 0, 0 }; // phase 2 - DriveArmStepDelta[3] = new int[] { 0, 1, 0, 1, -1, 0, -1, 0, 0, 1, 0, 1, -1, 0, -1, 0 }; // phase 3 - } - - public override 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); - } - if (reader.ReadBoolean()) - { - DebugService.WriteMessage("Loading machine '{0}'", typeof(Disk525).Name); - _disk = Disk525.LoadState(reader, version); - } - else - { - _disk = null; - } - } - - public override 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) - { - 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; - } - - public void RemoveDisk() - { - 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) - { - // step the drive head according to stepper magnet changes - int delta = DriveArmStepDelta[_trackNumber & 0x3][phaseState]; - if (delta != 0) - { - int newTrackNumber = MathHelpers.Clamp(_trackNumber + delta, 0, TrackNumberMax); - if (newTrackNumber != _trackNumber) - { - FlushTrack(); - _trackNumber = newTrackNumber; - _trackOffset = 0; - _trackLoaded = false; - } - } - } - - public int Read() - { - if (LoadTrack()) - { - int data = _trackData[_trackOffset++]; - if (_trackOffset >= Disk525.TrackSize) - { - _trackOffset = 0; - } - - return data; - } - - return _random.Next(0x01, 0xFF); - } - - public void Write(int data) - { - if (LoadTrack()) - { - _trackChanged = true; - _trackData[_trackOffset++] = (byte)data; - if (_trackOffset >= Disk525.TrackSize) - { - _trackOffset = 0; - } - } - } - - private bool LoadTrack() - { - if (!_trackLoaded && (_disk != null)) - { - _disk.ReadTrack(_trackNumber, 0, _trackData); - _trackLoaded = true; - } - - return _trackLoaded; - } - - public void FlushTrack() - { - if (_trackChanged) - { - _disk.WriteTrack(_trackNumber, 0, _trackData); - _trackChanged = false; - } - } - - public bool IsWriteProtected { get { return _disk.IsWriteProtected; } } - - private const int TrackNumberMax = 0x44; - - private const int PhaseCount = 4; - - private readonly int[][] DriveArmStepDelta = new int[PhaseCount][]; - - private bool _trackLoaded; - private bool _trackChanged; - private int _trackNumber; - private int _trackOffset; - private byte[] _trackData = new byte[Disk525.TrackSize]; - private Disk525 _disk; - - private Random _random = new Random(); - } -} +using System; +using System.IO; +using Jellyfish.Library; +using Jellyfish.Virtu.Services; + +namespace Jellyfish.Virtu +{ + public sealed class DiskIIDrive : MachineComponent + { + 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 + DriveArmStepDelta[2] = new int[] { 0, 0, -1, -1, 0, 0, -1, -1, 1, 1, 0, 0, 1, 1, 0, 0 }; // phase 2 + DriveArmStepDelta[3] = new int[] { 0, 1, 0, 1, -1, 0, -1, 0, 0, 1, 0, 1, -1, 0, -1, 0 }; // phase 3 + } + + public override 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); + } + if (reader.ReadBoolean()) + { + DebugService.WriteMessage("Loading machine '{0}'", typeof(Disk525).Name); + _disk = Disk525.LoadState(reader, version); + } + else + { + _disk = null; + } + } + + public override 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) + { + 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; + } + + public void RemoveDisk() + { + 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) + { + // step the drive head according to stepper magnet changes + int delta = DriveArmStepDelta[_trackNumber & 0x3][phaseState]; + if (delta != 0) + { + int newTrackNumber = MathHelpers.Clamp(_trackNumber + delta, 0, TrackNumberMax); + if (newTrackNumber != _trackNumber) + { + FlushTrack(); + _trackNumber = newTrackNumber; + _trackOffset = 0; + _trackLoaded = false; + } + } + } + + public int Read() + { + if (LoadTrack()) + { + int data = _trackData[_trackOffset++]; + if (_trackOffset >= Disk525.TrackSize) + { + _trackOffset = 0; + } + + return data; + } + + return _random.Next(0x01, 0xFF); + } + + public void Write(int data) + { + if (LoadTrack()) + { + _trackChanged = true; + _trackData[_trackOffset++] = (byte)data; + if (_trackOffset >= Disk525.TrackSize) + { + _trackOffset = 0; + } + } + } + + private bool LoadTrack() + { + if (!_trackLoaded && (_disk != null)) + { + _disk.ReadTrack(_trackNumber, 0, _trackData); + _trackLoaded = true; + } + + return _trackLoaded; + } + + public void FlushTrack() + { + if (_trackChanged) + { + _disk.WriteTrack(_trackNumber, 0, _trackData); + _trackChanged = false; + } + } + + public bool IsWriteProtected { get { return _disk.IsWriteProtected; } } + + private const int TrackNumberMax = 0x44; + + private const int PhaseCount = 4; + + private readonly int[][] DriveArmStepDelta = new int[PhaseCount][]; + + private bool _trackLoaded; + private bool _trackChanged; + private int _trackNumber; + private int _trackOffset; + private byte[] _trackData = new byte[Disk525.TrackSize]; + private Disk525 _disk; + + private Random _random = new Random(); + } +} diff --git a/Virtu/DiskNib.cs b/Virtu/DiskNib.cs index e186e00..68d0a5f 100644 --- a/Virtu/DiskNib.cs +++ b/Virtu/DiskNib.cs @@ -1,35 +1,35 @@ -using System; -using System.IO; -using Jellyfish.Library; - -namespace Jellyfish.Virtu -{ - public sealed class DiskNib : Disk525 - { - public DiskNib(string name, byte[] data, bool isWriteProtected) : - base(name, data, isWriteProtected) - { - } - - public DiskNib(string name, Stream stream, bool isWriteProtected) : - base(name, new byte[TrackCount * TrackSize], isWriteProtected) - { - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - - stream.ReadBlock(Data); - } - - public override void ReadTrack(int number, int fraction, byte[] buffer) - { - Buffer.BlockCopy(Data, (number / 2) * TrackSize, buffer, 0, TrackSize); - } - - public override void WriteTrack(int number, int fraction, byte[] buffer) - { - Buffer.BlockCopy(buffer, 0, Data, (number / 2) * TrackSize, TrackSize); - } - } -} +using System; +using System.IO; +using Jellyfish.Library; + +namespace Jellyfish.Virtu +{ + public sealed class DiskNib : Disk525 + { + public DiskNib(string name, byte[] data, bool isWriteProtected) : + base(name, data, isWriteProtected) + { + } + + public DiskNib(string name, Stream stream, bool isWriteProtected) : + base(name, new byte[TrackCount * TrackSize], isWriteProtected) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + + stream.ReadBlock(Data); + } + + public override void ReadTrack(int number, int fraction, byte[] buffer) + { + Buffer.BlockCopy(Data, (number / 2) * TrackSize, buffer, 0, TrackSize); + } + + public override void WriteTrack(int number, int fraction, byte[] buffer) + { + Buffer.BlockCopy(buffer, 0, Data, (number / 2) * TrackSize, TrackSize); + } + } +} diff --git a/Virtu/GamePort.cs b/Virtu/GamePort.cs index 1c5320e..fff1dd3 100644 --- a/Virtu/GamePort.cs +++ b/Virtu/GamePort.cs @@ -1,370 +1,370 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using Jellyfish.Library; -using Jellyfish.Virtu.Services; - -namespace Jellyfish.Virtu -{ - public sealed class GamePort : MachineComponent - { - public GamePort(Machine machine) : - base(machine) - { - _resetPaddle0StrobeEvent = ResetPaddle0StrobeEvent; // cache delegates; avoids garbage - _resetPaddle1StrobeEvent = ResetPaddle1StrobeEvent; - _resetPaddle2StrobeEvent = ResetPaddle2StrobeEvent; - _resetPaddle3StrobeEvent = ResetPaddle3StrobeEvent; - } - - public override void Initialize() - { - _keyboardService = Machine.Services.GetService(); - _gamePortService = Machine.Services.GetService(); - - JoystickDeadZone = 0.4f; - - InvertPaddles = true; // Raster Blaster - SwapPaddles = true; - Joystick0TouchX = 0.35f; - Joystick0TouchY = 0.6f; - Joystick0TouchWidth = 0.25f; - Joystick0TouchHeight = 0.4f; - Joystick0TouchRadius = 0.2f; - Joystick0TouchKeepLast = true; - Button0TouchX = 0; - Button0TouchY = 0; - Button0TouchWidth = 0.5f; - Button0TouchHeight = 1; - Button1TouchX = 0.5f; - Button1TouchY = 0; - Button1TouchWidth = 0.5f; - Button1TouchHeight = 1; - Button2TouchX = 0.75f; - Button2TouchY = 0; - Button2TouchWidth = 0.25f; - Button2TouchHeight = 0.25f; - Button2TouchOrder = 1; - } - - public override void LoadState(BinaryReader reader, Version version) - { - if (reader == null) - { - throw new ArgumentNullException("reader"); - } - - InvertPaddles = reader.ReadBoolean(); - SwapPaddles = reader.ReadBoolean(); - UseShiftKeyMod = reader.ReadBoolean(); - JoystickDeadZone = reader.ReadSingle(); - - 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(); - - UseTouch = reader.ReadBoolean(); - Joystick0TouchX = reader.ReadSingle(); - Joystick0TouchY = reader.ReadSingle(); - Joystick0TouchWidth = reader.ReadSingle(); - Joystick0TouchHeight = reader.ReadSingle(); - Joystick0TouchOrder = reader.ReadInt32(); - Joystick0TouchRadius = reader.ReadSingle(); - Joystick0TouchKeepLast = reader.ReadBoolean(); - Joystick1TouchX = reader.ReadSingle(); - Joystick1TouchY = reader.ReadSingle(); - Joystick1TouchWidth = reader.ReadSingle(); - Joystick1TouchHeight = reader.ReadSingle(); - Joystick1TouchOrder = reader.ReadInt32(); - Joystick1TouchRadius = reader.ReadSingle(); - Joystick1TouchKeepLast = reader.ReadBoolean(); - Button0TouchX = reader.ReadSingle(); - Button0TouchY = reader.ReadSingle(); - Button0TouchWidth = reader.ReadSingle(); - Button0TouchHeight = reader.ReadSingle(); - Button0TouchOrder = reader.ReadInt32(); - Button1TouchX = reader.ReadSingle(); - Button1TouchY = reader.ReadSingle(); - Button1TouchWidth = reader.ReadSingle(); - Button1TouchHeight = reader.ReadSingle(); - Button1TouchOrder = reader.ReadInt32(); - Button2TouchX = reader.ReadSingle(); - Button2TouchY = reader.ReadSingle(); - Button2TouchWidth = reader.ReadSingle(); - Button2TouchHeight = reader.ReadSingle(); - Button2TouchOrder = reader.ReadInt32(); - } - - public override void SaveState(BinaryWriter writer) - { - if (writer == null) - { - throw new ArgumentNullException("writer"); - } - - writer.Write(InvertPaddles); - writer.Write(SwapPaddles); - writer.Write(UseShiftKeyMod); - 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); - - writer.Write(UseTouch); - writer.Write(Joystick0TouchX); - writer.Write(Joystick0TouchY); - writer.Write(Joystick0TouchWidth); - writer.Write(Joystick0TouchHeight); - writer.Write(Joystick0TouchOrder); - writer.Write(Joystick0TouchRadius); - writer.Write(Joystick0TouchKeepLast); - writer.Write(Joystick1TouchX); - writer.Write(Joystick1TouchY); - writer.Write(Joystick1TouchWidth); - writer.Write(Joystick1TouchHeight); - writer.Write(Joystick1TouchOrder); - writer.Write(Joystick1TouchRadius); - writer.Write(Joystick1TouchKeepLast); - writer.Write(Button0TouchX); - writer.Write(Button0TouchY); - writer.Write(Button0TouchWidth); - writer.Write(Button0TouchHeight); - writer.Write(Button0TouchOrder); - writer.Write(Button1TouchX); - writer.Write(Button1TouchY); - writer.Write(Button1TouchWidth); - writer.Write(Button1TouchHeight); - writer.Write(Button1TouchOrder); - writer.Write(Button2TouchX); - writer.Write(Button2TouchY); - writer.Write(Button2TouchWidth); - writer.Write(Button2TouchHeight); - writer.Write(Button2TouchOrder); - } - - public bool ReadButton0() - { - return (_gamePortService.IsButton0Down || _keyboardService.IsOpenAppleKeyDown || - (UseKeyboard && (Button0Key > 0) && _keyboardService.IsKeyDown(Button0Key))); - } - - public bool ReadButton1() - { - return (_gamePortService.IsButton1Down || _keyboardService.IsCloseAppleKeyDown || - (UseKeyboard && (Button1Key > 0) && _keyboardService.IsKeyDown(Button1Key))); - } - - public bool ReadButton2() - { - return (_gamePortService.IsButton2Down || (UseShiftKeyMod && !_keyboardService.IsShiftKeyDown) || // Shift' [TN9] - (UseKeyboard && (Button2Key > 0) && _keyboardService.IsKeyDown(Button2Key))); - } - - [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] - public void TriggerTimers() - { - int paddle0 = _gamePortService.Paddle0; - int paddle1 = _gamePortService.Paddle1; - int paddle2 = _gamePortService.Paddle2; - int paddle3 = _gamePortService.Paddle3; - - if (UseKeyboard) // override - { - if (((Joystick0UpLeftKey > 0) && _keyboardService.IsKeyDown(Joystick0UpLeftKey)) || - ((Joystick0LeftKey > 0) && _keyboardService.IsKeyDown(Joystick0LeftKey)) || - ((Joystick0DownLeftKey > 0) && _keyboardService.IsKeyDown(Joystick0DownLeftKey))) - { - paddle0 -= PaddleScale; - } - if (((Joystick0UpRightKey > 0) && _keyboardService.IsKeyDown(Joystick0UpRightKey)) || - ((Joystick0RightKey > 0) && _keyboardService.IsKeyDown(Joystick0RightKey)) || - ((Joystick0DownRightKey > 0) && _keyboardService.IsKeyDown(Joystick0DownRightKey))) - { - paddle0 += PaddleScale; - } - if (((Joystick0UpLeftKey > 0) && _keyboardService.IsKeyDown(Joystick0UpLeftKey)) || - ((Joystick0UpKey > 0) && _keyboardService.IsKeyDown(Joystick0UpKey)) || - ((Joystick0UpRightKey > 0) && _keyboardService.IsKeyDown(Joystick0UpRightKey))) - { - paddle1 -= PaddleScale; - } - if (((Joystick0DownLeftKey > 0) && _keyboardService.IsKeyDown(Joystick0DownLeftKey)) || - ((Joystick0DownKey > 0) && _keyboardService.IsKeyDown(Joystick0DownKey)) || - ((Joystick0DownRightKey > 0) && _keyboardService.IsKeyDown(Joystick0DownRightKey))) - { - paddle1 += PaddleScale; - } - if (((Joystick1UpLeftKey > 0) && _keyboardService.IsKeyDown(Joystick1UpLeftKey)) || - ((Joystick1LeftKey > 0) && _keyboardService.IsKeyDown(Joystick1LeftKey)) || - ((Joystick1DownLeftKey > 0) && _keyboardService.IsKeyDown(Joystick1DownLeftKey))) - { - paddle2 -= PaddleScale; - } - if (((Joystick1UpRightKey > 0) && _keyboardService.IsKeyDown(Joystick1UpRightKey)) || - ((Joystick1RightKey > 0) && _keyboardService.IsKeyDown(Joystick1RightKey)) || - ((Joystick1DownRightKey > 0) && _keyboardService.IsKeyDown(Joystick1DownRightKey))) - { - paddle2 += PaddleScale; - } - if (((Joystick1UpLeftKey > 0) && _keyboardService.IsKeyDown(Joystick1UpLeftKey)) || - ((Joystick1UpKey > 0) && _keyboardService.IsKeyDown(Joystick1UpKey)) || - ((Joystick1UpRightKey > 0) && _keyboardService.IsKeyDown(Joystick1UpRightKey))) - { - paddle3 -= PaddleScale; - } - if (((Joystick1DownLeftKey > 0) && _keyboardService.IsKeyDown(Joystick1DownLeftKey)) || - ((Joystick1DownKey > 0) && _keyboardService.IsKeyDown(Joystick1DownKey)) || - ((Joystick1DownRightKey > 0) && _keyboardService.IsKeyDown(Joystick1DownRightKey))) - { - paddle3 += PaddleScale; - } - } - if (InvertPaddles) - { - paddle0 = 2 * PaddleScale - paddle0; - paddle1 = 2 * PaddleScale - paddle1; - paddle2 = 2 * PaddleScale - paddle2; - paddle3 = 2 * PaddleScale - paddle3; - } - - Paddle0Strobe = true; - Paddle1Strobe = true; - Paddle2Strobe = true; - Paddle3Strobe = true; - - Machine.Events.AddEvent(MathHelpers.ClampByte(SwapPaddles ? paddle1 : paddle0) * CyclesPerValue, _resetPaddle0StrobeEvent); // [7-29] - Machine.Events.AddEvent(MathHelpers.ClampByte(SwapPaddles ? paddle0 : paddle1) * CyclesPerValue, _resetPaddle1StrobeEvent); - Machine.Events.AddEvent(MathHelpers.ClampByte(SwapPaddles ? paddle3 : paddle2) * CyclesPerValue, _resetPaddle2StrobeEvent); - Machine.Events.AddEvent(MathHelpers.ClampByte(SwapPaddles ? paddle2 : paddle3) * CyclesPerValue, _resetPaddle3StrobeEvent); - } - - private void ResetPaddle0StrobeEvent() - { - Paddle0Strobe = false; - } - - private void ResetPaddle1StrobeEvent() - { - Paddle1Strobe = false; - } - - private void ResetPaddle2StrobeEvent() - { - Paddle2Strobe = false; - } - - private void ResetPaddle3StrobeEvent() - { - Paddle3Strobe = false; - } - - public const int PaddleScale = 128; - - public bool InvertPaddles { get; set; } - public bool SwapPaddles { get; set; } - public bool UseShiftKeyMod { get; set; } - public float 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 UseTouch { get; set; } - public float Joystick0TouchX { get; set; } - public float Joystick0TouchY { get; set; } - public float Joystick0TouchWidth { get; set; } - public float Joystick0TouchHeight { get; set; } - public int Joystick0TouchOrder { get; set; } - public float Joystick0TouchRadius { get; set; } - public bool Joystick0TouchKeepLast { get; set; } - public float Joystick1TouchX { get; set; } - public float Joystick1TouchY { get; set; } - public float Joystick1TouchWidth { get; set; } - public float Joystick1TouchHeight { get; set; } - public int Joystick1TouchOrder { get; set; } - public float Joystick1TouchRadius { get; set; } - public bool Joystick1TouchKeepLast { get; set; } - public float Button0TouchX { get; set; } - public float Button0TouchY { get; set; } - public float Button0TouchWidth { get; set; } - public float Button0TouchHeight { get; set; } - public int Button0TouchOrder { get; set; } - public float Button1TouchX { get; set; } - public float Button1TouchY { get; set; } - public float Button1TouchWidth { get; set; } - public float Button1TouchHeight { get; set; } - public int Button1TouchOrder { get; set; } - public float Button2TouchX { get; set; } - public float Button2TouchY { get; set; } - public float Button2TouchWidth { get; set; } - public float Button2TouchHeight { get; set; } - public int Button2TouchOrder { get; set; } - - public bool Paddle0Strobe { get; private set; } - public bool Paddle1Strobe { get; private set; } - public bool Paddle2Strobe { get; private set; } - public bool Paddle3Strobe { get; private set; } - - private const int CyclesPerValue = 11; - - private Action _resetPaddle0StrobeEvent; - private Action _resetPaddle1StrobeEvent; - private Action _resetPaddle2StrobeEvent; - private Action _resetPaddle3StrobeEvent; - - private KeyboardService _keyboardService; - private GamePortService _gamePortService; - } -} +using System; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using Jellyfish.Library; +using Jellyfish.Virtu.Services; + +namespace Jellyfish.Virtu +{ + public sealed class GamePort : MachineComponent + { + public GamePort(Machine machine) : + base(machine) + { + _resetPaddle0StrobeEvent = ResetPaddle0StrobeEvent; // cache delegates; avoids garbage + _resetPaddle1StrobeEvent = ResetPaddle1StrobeEvent; + _resetPaddle2StrobeEvent = ResetPaddle2StrobeEvent; + _resetPaddle3StrobeEvent = ResetPaddle3StrobeEvent; + } + + public override void Initialize() + { + _keyboardService = Machine.Services.GetService(); + _gamePortService = Machine.Services.GetService(); + + JoystickDeadZone = 0.4f; + + InvertPaddles = true; // Raster Blaster + SwapPaddles = true; + Joystick0TouchX = 0.35f; + Joystick0TouchY = 0.6f; + Joystick0TouchWidth = 0.25f; + Joystick0TouchHeight = 0.4f; + Joystick0TouchRadius = 0.2f; + Joystick0TouchKeepLast = true; + Button0TouchX = 0; + Button0TouchY = 0; + Button0TouchWidth = 0.5f; + Button0TouchHeight = 1; + Button1TouchX = 0.5f; + Button1TouchY = 0; + Button1TouchWidth = 0.5f; + Button1TouchHeight = 1; + Button2TouchX = 0.75f; + Button2TouchY = 0; + Button2TouchWidth = 0.25f; + Button2TouchHeight = 0.25f; + Button2TouchOrder = 1; + } + + public override void LoadState(BinaryReader reader, Version version) + { + if (reader == null) + { + throw new ArgumentNullException("reader"); + } + + InvertPaddles = reader.ReadBoolean(); + SwapPaddles = reader.ReadBoolean(); + UseShiftKeyMod = reader.ReadBoolean(); + JoystickDeadZone = reader.ReadSingle(); + + 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(); + + UseTouch = reader.ReadBoolean(); + Joystick0TouchX = reader.ReadSingle(); + Joystick0TouchY = reader.ReadSingle(); + Joystick0TouchWidth = reader.ReadSingle(); + Joystick0TouchHeight = reader.ReadSingle(); + Joystick0TouchOrder = reader.ReadInt32(); + Joystick0TouchRadius = reader.ReadSingle(); + Joystick0TouchKeepLast = reader.ReadBoolean(); + Joystick1TouchX = reader.ReadSingle(); + Joystick1TouchY = reader.ReadSingle(); + Joystick1TouchWidth = reader.ReadSingle(); + Joystick1TouchHeight = reader.ReadSingle(); + Joystick1TouchOrder = reader.ReadInt32(); + Joystick1TouchRadius = reader.ReadSingle(); + Joystick1TouchKeepLast = reader.ReadBoolean(); + Button0TouchX = reader.ReadSingle(); + Button0TouchY = reader.ReadSingle(); + Button0TouchWidth = reader.ReadSingle(); + Button0TouchHeight = reader.ReadSingle(); + Button0TouchOrder = reader.ReadInt32(); + Button1TouchX = reader.ReadSingle(); + Button1TouchY = reader.ReadSingle(); + Button1TouchWidth = reader.ReadSingle(); + Button1TouchHeight = reader.ReadSingle(); + Button1TouchOrder = reader.ReadInt32(); + Button2TouchX = reader.ReadSingle(); + Button2TouchY = reader.ReadSingle(); + Button2TouchWidth = reader.ReadSingle(); + Button2TouchHeight = reader.ReadSingle(); + Button2TouchOrder = reader.ReadInt32(); + } + + public override void SaveState(BinaryWriter writer) + { + if (writer == null) + { + throw new ArgumentNullException("writer"); + } + + writer.Write(InvertPaddles); + writer.Write(SwapPaddles); + writer.Write(UseShiftKeyMod); + 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); + + writer.Write(UseTouch); + writer.Write(Joystick0TouchX); + writer.Write(Joystick0TouchY); + writer.Write(Joystick0TouchWidth); + writer.Write(Joystick0TouchHeight); + writer.Write(Joystick0TouchOrder); + writer.Write(Joystick0TouchRadius); + writer.Write(Joystick0TouchKeepLast); + writer.Write(Joystick1TouchX); + writer.Write(Joystick1TouchY); + writer.Write(Joystick1TouchWidth); + writer.Write(Joystick1TouchHeight); + writer.Write(Joystick1TouchOrder); + writer.Write(Joystick1TouchRadius); + writer.Write(Joystick1TouchKeepLast); + writer.Write(Button0TouchX); + writer.Write(Button0TouchY); + writer.Write(Button0TouchWidth); + writer.Write(Button0TouchHeight); + writer.Write(Button0TouchOrder); + writer.Write(Button1TouchX); + writer.Write(Button1TouchY); + writer.Write(Button1TouchWidth); + writer.Write(Button1TouchHeight); + writer.Write(Button1TouchOrder); + writer.Write(Button2TouchX); + writer.Write(Button2TouchY); + writer.Write(Button2TouchWidth); + writer.Write(Button2TouchHeight); + writer.Write(Button2TouchOrder); + } + + public bool ReadButton0() + { + return (_gamePortService.IsButton0Down || _keyboardService.IsOpenAppleKeyDown || + (UseKeyboard && (Button0Key > 0) && _keyboardService.IsKeyDown(Button0Key))); + } + + public bool ReadButton1() + { + return (_gamePortService.IsButton1Down || _keyboardService.IsCloseAppleKeyDown || + (UseKeyboard && (Button1Key > 0) && _keyboardService.IsKeyDown(Button1Key))); + } + + public bool ReadButton2() + { + return (_gamePortService.IsButton2Down || (UseShiftKeyMod && !_keyboardService.IsShiftKeyDown) || // Shift' [TN9] + (UseKeyboard && (Button2Key > 0) && _keyboardService.IsKeyDown(Button2Key))); + } + + [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] + public void TriggerTimers() + { + int paddle0 = _gamePortService.Paddle0; + int paddle1 = _gamePortService.Paddle1; + int paddle2 = _gamePortService.Paddle2; + int paddle3 = _gamePortService.Paddle3; + + if (UseKeyboard) // override + { + if (((Joystick0UpLeftKey > 0) && _keyboardService.IsKeyDown(Joystick0UpLeftKey)) || + ((Joystick0LeftKey > 0) && _keyboardService.IsKeyDown(Joystick0LeftKey)) || + ((Joystick0DownLeftKey > 0) && _keyboardService.IsKeyDown(Joystick0DownLeftKey))) + { + paddle0 -= PaddleScale; + } + if (((Joystick0UpRightKey > 0) && _keyboardService.IsKeyDown(Joystick0UpRightKey)) || + ((Joystick0RightKey > 0) && _keyboardService.IsKeyDown(Joystick0RightKey)) || + ((Joystick0DownRightKey > 0) && _keyboardService.IsKeyDown(Joystick0DownRightKey))) + { + paddle0 += PaddleScale; + } + if (((Joystick0UpLeftKey > 0) && _keyboardService.IsKeyDown(Joystick0UpLeftKey)) || + ((Joystick0UpKey > 0) && _keyboardService.IsKeyDown(Joystick0UpKey)) || + ((Joystick0UpRightKey > 0) && _keyboardService.IsKeyDown(Joystick0UpRightKey))) + { + paddle1 -= PaddleScale; + } + if (((Joystick0DownLeftKey > 0) && _keyboardService.IsKeyDown(Joystick0DownLeftKey)) || + ((Joystick0DownKey > 0) && _keyboardService.IsKeyDown(Joystick0DownKey)) || + ((Joystick0DownRightKey > 0) && _keyboardService.IsKeyDown(Joystick0DownRightKey))) + { + paddle1 += PaddleScale; + } + if (((Joystick1UpLeftKey > 0) && _keyboardService.IsKeyDown(Joystick1UpLeftKey)) || + ((Joystick1LeftKey > 0) && _keyboardService.IsKeyDown(Joystick1LeftKey)) || + ((Joystick1DownLeftKey > 0) && _keyboardService.IsKeyDown(Joystick1DownLeftKey))) + { + paddle2 -= PaddleScale; + } + if (((Joystick1UpRightKey > 0) && _keyboardService.IsKeyDown(Joystick1UpRightKey)) || + ((Joystick1RightKey > 0) && _keyboardService.IsKeyDown(Joystick1RightKey)) || + ((Joystick1DownRightKey > 0) && _keyboardService.IsKeyDown(Joystick1DownRightKey))) + { + paddle2 += PaddleScale; + } + if (((Joystick1UpLeftKey > 0) && _keyboardService.IsKeyDown(Joystick1UpLeftKey)) || + ((Joystick1UpKey > 0) && _keyboardService.IsKeyDown(Joystick1UpKey)) || + ((Joystick1UpRightKey > 0) && _keyboardService.IsKeyDown(Joystick1UpRightKey))) + { + paddle3 -= PaddleScale; + } + if (((Joystick1DownLeftKey > 0) && _keyboardService.IsKeyDown(Joystick1DownLeftKey)) || + ((Joystick1DownKey > 0) && _keyboardService.IsKeyDown(Joystick1DownKey)) || + ((Joystick1DownRightKey > 0) && _keyboardService.IsKeyDown(Joystick1DownRightKey))) + { + paddle3 += PaddleScale; + } + } + if (InvertPaddles) + { + paddle0 = 2 * PaddleScale - paddle0; + paddle1 = 2 * PaddleScale - paddle1; + paddle2 = 2 * PaddleScale - paddle2; + paddle3 = 2 * PaddleScale - paddle3; + } + + Paddle0Strobe = true; + Paddle1Strobe = true; + Paddle2Strobe = true; + Paddle3Strobe = true; + + Machine.Events.AddEvent(MathHelpers.ClampByte(SwapPaddles ? paddle1 : paddle0) * CyclesPerValue, _resetPaddle0StrobeEvent); // [7-29] + Machine.Events.AddEvent(MathHelpers.ClampByte(SwapPaddles ? paddle0 : paddle1) * CyclesPerValue, _resetPaddle1StrobeEvent); + Machine.Events.AddEvent(MathHelpers.ClampByte(SwapPaddles ? paddle3 : paddle2) * CyclesPerValue, _resetPaddle2StrobeEvent); + Machine.Events.AddEvent(MathHelpers.ClampByte(SwapPaddles ? paddle2 : paddle3) * CyclesPerValue, _resetPaddle3StrobeEvent); + } + + private void ResetPaddle0StrobeEvent() + { + Paddle0Strobe = false; + } + + private void ResetPaddle1StrobeEvent() + { + Paddle1Strobe = false; + } + + private void ResetPaddle2StrobeEvent() + { + Paddle2Strobe = false; + } + + private void ResetPaddle3StrobeEvent() + { + Paddle3Strobe = false; + } + + public const int PaddleScale = 128; + + public bool InvertPaddles { get; set; } + public bool SwapPaddles { get; set; } + public bool UseShiftKeyMod { get; set; } + public float 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 UseTouch { get; set; } + public float Joystick0TouchX { get; set; } + public float Joystick0TouchY { get; set; } + public float Joystick0TouchWidth { get; set; } + public float Joystick0TouchHeight { get; set; } + public int Joystick0TouchOrder { get; set; } + public float Joystick0TouchRadius { get; set; } + public bool Joystick0TouchKeepLast { get; set; } + public float Joystick1TouchX { get; set; } + public float Joystick1TouchY { get; set; } + public float Joystick1TouchWidth { get; set; } + public float Joystick1TouchHeight { get; set; } + public int Joystick1TouchOrder { get; set; } + public float Joystick1TouchRadius { get; set; } + public bool Joystick1TouchKeepLast { get; set; } + public float Button0TouchX { get; set; } + public float Button0TouchY { get; set; } + public float Button0TouchWidth { get; set; } + public float Button0TouchHeight { get; set; } + public int Button0TouchOrder { get; set; } + public float Button1TouchX { get; set; } + public float Button1TouchY { get; set; } + public float Button1TouchWidth { get; set; } + public float Button1TouchHeight { get; set; } + public int Button1TouchOrder { get; set; } + public float Button2TouchX { get; set; } + public float Button2TouchY { get; set; } + public float Button2TouchWidth { get; set; } + public float Button2TouchHeight { get; set; } + public int Button2TouchOrder { get; set; } + + public bool Paddle0Strobe { get; private set; } + public bool Paddle1Strobe { get; private set; } + public bool Paddle2Strobe { get; private set; } + public bool Paddle3Strobe { get; private set; } + + private const int CyclesPerValue = 11; + + private Action _resetPaddle0StrobeEvent; + private Action _resetPaddle1StrobeEvent; + private Action _resetPaddle2StrobeEvent; + private Action _resetPaddle3StrobeEvent; + + private KeyboardService _keyboardService; + private GamePortService _gamePortService; + } +} diff --git a/Virtu/GlobalSuppressions.cs b/Virtu/GlobalSuppressions.cs index 93c1eb8..0479618 100644 --- a/Virtu/GlobalSuppressions.cs +++ b/Virtu/GlobalSuppressions.cs @@ -1,3 +1,3 @@ -using System.Diagnostics.CodeAnalysis; - -[assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")] +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")] diff --git a/Virtu/Jellyfish.Virtu.sln b/Virtu/Jellyfish.Virtu.sln index ef948ce..c2bd2ed 100644 --- a/Virtu/Jellyfish.Virtu.sln +++ b/Virtu/Jellyfish.Virtu.sln @@ -1,38 +1,38 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Library.Silverlight", "..\Library\Silverlight\Jellyfish.Library.Silverlight.csproj", "{99CA7796-B72A-4F8C-BCDB-0D688220A331}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Library.Wpf", "..\Library\Wpf\Jellyfish.Library.Wpf.csproj", "{93900841-7250-4D3A-837E-43EE3FD118DC}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Virtu.Silverlight", "Silverlight\Jellyfish.Virtu.Silverlight.csproj", "{F8DB6D3A-807D-4E2D-92D5-469273E088DA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Virtu.Wpf", "Wpf\Jellyfish.Virtu.Wpf.csproj", "{C152D47E-BBC1-4C35-8646-465180720A72}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {93900841-7250-4D3A-837E-43EE3FD118DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {93900841-7250-4D3A-837E-43EE3FD118DC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {93900841-7250-4D3A-837E-43EE3FD118DC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {93900841-7250-4D3A-837E-43EE3FD118DC}.Release|Any CPU.Build.0 = Release|Any CPU - {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Debug|Any CPU.Build.0 = Debug|Any CPU - {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Release|Any CPU.ActiveCfg = Release|Any CPU - {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Release|Any CPU.Build.0 = Release|Any CPU - {C152D47E-BBC1-4C35-8646-465180720A72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C152D47E-BBC1-4C35-8646-465180720A72}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C152D47E-BBC1-4C35-8646-465180720A72}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C152D47E-BBC1-4C35-8646-465180720A72}.Release|Any CPU.Build.0 = Release|Any CPU - {F8DB6D3A-807D-4E2D-92D5-469273E088DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F8DB6D3A-807D-4E2D-92D5-469273E088DA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F8DB6D3A-807D-4E2D-92D5-469273E088DA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F8DB6D3A-807D-4E2D-92D5-469273E088DA}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Library.Silverlight", "..\Library\Silverlight\Jellyfish.Library.Silverlight.csproj", "{99CA7796-B72A-4F8C-BCDB-0D688220A331}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Library.Wpf", "..\Library\Wpf\Jellyfish.Library.Wpf.csproj", "{93900841-7250-4D3A-837E-43EE3FD118DC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Virtu.Silverlight", "Silverlight\Jellyfish.Virtu.Silverlight.csproj", "{F8DB6D3A-807D-4E2D-92D5-469273E088DA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Virtu.Wpf", "Wpf\Jellyfish.Virtu.Wpf.csproj", "{C152D47E-BBC1-4C35-8646-465180720A72}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {93900841-7250-4D3A-837E-43EE3FD118DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {93900841-7250-4D3A-837E-43EE3FD118DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {93900841-7250-4D3A-837E-43EE3FD118DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {93900841-7250-4D3A-837E-43EE3FD118DC}.Release|Any CPU.Build.0 = Release|Any CPU + {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Debug|Any CPU.Build.0 = Debug|Any CPU + {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Release|Any CPU.ActiveCfg = Release|Any CPU + {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Release|Any CPU.Build.0 = Release|Any CPU + {C152D47E-BBC1-4C35-8646-465180720A72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C152D47E-BBC1-4C35-8646-465180720A72}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C152D47E-BBC1-4C35-8646-465180720A72}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C152D47E-BBC1-4C35-8646-465180720A72}.Release|Any CPU.Build.0 = Release|Any CPU + {F8DB6D3A-807D-4E2D-92D5-469273E088DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8DB6D3A-807D-4E2D-92D5-469273E088DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8DB6D3A-807D-4E2D-92D5-469273E088DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8DB6D3A-807D-4E2D-92D5-469273E088DA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Virtu/Keyboard.cs b/Virtu/Keyboard.cs index bee2f5c..b0f6ac4 100644 --- a/Virtu/Keyboard.cs +++ b/Virtu/Keyboard.cs @@ -1,120 +1,120 @@ -using System; -using System.IO; -using Jellyfish.Virtu.Services; - -namespace Jellyfish.Virtu -{ - public sealed class Keyboard : MachineComponent - { - public Keyboard(Machine machine) : - base(machine) - { - } - - public override void Initialize() - { - _keyboardService = Machine.Services.GetService(); - - UseGamePort = true; // Raster Blaster - Button2Key = ' '; - } - - public override void LoadState(BinaryReader reader, Version version) - { - if (reader == null) - { - throw new ArgumentNullException("reader"); - } - - DisableResetKey = reader.ReadBoolean(); - - 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(DisableResetKey); - - 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); - } - - public void ResetStrobe() - { - Strobe = false; - } - - public bool DisableResetKey { get; set; } - - 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; } - - private KeyboardService _keyboardService; - - private int _latch; - } -} +using System; +using System.IO; +using Jellyfish.Virtu.Services; + +namespace Jellyfish.Virtu +{ + public sealed class Keyboard : MachineComponent + { + public Keyboard(Machine machine) : + base(machine) + { + } + + public override void Initialize() + { + _keyboardService = Machine.Services.GetService(); + + UseGamePort = true; // Raster Blaster + Button2Key = ' '; + } + + public override void LoadState(BinaryReader reader, Version version) + { + if (reader == null) + { + throw new ArgumentNullException("reader"); + } + + DisableResetKey = reader.ReadBoolean(); + + 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(DisableResetKey); + + 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); + } + + public void ResetStrobe() + { + Strobe = false; + } + + public bool DisableResetKey { get; set; } + + 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; } + + private KeyboardService _keyboardService; + + private int _latch; + } +} diff --git a/Virtu/Machine.cs b/Virtu/Machine.cs index 0b66ad8..924c9cb 100644 --- a/Virtu/Machine.cs +++ b/Virtu/Machine.cs @@ -1,273 +1,273 @@ -using System; -using System.Collections.ObjectModel; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Linq; -using System.Threading; -using Jellyfish.Virtu.Services; - -namespace Jellyfish.Virtu -{ - public enum MachineState { Stopped = 0, Starting, Running, Pausing, Paused, Stopping } - - public sealed class Machine : IDisposable - { - public Machine() - { - Events = new MachineEvents(); - Services = new MachineServices(); - - Cpu = new Cpu(this); - Memory = new Memory(this); - Keyboard = new Keyboard(this); - GamePort = new GamePort(this); - Cassette = new Cassette(this); - Speaker = new Speaker(this); - Video = new Video(this); - NoSlotClock = new NoSlotClock(this); - - var emptySlot = new PeripheralCard(this); - Slot1 = emptySlot; - Slot2 = emptySlot; - Slot3 = emptySlot; - Slot4 = emptySlot; - Slot5 = emptySlot; - Slot6 = new DiskIIController(this); - Slot7 = emptySlot; - - 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" }; - } - - public void Dispose() - { - _pauseEvent.Close(); - _unpauseEvent.Close(); - } - - public void Reset() - { - foreach (var component in Components) - { - _debugService.WriteMessage("Resetting machine '{0}'", component.GetType().Name); - component.Reset(); - //_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) - { - Thread.Join(); - } - State = MachineState.Stopped; - _debugService.WriteMessage("Stopped machine"); - } - - private void Initialize() - { - foreach (var component in Components) - { - _debugService.WriteMessage("Initializing machine '{0}'", component.GetType().Name); - component.Initialize(); - //_debugService.WriteMessage("Initialized machine '{0}'", component.GetType().Name); - } - } - - private void LoadState() - { -#if WINDOWS - var args = Environment.GetCommandLineArgs(); - if (args.Length > 1) - { - string name = args[1]; - Func, bool> loader = StorageService.LoadFile; - - if (name.StartsWith("res://", StringComparison.OrdinalIgnoreCase)) - { - name = name.Substring(6); - loader = StorageService.LoadResource; - } - - if (name.EndsWith(".bin", StringComparison.OrdinalIgnoreCase)) - { - loader(name, stream => LoadState(stream)); - } - else if (name.EndsWith(".prg", StringComparison.OrdinalIgnoreCase)) - { - loader(name, stream => Memory.LoadPrg(stream)); - } - else if (name.EndsWith(".xex", StringComparison.OrdinalIgnoreCase)) - { - loader(name, stream => Memory.LoadXex(stream)); - } - else - { - 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.BootDrive.InsertDisk("Default.dsk", stream, false)); - } - } - - private void LoadState(Stream stream) - { - using (var reader = new BinaryReader(stream)) - { - 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.WriteMessage("Loading machine '{0}'", component.GetType().Name); - component.LoadState(reader, version); - //_debugService.WriteMessage("Loaded machine '{0}'", component.GetType().Name); - } - } - } - - private void SaveState() - { - _storageService.Save(Machine.StateFileName, stream => SaveState(stream)); - } - - private void SaveState(Stream stream) - { - using (var writer = new BinaryWriter(stream)) - { - writer.Write(StateSignature); - writer.Write(Machine.Version); - foreach (var component in Components) - { - _debugService.WriteMessage("Saving machine '{0}'", component.GetType().Name); - component.SaveState(writer); - //_debugService.WriteMessage("Saved machine '{0}'", component.GetType().Name); - } - } - } - - private void Uninitialize() - { - foreach (var component in Components) - { - _debugService.WriteMessage("Uninitializing machine '{0}'", component.GetType().Name); - component.Uninitialize(); - //_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 - { - Initialize(); - Reset(); - LoadState(); - - _debugService.WriteMessage("Running machine"); - State = MachineState.Running; - do - { - do - { - Events.HandleEvents(Cpu.Execute()); - } - while (State == MachineState.Running); - - if (State == MachineState.Pausing) - { - _pauseEvent.Set(); - _unpauseEvent.WaitOne(); - } - } - while (State != MachineState.Stopping); - - SaveState(); - Uninitialize(); - } - - public const string Version = "0.9.4.0"; - - public MachineEvents Events { get; private set; } - public MachineServices Services { get; private set; } - public MachineState State { get { return _state; } private set { _state = value; } } - - public Cpu Cpu { get; private set; } - public Memory Memory { get; private set; } - public Keyboard Keyboard { get; private set; } - public GamePort GamePort { get; private set; } - public Cassette Cassette { get; private set; } - public Speaker Speaker { get; private set; } - public Video Video { get; private set; } - public NoSlotClock NoSlotClock { get; private set; } - - public PeripheralCard Slot1 { get; private set; } - public PeripheralCard Slot2 { get; private set; } - public PeripheralCard Slot3 { get; private set; } - public PeripheralCard Slot4 { get; private set; } - public PeripheralCard Slot5 { get; private set; } - public PeripheralCard Slot6 { get; private set; } - public PeripheralCard Slot7 { get; private set; } - - 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 StorageService _storageService; - private volatile MachineState _state; - - private AutoResetEvent _pauseEvent = new AutoResetEvent(false); - private AutoResetEvent _unpauseEvent = new AutoResetEvent(false); - } -} +using System; +using System.Collections.ObjectModel; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Threading; +using Jellyfish.Virtu.Services; + +namespace Jellyfish.Virtu +{ + public enum MachineState { Stopped = 0, Starting, Running, Pausing, Paused, Stopping } + + public sealed class Machine : IDisposable + { + public Machine() + { + Events = new MachineEvents(); + Services = new MachineServices(); + + Cpu = new Cpu(this); + Memory = new Memory(this); + Keyboard = new Keyboard(this); + GamePort = new GamePort(this); + Cassette = new Cassette(this); + Speaker = new Speaker(this); + Video = new Video(this); + NoSlotClock = new NoSlotClock(this); + + var emptySlot = new PeripheralCard(this); + Slot1 = emptySlot; + Slot2 = emptySlot; + Slot3 = emptySlot; + Slot4 = emptySlot; + Slot5 = emptySlot; + Slot6 = new DiskIIController(this); + Slot7 = emptySlot; + + 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" }; + } + + public void Dispose() + { + _pauseEvent.Close(); + _unpauseEvent.Close(); + } + + public void Reset() + { + foreach (var component in Components) + { + _debugService.WriteMessage("Resetting machine '{0}'", component.GetType().Name); + component.Reset(); + //_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) + { + Thread.Join(); + } + State = MachineState.Stopped; + _debugService.WriteMessage("Stopped machine"); + } + + private void Initialize() + { + foreach (var component in Components) + { + _debugService.WriteMessage("Initializing machine '{0}'", component.GetType().Name); + component.Initialize(); + //_debugService.WriteMessage("Initialized machine '{0}'", component.GetType().Name); + } + } + + private void LoadState() + { +#if WINDOWS + var args = Environment.GetCommandLineArgs(); + if (args.Length > 1) + { + string name = args[1]; + Func, bool> loader = StorageService.LoadFile; + + if (name.StartsWith("res://", StringComparison.OrdinalIgnoreCase)) + { + name = name.Substring(6); + loader = StorageService.LoadResource; + } + + if (name.EndsWith(".bin", StringComparison.OrdinalIgnoreCase)) + { + loader(name, stream => LoadState(stream)); + } + else if (name.EndsWith(".prg", StringComparison.OrdinalIgnoreCase)) + { + loader(name, stream => Memory.LoadPrg(stream)); + } + else if (name.EndsWith(".xex", StringComparison.OrdinalIgnoreCase)) + { + loader(name, stream => Memory.LoadXex(stream)); + } + else + { + 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.BootDrive.InsertDisk("Default.dsk", stream, false)); + } + } + + private void LoadState(Stream stream) + { + using (var reader = new BinaryReader(stream)) + { + 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.WriteMessage("Loading machine '{0}'", component.GetType().Name); + component.LoadState(reader, version); + //_debugService.WriteMessage("Loaded machine '{0}'", component.GetType().Name); + } + } + } + + private void SaveState() + { + _storageService.Save(Machine.StateFileName, stream => SaveState(stream)); + } + + private void SaveState(Stream stream) + { + using (var writer = new BinaryWriter(stream)) + { + writer.Write(StateSignature); + writer.Write(Machine.Version); + foreach (var component in Components) + { + _debugService.WriteMessage("Saving machine '{0}'", component.GetType().Name); + component.SaveState(writer); + //_debugService.WriteMessage("Saved machine '{0}'", component.GetType().Name); + } + } + } + + private void Uninitialize() + { + foreach (var component in Components) + { + _debugService.WriteMessage("Uninitializing machine '{0}'", component.GetType().Name); + component.Uninitialize(); + //_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 + { + Initialize(); + Reset(); + LoadState(); + + _debugService.WriteMessage("Running machine"); + State = MachineState.Running; + do + { + do + { + Events.HandleEvents(Cpu.Execute()); + } + while (State == MachineState.Running); + + if (State == MachineState.Pausing) + { + _pauseEvent.Set(); + _unpauseEvent.WaitOne(); + } + } + while (State != MachineState.Stopping); + + SaveState(); + Uninitialize(); + } + + public const string Version = "0.9.4.0"; + + public MachineEvents Events { get; private set; } + public MachineServices Services { get; private set; } + public MachineState State { get { return _state; } private set { _state = value; } } + + public Cpu Cpu { get; private set; } + public Memory Memory { get; private set; } + public Keyboard Keyboard { get; private set; } + public GamePort GamePort { get; private set; } + public Cassette Cassette { get; private set; } + public Speaker Speaker { get; private set; } + public Video Video { get; private set; } + public NoSlotClock NoSlotClock { get; private set; } + + public PeripheralCard Slot1 { get; private set; } + public PeripheralCard Slot2 { get; private set; } + public PeripheralCard Slot3 { get; private set; } + public PeripheralCard Slot4 { get; private set; } + public PeripheralCard Slot5 { get; private set; } + public PeripheralCard Slot6 { get; private set; } + public PeripheralCard Slot7 { get; private set; } + + 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 StorageService _storageService; + private volatile MachineState _state; + + private AutoResetEvent _pauseEvent = new AutoResetEvent(false); + private AutoResetEvent _unpauseEvent = new AutoResetEvent(false); + } +} diff --git a/Virtu/MachineComponent.cs b/Virtu/MachineComponent.cs index 195b8ed..0d67f41 100644 --- a/Virtu/MachineComponent.cs +++ b/Virtu/MachineComponent.cs @@ -1,42 +1,42 @@ -using System; -using System.IO; -using Jellyfish.Library; -using Jellyfish.Virtu.Services; - -namespace Jellyfish.Virtu -{ - public abstract class MachineComponent - { - protected MachineComponent(Machine machine) - { - Machine = machine; - - _debugService = new Lazy(() => Machine.Services.GetService()); - } - - public virtual void Initialize() - { - } - - 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; } - protected DebugService DebugService { get { return _debugService.Value; } } - - private Lazy _debugService; - } -} +using System; +using System.IO; +using Jellyfish.Library; +using Jellyfish.Virtu.Services; + +namespace Jellyfish.Virtu +{ + public abstract class MachineComponent + { + protected MachineComponent(Machine machine) + { + Machine = machine; + + _debugService = new Lazy(() => Machine.Services.GetService()); + } + + public virtual void Initialize() + { + } + + 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; } + protected DebugService DebugService { get { return _debugService.Value; } } + + private Lazy _debugService; + } +} diff --git a/Virtu/MachineEvents.cs b/Virtu/MachineEvents.cs index f008d04..6b87993 100644 --- a/Virtu/MachineEvents.cs +++ b/Virtu/MachineEvents.cs @@ -1,107 +1,107 @@ -using System; -using System.Collections.Generic; -using System.Globalization; - -namespace Jellyfish.Virtu -{ - public sealed class MachineEvent - { - public MachineEvent(int delta, Action action) - { - Delta = delta; - Action = action; - } - - public override string ToString() - { - return string.Format(CultureInfo.InvariantCulture, "Delta = {0} Action = {{{1}.{2}}}", Delta, Action.Method.DeclaringType.Name, Action.Method.Name); - } - - public int Delta { get; set; } - public Action Action { get; set; } - } - - public sealed class MachineEvents - { - public void AddEvent(int delta, Action action) - { - var node = _used.First; - for (; node != null; node = node.Next) - { - if (delta < node.Value.Delta) - { - node.Value.Delta -= delta; - break; - } - if (node.Value.Delta > 0) - { - delta -= node.Value.Delta; - } - } - - var newNode = _free.First; - if (newNode != null) - { - _free.RemoveFirst(); - newNode.Value.Delta = delta; - newNode.Value.Action = action; - } - else - { - newNode = new LinkedListNode(new MachineEvent(delta, action)); - } - - if (node != null) - { - _used.AddBefore(node, newNode); - } - else - { - _used.AddLast(newNode); - } - } - - public int FindEvent(Action action) - { - int delta = 0; - - for (var node = _used.First; node != null; node = node.Next) - { - delta += node.Value.Delta; - if (object.ReferenceEquals(node.Value.Action, action)) // assumes delegate cached - { - return delta; - } - } - - return 0; - } - - public void HandleEvents(int delta) - { - var node = _used.First; - node.Value.Delta -= delta; - - while (node.Value.Delta <= 0) - { - node.Value.Action(); - RemoveEvent(node); - node = _used.First; - } - } - - private void RemoveEvent(LinkedListNode node) - { - if (node.Next != null) - { - node.Next.Value.Delta += node.Value.Delta; - } - - _used.Remove(node); - _free.AddFirst(node); // cache node; avoids garbage - } - - private LinkedList _used = new LinkedList(); - private LinkedList _free = new LinkedList(); - } -} +using System; +using System.Collections.Generic; +using System.Globalization; + +namespace Jellyfish.Virtu +{ + public sealed class MachineEvent + { + public MachineEvent(int delta, Action action) + { + Delta = delta; + Action = action; + } + + public override string ToString() + { + return string.Format(CultureInfo.InvariantCulture, "Delta = {0} Action = {{{1}.{2}}}", Delta, Action.Method.DeclaringType.Name, Action.Method.Name); + } + + public int Delta { get; set; } + public Action Action { get; set; } + } + + public sealed class MachineEvents + { + public void AddEvent(int delta, Action action) + { + var node = _used.First; + for (; node != null; node = node.Next) + { + if (delta < node.Value.Delta) + { + node.Value.Delta -= delta; + break; + } + if (node.Value.Delta > 0) + { + delta -= node.Value.Delta; + } + } + + var newNode = _free.First; + if (newNode != null) + { + _free.RemoveFirst(); + newNode.Value.Delta = delta; + newNode.Value.Action = action; + } + else + { + newNode = new LinkedListNode(new MachineEvent(delta, action)); + } + + if (node != null) + { + _used.AddBefore(node, newNode); + } + else + { + _used.AddLast(newNode); + } + } + + public int FindEvent(Action action) + { + int delta = 0; + + for (var node = _used.First; node != null; node = node.Next) + { + delta += node.Value.Delta; + if (object.ReferenceEquals(node.Value.Action, action)) // assumes delegate cached + { + return delta; + } + } + + return 0; + } + + public void HandleEvents(int delta) + { + var node = _used.First; + node.Value.Delta -= delta; + + while (node.Value.Delta <= 0) + { + node.Value.Action(); + RemoveEvent(node); + node = _used.First; + } + } + + private void RemoveEvent(LinkedListNode node) + { + if (node.Next != null) + { + node.Next.Value.Delta += node.Value.Delta; + } + + _used.Remove(node); + _free.AddFirst(node); // cache node; avoids garbage + } + + private LinkedList _used = new LinkedList(); + private LinkedList _free = new LinkedList(); + } +} diff --git a/Virtu/Memory.cs b/Virtu/Memory.cs index 683835f..85df58e 100644 --- a/Virtu/Memory.cs +++ b/Virtu/Memory.cs @@ -1,1738 +1,1738 @@ -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 -{ - public enum MonitorType { Unknown, Standard, Enhanced }; - - public sealed partial class Memory : MachineComponent - { - public Memory(Machine machine) : - base(machine) - { - WriteRamModeBankRegion = new Action[Video.ModeCount][][]; - for (int mode = 0; mode < Video.ModeCount; mode++) - { - WriteRamModeBankRegion[mode] = new Action[BankCount][] - { - new Action[RegionCount], new Action[RegionCount] - }; - } - WriteRamModeBankRegion[Video.Mode0][BankMain][Region0407] = WriteRamMode0MainRegion0407; - WriteRamModeBankRegion[Video.Mode0][BankMain][Region080B] = WriteRamMode0MainRegion080B; - WriteRamModeBankRegion[Video.Mode1][BankMain][Region0407] = WriteRamMode1MainRegion0407; - WriteRamModeBankRegion[Video.Mode1][BankMain][Region080B] = WriteRamMode1MainRegion080B; - WriteRamModeBankRegion[Video.Mode2][BankMain][Region0407] = WriteRamMode2MainRegion0407; - WriteRamModeBankRegion[Video.Mode2][BankMain][Region080B] = WriteRamMode2MainRegion080B; - WriteRamModeBankRegion[Video.Mode2][BankAux][Region0407] = WriteRamMode2AuxRegion0407; - WriteRamModeBankRegion[Video.Mode2][BankAux][Region080B] = WriteRamMode2AuxRegion080B; - WriteRamModeBankRegion[Video.Mode3][BankMain][Region0407] = WriteRamMode3MainRegion0407; - WriteRamModeBankRegion[Video.Mode3][BankMain][Region080B] = WriteRamMode3MainRegion080B; - WriteRamModeBankRegion[Video.Mode4][BankMain][Region0407] = WriteRamMode4MainRegion0407; - WriteRamModeBankRegion[Video.Mode4][BankMain][Region080B] = WriteRamMode4MainRegion080B; - WriteRamModeBankRegion[Video.Mode4][BankAux][Region0407] = WriteRamMode4AuxRegion0407; - WriteRamModeBankRegion[Video.Mode4][BankAux][Region080B] = WriteRamMode4AuxRegion080B; - WriteRamModeBankRegion[Video.Mode5][BankMain][Region203F] = WriteRamMode5MainRegion203F; - WriteRamModeBankRegion[Video.Mode5][BankMain][Region405F] = WriteRamMode5MainRegion405F; - WriteRamModeBankRegion[Video.Mode6][BankMain][Region0407] = WriteRamMode6MainRegion0407; - WriteRamModeBankRegion[Video.Mode6][BankMain][Region080B] = WriteRamMode6MainRegion080B; - WriteRamModeBankRegion[Video.Mode6][BankMain][Region203F] = WriteRamMode6MainRegion203F; - WriteRamModeBankRegion[Video.Mode6][BankMain][Region405F] = WriteRamMode6MainRegion405F; - WriteRamModeBankRegion[Video.Mode7][BankMain][Region0407] = WriteRamMode7MainRegion0407; - WriteRamModeBankRegion[Video.Mode7][BankMain][Region080B] = WriteRamMode7MainRegion080B; - WriteRamModeBankRegion[Video.Mode7][BankMain][Region203F] = WriteRamMode7MainRegion203F; - WriteRamModeBankRegion[Video.Mode7][BankMain][Region405F] = WriteRamMode7MainRegion405F; - WriteRamModeBankRegion[Video.Mode7][BankAux][Region0407] = WriteRamMode7AuxRegion0407; - WriteRamModeBankRegion[Video.Mode7][BankAux][Region080B] = WriteRamMode7AuxRegion080B; - WriteRamModeBankRegion[Video.Mode8][BankMain][Region0407] = WriteRamMode8MainRegion0407; - WriteRamModeBankRegion[Video.Mode8][BankMain][Region080B] = WriteRamMode8MainRegion080B; - WriteRamModeBankRegion[Video.Mode9][BankMain][Region0407] = WriteRamMode9MainRegion0407; - WriteRamModeBankRegion[Video.Mode9][BankMain][Region080B] = WriteRamMode9MainRegion080B; - WriteRamModeBankRegion[Video.Mode9][BankAux][Region0407] = WriteRamMode9AuxRegion0407; - WriteRamModeBankRegion[Video.Mode9][BankAux][Region080B] = WriteRamMode9AuxRegion080B; - WriteRamModeBankRegion[Video.ModeA][BankMain][Region0407] = WriteRamModeAMainRegion0407; - WriteRamModeBankRegion[Video.ModeA][BankMain][Region080B] = WriteRamModeAMainRegion080B; - WriteRamModeBankRegion[Video.ModeB][BankMain][Region0407] = WriteRamModeBMainRegion0407; - WriteRamModeBankRegion[Video.ModeB][BankMain][Region080B] = WriteRamModeBMainRegion080B; - WriteRamModeBankRegion[Video.ModeB][BankAux][Region0407] = WriteRamModeBAuxRegion0407; - WriteRamModeBankRegion[Video.ModeB][BankAux][Region080B] = WriteRamModeBAuxRegion080B; - WriteRamModeBankRegion[Video.ModeC][BankMain][Region203F] = WriteRamModeCMainRegion203F; - WriteRamModeBankRegion[Video.ModeC][BankMain][Region405F] = WriteRamModeCMainRegion405F; - WriteRamModeBankRegion[Video.ModeD][BankMain][Region203F] = WriteRamModeDMainRegion203F; - WriteRamModeBankRegion[Video.ModeD][BankMain][Region405F] = WriteRamModeDMainRegion405F; - WriteRamModeBankRegion[Video.ModeD][BankAux][Region203F] = WriteRamModeDAuxRegion203F; - WriteRamModeBankRegion[Video.ModeD][BankAux][Region405F] = WriteRamModeDAuxRegion405F; - WriteRamModeBankRegion[Video.ModeE][BankMain][Region0407] = WriteRamModeEMainRegion0407; - WriteRamModeBankRegion[Video.ModeE][BankMain][Region080B] = WriteRamModeEMainRegion080B; - WriteRamModeBankRegion[Video.ModeE][BankMain][Region203F] = WriteRamModeEMainRegion203F; - WriteRamModeBankRegion[Video.ModeE][BankMain][Region405F] = WriteRamModeEMainRegion405F; - WriteRamModeBankRegion[Video.ModeF][BankMain][Region0407] = WriteRamModeFMainRegion0407; - WriteRamModeBankRegion[Video.ModeF][BankMain][Region080B] = WriteRamModeFMainRegion080B; - WriteRamModeBankRegion[Video.ModeF][BankMain][Region203F] = WriteRamModeFMainRegion203F; - WriteRamModeBankRegion[Video.ModeF][BankMain][Region405F] = WriteRamModeFMainRegion405F; - WriteRamModeBankRegion[Video.ModeF][BankAux][Region0407] = WriteRamModeFAuxRegion0407; - 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() - { - _keyboard = Machine.Keyboard; - _gamePort = Machine.GamePort; - _cassette = Machine.Cassette; - _speaker = Machine.Speaker; - _video = Machine.Video; - _noSlotClock = Machine.NoSlotClock; - - StorageService.LoadResource("Roms/AppleIIe.rom", stream => - { - stream.SkipBlock(0x0100); - stream.ReadBlock(_romInternalRegionC1CF); - stream.ReadBlock(_romRegionD0DF); - stream.ReadBlock(_romRegionE0FF); - }); - - if ((ReadRomRegionE0FF(0xFBB3) == 0x06) && (ReadRomRegionE0FF(0xFBBF) == 0xC1)) - { - Monitor = MonitorType.Standard; - } - else if ((ReadRomRegionE0FF(0xFBB3) == 0x06) && (ReadRomRegionE0FF(0xFBBF) == 0x00) && (ReadRomRegionE0FF(0xFBC0) == 0xE0)) - { - Monitor = MonitorType.Enhanced; - } - } - - public override void Reset() // [7-3] - { - ResetState(State80Col | State80Store | StateAltChrSet | StateAltZP | StateBank1 | StateHRamRd | StateHRamPreWrt | StateHRamWrt | // HRamWrt' [5-23] - StateHires | StatePage2 | StateRamRd | StateRamWrt | StateIntCXRom | StateSlotC3Rom | StateIntC8Rom | StateAn0 | StateAn1 | StateAn2 | StateAn3); - SetState(StateDRes); // An3' -> DRes [8-20] - - MapRegion0001(); - MapRegion02BF(); - MapRegionC0CF(); - 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); - } - - 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) - { - int region = PageRegion[address >> 8]; - return ((address & 0xF000) != 0xC000) ? _regionRead[region][address - RegionBaseAddress[region]] : ReadIoRegionC0CF(address); - } - - public int ReadZeroPage(int address) - { - return _zeroPage[address]; - } - - public void Write(int address, int data) - { - int region = PageRegion[address >> 8]; - if (_writeRegion[region] == null) - { - _regionWrite[region][address - RegionBaseAddress[region]] = (byte)data; - } - else - { - _writeRegion[region](address, (byte)data); - } - } - - public void WriteZeroPage(int address, int data) - { - _zeroPage[address] = (byte)data; - } - #endregion - - #region Read Actions - private int ReadIoRegionC0CF(int address) - { - switch (address & 0xFF00) - { - case 0xC000: - return ReadIoRegionC0C0(address); - - case 0xC100: case 0xC200: case 0xC400: case 0xC500: case 0xC600: case 0xC700: - return ReadIoRegionC1C7(address); - - case 0xC300: - return ReadIoRegionC3C3(address); - - case 0xC800: case 0xC900: case 0xCA00: case 0xCB00: case 0xCC00: case 0xCD00: case 0xCE00: case 0xCF00: - return ReadIoRegionC8CF(address); - } - - return _video.ReadFloatingBus(); - } - - [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] - [SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode")] - private int ReadIoRegionC0C0(int address) - { - switch (address) - { - case 0xC000: case 0xC001: case 0xC002: case 0xC003: case 0xC004: case 0xC005: case 0xC006: case 0xC007: // [7-15] - case 0xC008: case 0xC009: case 0xC00A: case 0xC00B: case 0xC00C: case 0xC00D: case 0xC00E: case 0xC00F: - return SetBit7(_keyboard.Latch, _keyboard.Strobe); - - case 0xC010: - _keyboard.ResetStrobe(); - return SetBit7(_keyboard.Latch, _keyboard.IsAnyKeyDown); - - case 0xC011: - return SetBit7(_keyboard.Latch, !IsHighRamBank1); // Bank1' [5-22] - - case 0xC012: - return SetBit7(_keyboard.Latch, IsHighRamRead); - - case 0xC013: - return SetBit7(_keyboard.Latch, IsRamReadAux); - - case 0xC014: - return SetBit7(_keyboard.Latch, IsRamWriteAux); - - case 0xC015: - return SetBit7(_keyboard.Latch, IsRomC1CFInternal); - - case 0xC016: - return SetBit7(_keyboard.Latch, IsZeroPageAux); - - case 0xC017: - return SetBit7(_keyboard.Latch, IsRomC3C3External); - - case 0xC018: - return SetBit7(_keyboard.Latch, Is80Store); - - case 0xC019: - return SetBit7(_keyboard.Latch, !_video.IsVBlank); // Vbl' [7-5] - - case 0xC01A: - return SetBit7(_keyboard.Latch, IsText); - - case 0xC01B: - return SetBit7(_keyboard.Latch, IsMixed); - - case 0xC01C: - return SetBit7(_keyboard.Latch, IsPage2); - - case 0xC01D: - return SetBit7(_keyboard.Latch, IsHires); - - case 0xC01E: - return SetBit7(_keyboard.Latch, IsCharSetAlternate); - - case 0xC01F: - return SetBit7(_keyboard.Latch, Is80Columns); - - case 0xC020: case 0xC021: case 0xC022: case 0xC023: case 0xC024: case 0xC025: case 0xC026: case 0xC027: // [7-8] - case 0xC028: case 0xC029: case 0xC02A: case 0xC02B: case 0xC02C: case 0xC02D: case 0xC02E: case 0xC02F: - _cassette.ToggleOutput(); - break; - - case 0xC030: case 0xC031: case 0xC032: case 0xC033: case 0xC034: case 0xC035: case 0xC036: case 0xC037: // [7-9] - case 0xC038: case 0xC039: case 0xC03A: case 0xC03B: case 0xC03C: case 0xC03D: case 0xC03E: case 0xC03F: - _speaker.ToggleOutput(); - break; - - case 0xC040: case 0xC041: case 0xC042: case 0xC043: case 0xC044: case 0xC045: case 0xC046: case 0xC047: // [2-18] - case 0xC048: case 0xC049: case 0xC04A: case 0xC04B: case 0xC04C: case 0xC04D: case 0xC04E: case 0xC04F: - break; - - case 0xC050: case 0xC051: - SetText(TestBit(address, 0)); - break; - - case 0xC052: case 0xC053: - SetMixed(TestBit(address, 0)); - break; - - case 0xC054: case 0xC055: - SetPage2(TestBit(address, 0)); - break; - - case 0xC056: case 0xC057: - SetHires(TestBit(address, 0)); - break; - - case 0xC058: case 0xC059: - SetAnnunciator0(TestBit(address, 0)); - break; - - case 0xC05A: case 0xC05B: - SetAnnunciator1(TestBit(address, 0)); - break; - - case 0xC05C: case 0xC05D: - SetAnnunciator2(TestBit(address, 0)); - break; - - case 0xC05E: case 0xC05F: - SetAnnunciator3(TestBit(address, 0)); - SetDoubleRes(!TestBit(address, 0)); - break; - - case 0xC060: case 0xC068: // [2-18, 7-5] - return SetBit7(_video.ReadFloatingBus(), _cassette.ReadInput()); // [7-8] - - case 0xC061: case 0xC069: - return SetBit7(_video.ReadFloatingBus(), _gamePort.ReadButton0()); - - case 0xC062: case 0xC06A: - return SetBit7(_video.ReadFloatingBus(), _gamePort.ReadButton1()); - - case 0xC063: case 0xC06B: - return SetBit7(_video.ReadFloatingBus(), _gamePort.ReadButton2()); - - case 0xC064: case 0xC06C: - return SetBit7(_video.ReadFloatingBus(), _gamePort.Paddle0Strobe); - - case 0xC065: case 0xC06D: - return SetBit7(_video.ReadFloatingBus(), _gamePort.Paddle1Strobe); - - case 0xC066: case 0xC06E: - return SetBit7(_video.ReadFloatingBus(), _gamePort.Paddle2Strobe); - - case 0xC067: case 0xC06F: - return SetBit7(_video.ReadFloatingBus(), _gamePort.Paddle3Strobe); - - case 0xC070: case 0xC071: case 0xC072: case 0xC073: case 0xC074: case 0xC075: case 0xC076: case 0xC077: - case 0xC078: case 0xC079: case 0xC07A: case 0xC07B: case 0xC07C: case 0xC07D: case 0xC07E: case 0xC07F: - _gamePort.TriggerTimers(); - break; - - case 0xC080: case 0xC081: case 0xC082: case 0xC083: case 0xC084: case 0xC085: case 0xC086: case 0xC087: // slot0 [5-23] - case 0xC088: case 0xC089: case 0xC08A: case 0xC08B: case 0xC08C: case 0xC08D: case 0xC08E: case 0xC08F: - SetHighRam(address, true); - break; - - case 0xC090: case 0xC091: case 0xC092: case 0xC093: case 0xC094: case 0xC095: case 0xC096: case 0xC097: // slot1 - case 0xC098: case 0xC099: case 0xC09A: case 0xC09B: case 0xC09C: case 0xC09D: case 0xC09E: case 0xC09F: - return Machine.Slot1.ReadIoRegionC0C0(address); - - case 0xC0A0: case 0xC0A1: case 0xC0A2: case 0xC0A3: case 0xC0A4: case 0xC0A5: case 0xC0A6: case 0xC0A7: // slot2 - case 0xC0A8: case 0xC0A9: case 0xC0AA: case 0xC0AB: case 0xC0AC: case 0xC0AD: case 0xC0AE: case 0xC0AF: - return Machine.Slot2.ReadIoRegionC0C0(address); - - case 0xC0B0: case 0xC0B1: case 0xC0B2: case 0xC0B3: case 0xC0B4: case 0xC0B5: case 0xC0B6: case 0xC0B7: // slot3 - case 0xC0B8: case 0xC0B9: case 0xC0BA: case 0xC0BB: case 0xC0BC: case 0xC0BD: case 0xC0BE: case 0xC0BF: - return Machine.Slot3.ReadIoRegionC0C0(address); - - case 0xC0C0: case 0xC0C1: case 0xC0C2: case 0xC0C3: case 0xC0C4: case 0xC0C5: case 0xC0C6: case 0xC0C7: // slot4 - case 0xC0C8: case 0xC0C9: case 0xC0CA: case 0xC0CB: case 0xC0CC: case 0xC0CD: case 0xC0CE: case 0xC0CF: - return Machine.Slot4.ReadIoRegionC0C0(address); - - case 0xC0D0: case 0xC0D1: case 0xC0D2: case 0xC0D3: case 0xC0D4: case 0xC0D5: case 0xC0D6: case 0xC0D7: // slot5 - case 0xC0D8: case 0xC0D9: case 0xC0DA: case 0xC0DB: case 0xC0DC: case 0xC0DD: case 0xC0DE: case 0xC0DF: - return Machine.Slot5.ReadIoRegionC0C0(address); - - case 0xC0E0: case 0xC0E1: case 0xC0E2: case 0xC0E3: case 0xC0E4: case 0xC0E5: case 0xC0E6: case 0xC0E7: // slot6 - case 0xC0E8: case 0xC0E9: case 0xC0EA: case 0xC0EB: case 0xC0EC: case 0xC0ED: case 0xC0EE: case 0xC0EF: - return Machine.Slot6.ReadIoRegionC0C0(address); - - case 0xC0F0: case 0xC0F1: case 0xC0F2: case 0xC0F3: case 0xC0F4: case 0xC0F5: case 0xC0F6: case 0xC0F7: // slot7 - case 0xC0F8: case 0xC0F9: case 0xC0FA: case 0xC0FB: case 0xC0FC: case 0xC0FD: case 0xC0FE: case 0xC0FF: - return Machine.Slot7.ReadIoRegionC0C0(address); - - default: - throw new ArgumentOutOfRangeException("address"); - } - - return _video.ReadFloatingBus(); - } - - private int ReadIoRegionC1C7(int address) - { - _slotRegionC8CF = (address >> 8) & 0x07; - return IsRomC1CFInternal ? _romInternalRegionC1CF[address - 0xC100] : Machine.Slots[_slotRegionC8CF].ReadIoRegionC1C7(address); - } - - private int ReadIoRegionC3C3(int address) - { - _slotRegionC8CF = 3; - if (!IsRomC3C3External) - { - SetRomC8CF(true); // $C3XX sets IntC8Rom; inhibits I/O Strobe' [5-28, 7-21] - } - return (IsRomC1CFInternal || !IsRomC3C3External) ? _noSlotClock.Read(address, _romInternalRegionC1CF[address - 0xC100]) : Machine.Slot3.ReadIoRegionC1C7(address); - } - - private int ReadIoRegionC8CF(int address) - { - if (address == 0xCFFF) - { - SetRomC8CF(false); // $CFFF resets IntC8Rom [5-28, 7-21] - } - return (IsRomC1CFInternal || IsRomC8CFInternal) ? _noSlotClock.Read(address, _romInternalRegionC1CF[address - 0xC100]) : Machine.Slots[_slotRegionC8CF].ReadIoRegionC8CF(address); - } - - [SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow", MessageId = "address-512")] - public int ReadRamMainRegion02BF(int address) - { - return _ramMainRegion02BF[address - 0x0200]; - } - - [SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow", MessageId = "address-512")] - public int ReadRamAuxRegion02BF(int address) - { - return _ramAuxRegion02BF[address - 0x0200]; - } - - [SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow", MessageId = "address-57344")] - public int ReadRomRegionE0FF(int address) - { - return _romRegionE0FF[address - 0xE000]; - } - #endregion - - #region Write Actions - [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] - [SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode")] - private void WriteIoRegionC0C0(int address, byte data) - { - switch (address) - { - case 0xC000: case 0xC001: // [5-22] - Set80Store(TestBit(address, 0)); - break; - - case 0xC002: case 0xC003: - SetRamRead(TestBit(address, 0)); - break; - - case 0xC004: case 0xC005: - SetRamWrite(TestBit(address, 0)); - break; - - case 0xC006: case 0xC007: - SetRomC1CF(TestBit(address, 0)); - break; - - case 0xC008: case 0xC009: - SetZeroPage(TestBit(address, 0)); - break; - - case 0xC00A: case 0xC00B: - SetRomC3C3(TestBit(address, 0)); - break; - - case 0xC00C: case 0xC00D: // [7-5] - Set80Columns(TestBit(address, 0)); - break; - - case 0xC00E: case 0xC00F: - SetCharSet(TestBit(address, 0)); - break; - - case 0xC010: case 0xC011: case 0xC012: case 0xC013: case 0xC014: case 0xC015: case 0xC016: case 0xC017: // [7-15] - case 0xC018: case 0xC019: case 0xC01A: case 0xC01B: case 0xC01C: case 0xC01D: case 0xC01E: case 0xC01F: - _keyboard.ResetStrobe(); - break; - - case 0xC020: case 0xC021: case 0xC022: case 0xC023: case 0xC024: case 0xC025: case 0xC026: case 0xC027: // [7-8] - case 0xC028: case 0xC029: case 0xC02A: case 0xC02B: case 0xC02C: case 0xC02D: case 0xC02E: case 0xC02F: - _cassette.ToggleOutput(); - break; - - case 0xC030: case 0xC031: case 0xC032: case 0xC033: case 0xC034: case 0xC035: case 0xC036: case 0xC037: // [7-9] - case 0xC038: case 0xC039: case 0xC03A: case 0xC03B: case 0xC03C: case 0xC03D: case 0xC03E: case 0xC03F: - _speaker.ToggleOutput(); - break; - - case 0xC040: case 0xC041: case 0xC042: case 0xC043: case 0xC044: case 0xC045: case 0xC046: case 0xC047: // [2-18] - case 0xC048: case 0xC049: case 0xC04A: case 0xC04B: case 0xC04C: case 0xC04D: case 0xC04E: case 0xC04F: - break; - - case 0xC050: case 0xC051: - SetText(TestBit(address, 0)); - break; - - case 0xC052: case 0xC053: - SetMixed(TestBit(address, 0)); - break; - - case 0xC054: case 0xC055: - SetPage2(TestBit(address, 0)); - break; - - case 0xC056: case 0xC057: - SetHires(TestBit(address, 0)); - break; - - case 0xC058: case 0xC059: - SetAnnunciator0(TestBit(address, 0)); - break; - - case 0xC05A: case 0xC05B: - SetAnnunciator1(TestBit(address, 0)); - break; - - case 0xC05C: case 0xC05D: - SetAnnunciator2(TestBit(address, 0)); - break; - - case 0xC05E: case 0xC05F: - SetAnnunciator3(TestBit(address, 0)); - SetDoubleRes(!TestBit(address, 0)); - break; - - case 0xC060: case 0xC061: case 0xC062: case 0xC063: case 0xC064: case 0xC065: case 0xC066: case 0xC067: // [2-18, 7-5] - case 0xC068: case 0xC069: case 0xC06A: case 0xC06B: case 0xC06C: case 0xC06D: case 0xC06E: case 0xC06F: - break; - - case 0xC070: case 0xC071: case 0xC072: case 0xC073: case 0xC074: case 0xC075: case 0xC076: case 0xC077: - case 0xC078: case 0xC079: case 0xC07A: case 0xC07B: case 0xC07C: case 0xC07D: case 0xC07E: case 0xC07F: - _gamePort.TriggerTimers(); - break; - - case 0xC080: case 0xC081: case 0xC082: case 0xC083: case 0xC084: case 0xC085: case 0xC086: case 0xC087: // slot0 [5-23] - case 0xC088: case 0xC089: case 0xC08A: case 0xC08B: case 0xC08C: case 0xC08D: case 0xC08E: case 0xC08F: - SetHighRam(address, false); - break; - - case 0xC090: case 0xC091: case 0xC092: case 0xC093: case 0xC094: case 0xC095: case 0xC096: case 0xC097: // slot1 - case 0xC098: case 0xC099: case 0xC09A: case 0xC09B: case 0xC09C: case 0xC09D: case 0xC09E: case 0xC09F: - Machine.Slot1.WriteIoRegionC0C0(address, data); - break; - - case 0xC0A0: case 0xC0A1: case 0xC0A2: case 0xC0A3: case 0xC0A4: case 0xC0A5: case 0xC0A6: case 0xC0A7: // slot2 - case 0xC0A8: case 0xC0A9: case 0xC0AA: case 0xC0AB: case 0xC0AC: case 0xC0AD: case 0xC0AE: case 0xC0AF: - Machine.Slot2.WriteIoRegionC0C0(address, data); - break; - - case 0xC0B0: case 0xC0B1: case 0xC0B2: case 0xC0B3: case 0xC0B4: case 0xC0B5: case 0xC0B6: case 0xC0B7: // slot3 - case 0xC0B8: case 0xC0B9: case 0xC0BA: case 0xC0BB: case 0xC0BC: case 0xC0BD: case 0xC0BE: case 0xC0BF: - Machine.Slot3.WriteIoRegionC0C0(address, data); - break; - - case 0xC0C0: case 0xC0C1: case 0xC0C2: case 0xC0C3: case 0xC0C4: case 0xC0C5: case 0xC0C6: case 0xC0C7: // slot4 - case 0xC0C8: case 0xC0C9: case 0xC0CA: case 0xC0CB: case 0xC0CC: case 0xC0CD: case 0xC0CE: case 0xC0CF: - Machine.Slot4.WriteIoRegionC0C0(address, data); - break; - - case 0xC0D0: case 0xC0D1: case 0xC0D2: case 0xC0D3: case 0xC0D4: case 0xC0D5: case 0xC0D6: case 0xC0D7: // slot5 - case 0xC0D8: case 0xC0D9: case 0xC0DA: case 0xC0DB: case 0xC0DC: case 0xC0DD: case 0xC0DE: case 0xC0DF: - Machine.Slot5.WriteIoRegionC0C0(address, data); - break; - - case 0xC0E0: case 0xC0E1: case 0xC0E2: case 0xC0E3: case 0xC0E4: case 0xC0E5: case 0xC0E6: case 0xC0E7: // slot6 - case 0xC0E8: case 0xC0E9: case 0xC0EA: case 0xC0EB: case 0xC0EC: case 0xC0ED: case 0xC0EE: case 0xC0EF: - Machine.Slot6.WriteIoRegionC0C0(address, data); - break; - - case 0xC0F0: case 0xC0F1: case 0xC0F2: case 0xC0F3: case 0xC0F4: case 0xC0F5: case 0xC0F6: case 0xC0F7: // slot7 - case 0xC0F8: case 0xC0F9: case 0xC0FA: case 0xC0FB: case 0xC0FC: case 0xC0FD: case 0xC0FE: case 0xC0FF: - Machine.Slot7.WriteIoRegionC0C0(address, data); - break; - - default: - throw new ArgumentOutOfRangeException("address"); - } - } - - private void WriteIoRegionC1C7(int address, byte data) - { - _slotRegionC8CF = (address >> 8) & 0x07; - if (!IsRomC1CFInternal) - { - Machine.Slots[_slotRegionC8CF].WriteIoRegionC1C7(address, data); - } - } - - private void WriteIoRegionC3C3(int address, byte data) - { - _slotRegionC8CF = 3; - if (!IsRomC3C3External) - { - SetRomC8CF(true); // $C3XX sets IntC8Rom; inhibits I/O Strobe' [5-28, 7-21] - } - if (IsRomC1CFInternal || !IsRomC3C3External) - { - _noSlotClock.Write(address); - } - else - { - Machine.Slot3.WriteIoRegionC1C7(address, data); - } - } - - private void WriteIoRegionC8CF(int address, byte data) - { - if (address == 0xCFFF) - { - SetRomC8CF(false); // $CFFF resets IntC8Rom [5-28, 7-21] - } - if (IsRomC1CFInternal || IsRomC8CFInternal) - { - _noSlotClock.Write(address); - } - else - { - Machine.Slots[_slotRegionC8CF].WriteIoRegionC8CF(address, data); - } - } - - private void WriteRamMode0MainRegion0407(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0400); // lores page1 - } - } - - private void WriteRamMode0MainRegion080B(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0800); // lores page2 - } - } - - private void WriteRamMode1MainRegion0407(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0400); // text40 page1 - } - } - - private void WriteRamMode1MainRegion080B(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0800); // text40 page2 - } - } - - private void WriteRamMode2MainRegion0407(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0400); // text80 page1 - } - } - - private void WriteRamMode2MainRegion080B(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0800); // text80 page2 - } - } - - private void WriteRamMode2AuxRegion0407(int address, byte data) - { - if (_ramAuxRegion02BF[address - 0x0200] != data) - { - _ramAuxRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0400); // text80 page1 - } - } - - private void WriteRamMode2AuxRegion080B(int address, byte data) - { - if (_ramAuxRegion02BF[address - 0x0200] != data) - { - _ramAuxRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0800); // text80 page2 - } - } - - private void WriteRamMode3MainRegion0407(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0400); // lores & text40 page1 - } - } - - private void WriteRamMode3MainRegion080B(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0800); // lores & text40 page2 - } - } - - private void WriteRamMode4MainRegion0407(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0400); // lores & text80 page1 - } - } - - private void WriteRamMode4MainRegion080B(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0800); // lores & text80 page2 - } - } - - private void WriteRamMode4AuxRegion0407(int address, byte data) - { - if (_ramAuxRegion02BF[address - 0x0200] != data) - { - _ramAuxRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixedText(address - 0x0400); // [lores &] text80 page1 - } - } - - private void WriteRamMode4AuxRegion080B(int address, byte data) - { - if (_ramAuxRegion02BF[address - 0x0200] != data) - { - _ramAuxRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixedText(address - 0x0800); // [lores &] text80 page2 - } - } - - private void WriteRamMode5MainRegion203F(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x2000); // hires page1 - } - } - - private void WriteRamMode5MainRegion405F(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x4000); // hires page2 - } - } - - private void WriteRamMode6MainRegion0407(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixedText(address - 0x0400); // [hires &] text40 page1 - } - } - - private void WriteRamMode6MainRegion080B(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixedText(address - 0x0800); // [hires &] text40 page2 - } - } - - private void WriteRamMode6MainRegion203F(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixed(address - 0x2000); // hires [& text40] page1 - } - } - - private void WriteRamMode6MainRegion405F(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixed(address - 0x4000); // hires [& text40] page2 - } - } - - private void WriteRamMode7MainRegion0407(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixedText(address - 0x0400); // [hires &] text80 page1 - } - } - - private void WriteRamMode7MainRegion080B(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixedText(address - 0x0800); // [hires &] text80 page2 - } - } - - private void WriteRamMode7MainRegion203F(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixed(address - 0x2000); // hires [& text80] page1 - } - } - - private void WriteRamMode7MainRegion405F(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixed(address - 0x4000); // hires [& text80] page2 - } - } - - private void WriteRamMode7AuxRegion0407(int address, byte data) - { - if (_ramAuxRegion02BF[address - 0x0200] != data) - { - _ramAuxRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixedText(address - 0x0400); // [hires &] text80 page1 - } - } - - private void WriteRamMode7AuxRegion080B(int address, byte data) - { - if (_ramAuxRegion02BF[address - 0x0200] != data) - { - _ramAuxRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixedText(address - 0x0800); // [hires &] text80 page2 - } - } - - private void WriteRamMode8MainRegion0407(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0400); // 7mlores page1 - } - } - - private void WriteRamMode8MainRegion080B(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0800); // 7mlores page2 - } - } - - private void WriteRamMode9MainRegion0407(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0400); // dlores page1 - } - } - - private void WriteRamMode9MainRegion080B(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0800); // dlores page2 - } - } - - private void WriteRamMode9AuxRegion0407(int address, byte data) - { - if (_ramAuxRegion02BF[address - 0x0200] != data) - { - _ramAuxRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0400); // dlores page1 - } - } - - private void WriteRamMode9AuxRegion080B(int address, byte data) - { - if (_ramAuxRegion02BF[address - 0x0200] != data) - { - _ramAuxRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0800); // dlores page2 - } - } - - private void WriteRamModeAMainRegion0407(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0400); // 7mlores & text40 page1 - } - } - - private void WriteRamModeAMainRegion080B(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0800); // 7mlores & text40 page2 - } - } - - private void WriteRamModeBMainRegion0407(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0400); // dlores & text80 page1 - } - } - - private void WriteRamModeBMainRegion080B(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0800); // dlores & text80 page2 - } - } - - private void WriteRamModeBAuxRegion0407(int address, byte data) - { - if (_ramAuxRegion02BF[address - 0x0200] != data) - { - _ramAuxRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0400); // dlores & text80 page1 - } - } - - private void WriteRamModeBAuxRegion080B(int address, byte data) - { - if (_ramAuxRegion02BF[address - 0x0200] != data) - { - _ramAuxRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x0800); // dlores & text80 page2 - } - } - - private void WriteRamModeCMainRegion203F(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x2000); // ndhires page1 - } - } - - private void WriteRamModeCMainRegion405F(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x4000); // ndhires page2 - } - } - - private void WriteRamModeDMainRegion203F(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x2000); // dhires page1 - } - } - - private void WriteRamModeDMainRegion405F(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x4000); // dhires page2 - } - } - - private void WriteRamModeDAuxRegion203F(int address, byte data) - { - if (_ramAuxRegion02BF[address - 0x0200] != data) - { - _ramAuxRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x2000); // dhires page1 - } - } - - private void WriteRamModeDAuxRegion405F(int address, byte data) - { - if (_ramAuxRegion02BF[address - 0x0200] != data) - { - _ramAuxRegion02BF[address - 0x0200] = data; - _video.DirtyCell(address - 0x4000); // dhires page2 - } - } - - private void WriteRamModeEMainRegion0407(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixedText(address - 0x0400); // [ndhires &] text40 page1 - } - } - - private void WriteRamModeEMainRegion080B(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixedText(address - 0x0800); // [ndhires &] text40 page2 - } - } - - private void WriteRamModeEMainRegion203F(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixed(address - 0x2000); // ndhires [& text40] page1 - } - } - - private void WriteRamModeEMainRegion405F(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixed(address - 0x4000); // ndhires [& text40] page2 - } - } - - private void WriteRamModeFMainRegion0407(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixedText(address - 0x0400); // [dhires &] text80 page1 - } - } - - private void WriteRamModeFMainRegion080B(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixedText(address - 0x0800); // [dhires &] text80 page2 - } - } - - private void WriteRamModeFMainRegion203F(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixed(address - 0x2000); // dhires [& text80] page1 - } - } - - private void WriteRamModeFMainRegion405F(int address, byte data) - { - if (_ramMainRegion02BF[address - 0x0200] != data) - { - _ramMainRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixed(address - 0x4000); // dhires [& text80] page2 - } - } - - private void WriteRamModeFAuxRegion0407(int address, byte data) - { - if (_ramAuxRegion02BF[address - 0x0200] != data) - { - _ramAuxRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixedText(address - 0x0400); // [dhires &] text80 page1 - } - } - - private void WriteRamModeFAuxRegion080B(int address, byte data) - { - if (_ramAuxRegion02BF[address - 0x0200] != data) - { - _ramAuxRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixedText(address - 0x0800); // [dhires &] text80 page2 - } - } - - private void WriteRamModeFAuxRegion203F(int address, byte data) - { - if (_ramAuxRegion02BF[address - 0x0200] != data) - { - _ramAuxRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixed(address - 0x2000); // dhires [& text80] page1 - } - } - - private void WriteRamModeFAuxRegion405F(int address, byte data) - { - if (_ramAuxRegion02BF[address - 0x0200] != data) - { - _ramAuxRegion02BF[address - 0x0200] = data; - _video.DirtyCellMixed(address - 0x4000); // dhires [& text80] page2 - } - } - - private void WriteRomRegionD0FF(int address, byte data) - { - } - #endregion - - #region Softswitch Actions - private void MapRegion0001() - { - if (!IsZeroPageAux) - { - _regionRead[Region0001] = _ramMainRegion0001; - _regionWrite[Region0001] = _ramMainRegion0001; - _zeroPage = _ramMainRegion0001; - } - else - { - _regionRead[Region0001] = _ramAuxRegion0001; - _regionWrite[Region0001] = _ramAuxRegion0001; - _zeroPage = _ramAuxRegion0001; - } - _writeRegion[Region0001] = null; - } - - private void MapRegion02BF() - { - if (!IsRamReadAux) - { - _regionRead[Region02BF] = _ramMainRegion02BF; - _regionRead[Region080B] = _ramMainRegion02BF; - _regionRead[Region405F] = _ramMainRegion02BF; - } - else - { - _regionRead[Region02BF] = _ramAuxRegion02BF; - _regionRead[Region080B] = _ramAuxRegion02BF; - _regionRead[Region405F] = _ramAuxRegion02BF; - } - int mode = VideoMode; - if (!IsRamWriteAux) - { - _regionWrite[Region02BF] = _ramMainRegion02BF; - _regionWrite[Region080B] = _ramMainRegion02BF; - _regionWrite[Region405F] = _ramMainRegion02BF; - _writeRegion[Region02BF] = null; - _writeRegion[Region080B] = WriteRamModeBankRegion[mode][BankMain][Region080B]; - _writeRegion[Region405F] = WriteRamModeBankRegion[mode][BankMain][Region405F]; - } - else - { - _regionWrite[Region02BF] = _ramAuxRegion02BF; - _regionWrite[Region080B] = _ramAuxRegion02BF; - _regionWrite[Region405F] = _ramAuxRegion02BF; - _writeRegion[Region02BF] = null; - _writeRegion[Region080B] = WriteRamModeBankRegion[mode][BankAux][Region080B]; - _writeRegion[Region405F] = WriteRamModeBankRegion[mode][BankAux][Region405F]; - } - MapRegion0407(); - MapRegion203F(); - } - - private void MapRegion0407() - { - if (!IsRamReadAuxRegion0407) - { - _regionRead[Region0407] = _ramMainRegion02BF; - } - else - { - _regionRead[Region0407] = _ramAuxRegion02BF; - } - int mode = VideoMode; - if (!IsRamWriteAuxRegion0407) - { - _regionWrite[Region0407] = _ramMainRegion02BF; - _writeRegion[Region0407] = WriteRamModeBankRegion[mode][BankMain][Region0407]; - } - else - { - _regionWrite[Region0407] = _ramAuxRegion02BF; - _writeRegion[Region0407] = WriteRamModeBankRegion[mode][BankAux][Region0407]; - } - } - - private void MapRegion203F() - { - if (!IsRamReadAuxRegion203F) - { - _regionRead[Region203F] = _ramMainRegion02BF; - } - else - { - _regionRead[Region203F] = _ramAuxRegion02BF; - } - int mode = VideoMode; - if (!IsRamWriteAuxRegion203F) - { - _regionWrite[Region203F] = _ramMainRegion02BF; - _writeRegion[Region203F] = WriteRamModeBankRegion[mode][BankMain][Region203F]; - } - else - { - _regionWrite[Region203F] = _ramAuxRegion02BF; - _writeRegion[Region203F] = WriteRamModeBankRegion[mode][BankAux][Region203F]; - } - } - - private void MapRegionC0CF() - { - _regionRead[RegionC0C0] = null; - if (IsRomC1CFInternal) - { - _regionRead[RegionC1C7] = _romInternalRegionC1CF; - _regionRead[RegionC3C3] = _romInternalRegionC1CF; - _regionRead[RegionC8CF] = _romInternalRegionC1CF; - } - else - { - _regionRead[RegionC1C7] = _romExternalRegionC1CF; - _regionRead[RegionC3C3] = IsRomC3C3External ? _romExternalRegionC1CF : _romInternalRegionC1CF; - _regionRead[RegionC8CF] = !IsRomC8CFInternal ? _romExternalRegionC1CF : _romInternalRegionC1CF; - } - _regionWrite[RegionC0C0] = null; - _regionWrite[RegionC1C7] = null; - _regionWrite[RegionC3C3] = null; - _regionWrite[RegionC8CF] = null; - _writeRegion[RegionC0C0] = _writeIoRegionC0C0; - _writeRegion[RegionC1C7] = _writeIoRegionC1C7; - _writeRegion[RegionC3C3] = _writeIoRegionC3C3; - _writeRegion[RegionC8CF] = _writeIoRegionC8CF; - } - - private void MapRegionD0FF() - { - if (IsHighRamRead) - { - if (!IsHighRamAux) - { - _regionRead[RegionD0DF] = IsHighRamBank1 ? _ramMainBank1RegionD0DF : _ramMainBank2RegionD0DF; - _regionRead[RegionE0FF] = _ramMainRegionE0FF; - } - else - { - _regionRead[RegionD0DF] = IsHighRamBank1 ? _ramAuxBank1RegionD0DF : _ramAuxBank2RegionD0DF; - _regionRead[RegionE0FF] = _ramAuxRegionE0FF; - } - } - else - { - _regionRead[RegionD0DF] = _romRegionD0DF; - _regionRead[RegionE0FF] = _romRegionE0FF; - } - if (IsHighRamWrite) - { - if (!IsHighRamAux) - { - _regionWrite[RegionD0DF] = IsHighRamBank1 ? _ramMainBank1RegionD0DF : _ramMainBank2RegionD0DF; - _regionWrite[RegionE0FF] = _ramMainRegionE0FF; - } - else - { - _regionWrite[RegionD0DF] = IsHighRamBank1 ? _ramAuxBank1RegionD0DF : _ramAuxBank2RegionD0DF; - _regionWrite[RegionE0FF] = _ramAuxRegionE0FF; - } - _writeRegion[RegionD0DF] = null; - _writeRegion[RegionE0FF] = null; - } - else - { - _regionWrite[RegionD0DF] = null; - _regionWrite[RegionE0FF] = null; - _writeRegion[RegionD0DF] = _writeRomRegionD0FF; - _writeRegion[RegionE0FF] = _writeRomRegionD0FF; - } - } - - private void Set80Columns(bool value) - { - if (!TestState(State80Col, value)) - { - SetState(State80Col, value); - MapRegion02BF(); - _video.DirtyScreen(); - } - } - - private void Set80Store(bool value) - { - if (!TestState(State80Store, value)) - { - SetState(State80Store, value); - if (IsPage2) // [5-7, 8-19] - { - MapRegion02BF(); - _video.DirtyScreen(); - } - else - { - MapRegion0407(); - MapRegion203F(); - } - } - } - - private void SetAnnunciator0(bool value) - { - SetState(StateAn0, value); - } - - private void SetAnnunciator1(bool value) - { - SetState(StateAn1, value); - } - - private void SetAnnunciator2(bool value) - { - SetState(StateAn2, value); - } - - private void SetAnnunciator3(bool value) - { - SetState(StateAn3, value); - } - - private void SetCharSet(bool value) - { - if (!TestState(StateAltChrSet, value)) - { - SetState(StateAltChrSet, value); - _video.SetCharSet(); - } - } - - private void SetDoubleRes(bool value) - { - if (!TestState(StateDRes, value)) - { - SetState(StateDRes, value); - MapRegion02BF(); - _video.DirtyScreen(); - } - } - - private void SetHighRam(int address, bool isRead) - { - SetState(StateBank1, TestBit(address, 3)); // A3 [5-22] - SetState(StateHRamRd, TestMask(address, 0x3, 0x3) || TestMask(address, 0x3, 0x0)); // A0.A1+A0'.A1' [5-23] (5-22 misprint) - if (TestBit(address, 0)) // A0 [5-23] - { - if (isRead && TestState(StateHRamPreWrt)) - { - ResetState(StateHRamWrt); // HRamWrt' [5-23] - } - } - else - { - SetState(StateHRamWrt); - } - SetState(StateHRamPreWrt, isRead && TestBit(address, 0)); // A0.R/W' [5-22] - MapRegionD0FF(); - } - - private void SetHires(bool value) - { - if (!TestState(StateHires, value)) - { - SetState(StateHires, value); - if (!Is80Store) // [5-7, 8-19] - { - MapRegion02BF(); - _video.DirtyScreen(); - } - else - { - MapRegion203F(); - } - } - } - - private void SetMixed(bool value) - { - if (!TestState(StateMixed, value)) - { - SetState(StateMixed, value); - MapRegion02BF(); - _video.DirtyScreen(); - } - } - - private void SetPage2(bool value) - { - if (!TestState(StatePage2, value)) - { - SetState(StatePage2, value); - if (!Is80Store) // [5-7, 8-19] - { - MapRegion02BF(); - _video.DirtyScreen(); - } - else - { - MapRegion0407(); - MapRegion203F(); - } - } - } - - private void SetRamRead(bool value) - { - if (!TestState(StateRamRd, value)) - { - SetState(StateRamRd, value); - MapRegion02BF(); - } - } - - private void SetRamWrite(bool value) - { - if (!TestState(StateRamWrt, value)) - { - SetState(StateRamWrt, value); - MapRegion02BF(); - } - } - - private void SetRomC1CF(bool value) - { - if (!TestState(StateIntCXRom, value)) - { - SetState(StateIntCXRom, value); - MapRegionC0CF(); - } - } - - private void SetRomC3C3(bool value) - { - if (!TestState(StateSlotC3Rom, value)) - { - SetState(StateSlotC3Rom, value); - MapRegionC0CF(); - } - } - - private void SetRomC8CF(bool value) - { - if (!TestState(StateIntC8Rom, value)) - { - SetState(StateIntC8Rom, value); - MapRegionC0CF(); - } - } - - private void SetText(bool value) - { - if (!TestState(StateText, value)) - { - SetState(StateText, value); - MapRegion02BF(); - _video.DirtyScreen(); - } - } - - private void SetZeroPage(bool value) - { - if (!TestState(StateAltZP, value)) - { - SetState(StateAltZP, value); - MapRegion0001(); - MapRegionD0FF(); - } - } - #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); - _ramMainRegion02BF[0x03F3 - 0x0200] = (byte)(address >> 8); - _ramMainRegion02BF[0x03F4 - 0x0200] = (byte)((address >> 8) ^ 0xA5); - } - - private static int SetBit7(int data, bool value) - { - return value ? (data | 0x80) : (data & 0x7F); - } - - private static bool TestBit(int data, int bit) - { - return ((data & (0x1 << bit)) != 0x0); - } - - private static bool TestMask(int data, int mask, int value) - { - return ((data & mask) == value); - } - - private void ResetState(int mask) - { - _state &= ~mask; - } - - private void SetState(int mask) - { - _state |= mask; - } - - private void SetState(int mask, bool value) - { - if (value) - { - _state |= mask; - } - else - { - _state &= ~mask; - } - } - - private bool TestState(int mask) - { - return ((_state & mask) != 0x0); - } - - private bool TestState(int mask, bool value) - { - return (((_state & mask) != 0x0) == value); - } - - private bool TestState(int mask, int value) - { - return ((_state & mask) == value); - } - - public bool Is80Columns { get { return TestState(State80Col); } } - public bool Is80Store { get { return TestState(State80Store); } } - public bool IsAnnunciator0 { get { return TestState(StateAn0); } } - public bool IsAnnunciator1 { get { return TestState(StateAn1); } } - public bool IsAnnunciator2 { get { return TestState(StateAn2); } } - public bool IsAnnunciator3 { get { return TestState(StateAn3); } } - public bool IsCharSetAlternate { get { return TestState(StateAltChrSet); } } - public bool IsDoubleRes { get { return TestState(StateDRes); } } - public bool IsHighRamAux { get { return IsZeroPageAux; } } - public bool IsHighRamBank1 { get { return TestState(StateBank1); } } - public bool IsHighRamRead { get { return TestState(StateHRamRd); } } - public bool IsHighRamWrite { get { return !TestState(StateHRamWrt); } } // HRamWrt' [5-23] - public bool IsHires { get { return TestState(StateHires); } } - public bool IsMixed { get { return TestState(StateMixed); } } - public bool IsPage2 { get { return TestState(StatePage2); } } - public bool IsRamReadAux { get { return TestState(StateRamRd); } } - public bool IsRamReadAuxRegion0407 { get { return Is80Store ? IsPage2 : IsRamReadAux; } } - public bool IsRamReadAuxRegion203F { get { return TestState(State80Store | StateHires, State80Store | StateHires) ? IsPage2 : IsRamReadAux; } } - public bool IsRamWriteAux { get { return TestState(StateRamWrt); } } - public bool IsRamWriteAuxRegion0407 { get { return Is80Store ? IsPage2 : IsRamWriteAux; } } - public bool IsRamWriteAuxRegion203F { get { return TestState(State80Store | StateHires, State80Store | StateHires) ? IsPage2 : IsRamWriteAux; } } - public bool IsRomC1CFInternal { get { return TestState(StateIntCXRom); } } - public bool IsRomC3C3External { get { return TestState(StateSlotC3Rom); } } - public bool IsRomC8CFInternal { get { return TestState(StateIntC8Rom); } } - public bool IsText { get { return TestState(StateText); } } - public bool IsVideoPage2 { get { return TestState(State80Store | StatePage2, StatePage2); } } // 80Store inhibits video Page2 [5-7, 8-19] - public bool IsZeroPageAux { get { return TestState(StateAltZP); } } - - 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; - private Speaker _speaker; - private Video _video; - private NoSlotClock _noSlotClock; - - private int _state; - private int _slotRegionC8CF; - - private byte[] _zeroPage; - private byte[][] _regionRead = new byte[RegionCount][]; - private byte[][] _regionWrite = new byte[RegionCount][]; - private Action[] _writeRegion = new Action[RegionCount]; - - private byte[] _ramMainRegion0001 = new byte[0x0200]; - private byte[] _ramMainRegion02BF = new byte[0xBE00]; - private byte[] _ramMainBank1RegionD0DF = new byte[0x1000]; - private byte[] _ramMainBank2RegionD0DF = new byte[0x1000]; - private byte[] _ramMainRegionE0FF = new byte[0x2000]; - private byte[] _ramAuxRegion0001 = new byte[0x0200]; - private byte[] _ramAuxRegion02BF = new byte[0xBE00]; - private byte[] _ramAuxBank1RegionD0DF = new byte[0x1000]; - private byte[] _ramAuxBank2RegionD0DF = new byte[0x1000]; - private byte[] _ramAuxRegionE0FF = new byte[0x2000]; - - private byte[] _romExternalRegionC1CF = new byte[0x0F00]; - private byte[] _romInternalRegionC1CF = new byte[0x0F00]; - private byte[] _romRegionD0DF = new byte[0x1000]; - private byte[] _romRegionE0FF = new byte[0x2000]; - } -} +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 +{ + public enum MonitorType { Unknown, Standard, Enhanced }; + + public sealed partial class Memory : MachineComponent + { + public Memory(Machine machine) : + base(machine) + { + WriteRamModeBankRegion = new Action[Video.ModeCount][][]; + for (int mode = 0; mode < Video.ModeCount; mode++) + { + WriteRamModeBankRegion[mode] = new Action[BankCount][] + { + new Action[RegionCount], new Action[RegionCount] + }; + } + WriteRamModeBankRegion[Video.Mode0][BankMain][Region0407] = WriteRamMode0MainRegion0407; + WriteRamModeBankRegion[Video.Mode0][BankMain][Region080B] = WriteRamMode0MainRegion080B; + WriteRamModeBankRegion[Video.Mode1][BankMain][Region0407] = WriteRamMode1MainRegion0407; + WriteRamModeBankRegion[Video.Mode1][BankMain][Region080B] = WriteRamMode1MainRegion080B; + WriteRamModeBankRegion[Video.Mode2][BankMain][Region0407] = WriteRamMode2MainRegion0407; + WriteRamModeBankRegion[Video.Mode2][BankMain][Region080B] = WriteRamMode2MainRegion080B; + WriteRamModeBankRegion[Video.Mode2][BankAux][Region0407] = WriteRamMode2AuxRegion0407; + WriteRamModeBankRegion[Video.Mode2][BankAux][Region080B] = WriteRamMode2AuxRegion080B; + WriteRamModeBankRegion[Video.Mode3][BankMain][Region0407] = WriteRamMode3MainRegion0407; + WriteRamModeBankRegion[Video.Mode3][BankMain][Region080B] = WriteRamMode3MainRegion080B; + WriteRamModeBankRegion[Video.Mode4][BankMain][Region0407] = WriteRamMode4MainRegion0407; + WriteRamModeBankRegion[Video.Mode4][BankMain][Region080B] = WriteRamMode4MainRegion080B; + WriteRamModeBankRegion[Video.Mode4][BankAux][Region0407] = WriteRamMode4AuxRegion0407; + WriteRamModeBankRegion[Video.Mode4][BankAux][Region080B] = WriteRamMode4AuxRegion080B; + WriteRamModeBankRegion[Video.Mode5][BankMain][Region203F] = WriteRamMode5MainRegion203F; + WriteRamModeBankRegion[Video.Mode5][BankMain][Region405F] = WriteRamMode5MainRegion405F; + WriteRamModeBankRegion[Video.Mode6][BankMain][Region0407] = WriteRamMode6MainRegion0407; + WriteRamModeBankRegion[Video.Mode6][BankMain][Region080B] = WriteRamMode6MainRegion080B; + WriteRamModeBankRegion[Video.Mode6][BankMain][Region203F] = WriteRamMode6MainRegion203F; + WriteRamModeBankRegion[Video.Mode6][BankMain][Region405F] = WriteRamMode6MainRegion405F; + WriteRamModeBankRegion[Video.Mode7][BankMain][Region0407] = WriteRamMode7MainRegion0407; + WriteRamModeBankRegion[Video.Mode7][BankMain][Region080B] = WriteRamMode7MainRegion080B; + WriteRamModeBankRegion[Video.Mode7][BankMain][Region203F] = WriteRamMode7MainRegion203F; + WriteRamModeBankRegion[Video.Mode7][BankMain][Region405F] = WriteRamMode7MainRegion405F; + WriteRamModeBankRegion[Video.Mode7][BankAux][Region0407] = WriteRamMode7AuxRegion0407; + WriteRamModeBankRegion[Video.Mode7][BankAux][Region080B] = WriteRamMode7AuxRegion080B; + WriteRamModeBankRegion[Video.Mode8][BankMain][Region0407] = WriteRamMode8MainRegion0407; + WriteRamModeBankRegion[Video.Mode8][BankMain][Region080B] = WriteRamMode8MainRegion080B; + WriteRamModeBankRegion[Video.Mode9][BankMain][Region0407] = WriteRamMode9MainRegion0407; + WriteRamModeBankRegion[Video.Mode9][BankMain][Region080B] = WriteRamMode9MainRegion080B; + WriteRamModeBankRegion[Video.Mode9][BankAux][Region0407] = WriteRamMode9AuxRegion0407; + WriteRamModeBankRegion[Video.Mode9][BankAux][Region080B] = WriteRamMode9AuxRegion080B; + WriteRamModeBankRegion[Video.ModeA][BankMain][Region0407] = WriteRamModeAMainRegion0407; + WriteRamModeBankRegion[Video.ModeA][BankMain][Region080B] = WriteRamModeAMainRegion080B; + WriteRamModeBankRegion[Video.ModeB][BankMain][Region0407] = WriteRamModeBMainRegion0407; + WriteRamModeBankRegion[Video.ModeB][BankMain][Region080B] = WriteRamModeBMainRegion080B; + WriteRamModeBankRegion[Video.ModeB][BankAux][Region0407] = WriteRamModeBAuxRegion0407; + WriteRamModeBankRegion[Video.ModeB][BankAux][Region080B] = WriteRamModeBAuxRegion080B; + WriteRamModeBankRegion[Video.ModeC][BankMain][Region203F] = WriteRamModeCMainRegion203F; + WriteRamModeBankRegion[Video.ModeC][BankMain][Region405F] = WriteRamModeCMainRegion405F; + WriteRamModeBankRegion[Video.ModeD][BankMain][Region203F] = WriteRamModeDMainRegion203F; + WriteRamModeBankRegion[Video.ModeD][BankMain][Region405F] = WriteRamModeDMainRegion405F; + WriteRamModeBankRegion[Video.ModeD][BankAux][Region203F] = WriteRamModeDAuxRegion203F; + WriteRamModeBankRegion[Video.ModeD][BankAux][Region405F] = WriteRamModeDAuxRegion405F; + WriteRamModeBankRegion[Video.ModeE][BankMain][Region0407] = WriteRamModeEMainRegion0407; + WriteRamModeBankRegion[Video.ModeE][BankMain][Region080B] = WriteRamModeEMainRegion080B; + WriteRamModeBankRegion[Video.ModeE][BankMain][Region203F] = WriteRamModeEMainRegion203F; + WriteRamModeBankRegion[Video.ModeE][BankMain][Region405F] = WriteRamModeEMainRegion405F; + WriteRamModeBankRegion[Video.ModeF][BankMain][Region0407] = WriteRamModeFMainRegion0407; + WriteRamModeBankRegion[Video.ModeF][BankMain][Region080B] = WriteRamModeFMainRegion080B; + WriteRamModeBankRegion[Video.ModeF][BankMain][Region203F] = WriteRamModeFMainRegion203F; + WriteRamModeBankRegion[Video.ModeF][BankMain][Region405F] = WriteRamModeFMainRegion405F; + WriteRamModeBankRegion[Video.ModeF][BankAux][Region0407] = WriteRamModeFAuxRegion0407; + 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() + { + _keyboard = Machine.Keyboard; + _gamePort = Machine.GamePort; + _cassette = Machine.Cassette; + _speaker = Machine.Speaker; + _video = Machine.Video; + _noSlotClock = Machine.NoSlotClock; + + StorageService.LoadResource("Roms/AppleIIe.rom", stream => + { + stream.SkipBlock(0x0100); + stream.ReadBlock(_romInternalRegionC1CF); + stream.ReadBlock(_romRegionD0DF); + stream.ReadBlock(_romRegionE0FF); + }); + + if ((ReadRomRegionE0FF(0xFBB3) == 0x06) && (ReadRomRegionE0FF(0xFBBF) == 0xC1)) + { + Monitor = MonitorType.Standard; + } + else if ((ReadRomRegionE0FF(0xFBB3) == 0x06) && (ReadRomRegionE0FF(0xFBBF) == 0x00) && (ReadRomRegionE0FF(0xFBC0) == 0xE0)) + { + Monitor = MonitorType.Enhanced; + } + } + + public override void Reset() // [7-3] + { + ResetState(State80Col | State80Store | StateAltChrSet | StateAltZP | StateBank1 | StateHRamRd | StateHRamPreWrt | StateHRamWrt | // HRamWrt' [5-23] + StateHires | StatePage2 | StateRamRd | StateRamWrt | StateIntCXRom | StateSlotC3Rom | StateIntC8Rom | StateAn0 | StateAn1 | StateAn2 | StateAn3); + SetState(StateDRes); // An3' -> DRes [8-20] + + MapRegion0001(); + MapRegion02BF(); + MapRegionC0CF(); + 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); + } + + 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) + { + int region = PageRegion[address >> 8]; + return ((address & 0xF000) != 0xC000) ? _regionRead[region][address - RegionBaseAddress[region]] : ReadIoRegionC0CF(address); + } + + public int ReadZeroPage(int address) + { + return _zeroPage[address]; + } + + public void Write(int address, int data) + { + int region = PageRegion[address >> 8]; + if (_writeRegion[region] == null) + { + _regionWrite[region][address - RegionBaseAddress[region]] = (byte)data; + } + else + { + _writeRegion[region](address, (byte)data); + } + } + + public void WriteZeroPage(int address, int data) + { + _zeroPage[address] = (byte)data; + } + #endregion + + #region Read Actions + private int ReadIoRegionC0CF(int address) + { + switch (address & 0xFF00) + { + case 0xC000: + return ReadIoRegionC0C0(address); + + case 0xC100: case 0xC200: case 0xC400: case 0xC500: case 0xC600: case 0xC700: + return ReadIoRegionC1C7(address); + + case 0xC300: + return ReadIoRegionC3C3(address); + + case 0xC800: case 0xC900: case 0xCA00: case 0xCB00: case 0xCC00: case 0xCD00: case 0xCE00: case 0xCF00: + return ReadIoRegionC8CF(address); + } + + return _video.ReadFloatingBus(); + } + + [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] + [SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode")] + private int ReadIoRegionC0C0(int address) + { + switch (address) + { + case 0xC000: case 0xC001: case 0xC002: case 0xC003: case 0xC004: case 0xC005: case 0xC006: case 0xC007: // [7-15] + case 0xC008: case 0xC009: case 0xC00A: case 0xC00B: case 0xC00C: case 0xC00D: case 0xC00E: case 0xC00F: + return SetBit7(_keyboard.Latch, _keyboard.Strobe); + + case 0xC010: + _keyboard.ResetStrobe(); + return SetBit7(_keyboard.Latch, _keyboard.IsAnyKeyDown); + + case 0xC011: + return SetBit7(_keyboard.Latch, !IsHighRamBank1); // Bank1' [5-22] + + case 0xC012: + return SetBit7(_keyboard.Latch, IsHighRamRead); + + case 0xC013: + return SetBit7(_keyboard.Latch, IsRamReadAux); + + case 0xC014: + return SetBit7(_keyboard.Latch, IsRamWriteAux); + + case 0xC015: + return SetBit7(_keyboard.Latch, IsRomC1CFInternal); + + case 0xC016: + return SetBit7(_keyboard.Latch, IsZeroPageAux); + + case 0xC017: + return SetBit7(_keyboard.Latch, IsRomC3C3External); + + case 0xC018: + return SetBit7(_keyboard.Latch, Is80Store); + + case 0xC019: + return SetBit7(_keyboard.Latch, !_video.IsVBlank); // Vbl' [7-5] + + case 0xC01A: + return SetBit7(_keyboard.Latch, IsText); + + case 0xC01B: + return SetBit7(_keyboard.Latch, IsMixed); + + case 0xC01C: + return SetBit7(_keyboard.Latch, IsPage2); + + case 0xC01D: + return SetBit7(_keyboard.Latch, IsHires); + + case 0xC01E: + return SetBit7(_keyboard.Latch, IsCharSetAlternate); + + case 0xC01F: + return SetBit7(_keyboard.Latch, Is80Columns); + + case 0xC020: case 0xC021: case 0xC022: case 0xC023: case 0xC024: case 0xC025: case 0xC026: case 0xC027: // [7-8] + case 0xC028: case 0xC029: case 0xC02A: case 0xC02B: case 0xC02C: case 0xC02D: case 0xC02E: case 0xC02F: + _cassette.ToggleOutput(); + break; + + case 0xC030: case 0xC031: case 0xC032: case 0xC033: case 0xC034: case 0xC035: case 0xC036: case 0xC037: // [7-9] + case 0xC038: case 0xC039: case 0xC03A: case 0xC03B: case 0xC03C: case 0xC03D: case 0xC03E: case 0xC03F: + _speaker.ToggleOutput(); + break; + + case 0xC040: case 0xC041: case 0xC042: case 0xC043: case 0xC044: case 0xC045: case 0xC046: case 0xC047: // [2-18] + case 0xC048: case 0xC049: case 0xC04A: case 0xC04B: case 0xC04C: case 0xC04D: case 0xC04E: case 0xC04F: + break; + + case 0xC050: case 0xC051: + SetText(TestBit(address, 0)); + break; + + case 0xC052: case 0xC053: + SetMixed(TestBit(address, 0)); + break; + + case 0xC054: case 0xC055: + SetPage2(TestBit(address, 0)); + break; + + case 0xC056: case 0xC057: + SetHires(TestBit(address, 0)); + break; + + case 0xC058: case 0xC059: + SetAnnunciator0(TestBit(address, 0)); + break; + + case 0xC05A: case 0xC05B: + SetAnnunciator1(TestBit(address, 0)); + break; + + case 0xC05C: case 0xC05D: + SetAnnunciator2(TestBit(address, 0)); + break; + + case 0xC05E: case 0xC05F: + SetAnnunciator3(TestBit(address, 0)); + SetDoubleRes(!TestBit(address, 0)); + break; + + case 0xC060: case 0xC068: // [2-18, 7-5] + return SetBit7(_video.ReadFloatingBus(), _cassette.ReadInput()); // [7-8] + + case 0xC061: case 0xC069: + return SetBit7(_video.ReadFloatingBus(), _gamePort.ReadButton0()); + + case 0xC062: case 0xC06A: + return SetBit7(_video.ReadFloatingBus(), _gamePort.ReadButton1()); + + case 0xC063: case 0xC06B: + return SetBit7(_video.ReadFloatingBus(), _gamePort.ReadButton2()); + + case 0xC064: case 0xC06C: + return SetBit7(_video.ReadFloatingBus(), _gamePort.Paddle0Strobe); + + case 0xC065: case 0xC06D: + return SetBit7(_video.ReadFloatingBus(), _gamePort.Paddle1Strobe); + + case 0xC066: case 0xC06E: + return SetBit7(_video.ReadFloatingBus(), _gamePort.Paddle2Strobe); + + case 0xC067: case 0xC06F: + return SetBit7(_video.ReadFloatingBus(), _gamePort.Paddle3Strobe); + + case 0xC070: case 0xC071: case 0xC072: case 0xC073: case 0xC074: case 0xC075: case 0xC076: case 0xC077: + case 0xC078: case 0xC079: case 0xC07A: case 0xC07B: case 0xC07C: case 0xC07D: case 0xC07E: case 0xC07F: + _gamePort.TriggerTimers(); + break; + + case 0xC080: case 0xC081: case 0xC082: case 0xC083: case 0xC084: case 0xC085: case 0xC086: case 0xC087: // slot0 [5-23] + case 0xC088: case 0xC089: case 0xC08A: case 0xC08B: case 0xC08C: case 0xC08D: case 0xC08E: case 0xC08F: + SetHighRam(address, true); + break; + + case 0xC090: case 0xC091: case 0xC092: case 0xC093: case 0xC094: case 0xC095: case 0xC096: case 0xC097: // slot1 + case 0xC098: case 0xC099: case 0xC09A: case 0xC09B: case 0xC09C: case 0xC09D: case 0xC09E: case 0xC09F: + return Machine.Slot1.ReadIoRegionC0C0(address); + + case 0xC0A0: case 0xC0A1: case 0xC0A2: case 0xC0A3: case 0xC0A4: case 0xC0A5: case 0xC0A6: case 0xC0A7: // slot2 + case 0xC0A8: case 0xC0A9: case 0xC0AA: case 0xC0AB: case 0xC0AC: case 0xC0AD: case 0xC0AE: case 0xC0AF: + return Machine.Slot2.ReadIoRegionC0C0(address); + + case 0xC0B0: case 0xC0B1: case 0xC0B2: case 0xC0B3: case 0xC0B4: case 0xC0B5: case 0xC0B6: case 0xC0B7: // slot3 + case 0xC0B8: case 0xC0B9: case 0xC0BA: case 0xC0BB: case 0xC0BC: case 0xC0BD: case 0xC0BE: case 0xC0BF: + return Machine.Slot3.ReadIoRegionC0C0(address); + + case 0xC0C0: case 0xC0C1: case 0xC0C2: case 0xC0C3: case 0xC0C4: case 0xC0C5: case 0xC0C6: case 0xC0C7: // slot4 + case 0xC0C8: case 0xC0C9: case 0xC0CA: case 0xC0CB: case 0xC0CC: case 0xC0CD: case 0xC0CE: case 0xC0CF: + return Machine.Slot4.ReadIoRegionC0C0(address); + + case 0xC0D0: case 0xC0D1: case 0xC0D2: case 0xC0D3: case 0xC0D4: case 0xC0D5: case 0xC0D6: case 0xC0D7: // slot5 + case 0xC0D8: case 0xC0D9: case 0xC0DA: case 0xC0DB: case 0xC0DC: case 0xC0DD: case 0xC0DE: case 0xC0DF: + return Machine.Slot5.ReadIoRegionC0C0(address); + + case 0xC0E0: case 0xC0E1: case 0xC0E2: case 0xC0E3: case 0xC0E4: case 0xC0E5: case 0xC0E6: case 0xC0E7: // slot6 + case 0xC0E8: case 0xC0E9: case 0xC0EA: case 0xC0EB: case 0xC0EC: case 0xC0ED: case 0xC0EE: case 0xC0EF: + return Machine.Slot6.ReadIoRegionC0C0(address); + + case 0xC0F0: case 0xC0F1: case 0xC0F2: case 0xC0F3: case 0xC0F4: case 0xC0F5: case 0xC0F6: case 0xC0F7: // slot7 + case 0xC0F8: case 0xC0F9: case 0xC0FA: case 0xC0FB: case 0xC0FC: case 0xC0FD: case 0xC0FE: case 0xC0FF: + return Machine.Slot7.ReadIoRegionC0C0(address); + + default: + throw new ArgumentOutOfRangeException("address"); + } + + return _video.ReadFloatingBus(); + } + + private int ReadIoRegionC1C7(int address) + { + _slotRegionC8CF = (address >> 8) & 0x07; + return IsRomC1CFInternal ? _romInternalRegionC1CF[address - 0xC100] : Machine.Slots[_slotRegionC8CF].ReadIoRegionC1C7(address); + } + + private int ReadIoRegionC3C3(int address) + { + _slotRegionC8CF = 3; + if (!IsRomC3C3External) + { + SetRomC8CF(true); // $C3XX sets IntC8Rom; inhibits I/O Strobe' [5-28, 7-21] + } + return (IsRomC1CFInternal || !IsRomC3C3External) ? _noSlotClock.Read(address, _romInternalRegionC1CF[address - 0xC100]) : Machine.Slot3.ReadIoRegionC1C7(address); + } + + private int ReadIoRegionC8CF(int address) + { + if (address == 0xCFFF) + { + SetRomC8CF(false); // $CFFF resets IntC8Rom [5-28, 7-21] + } + return (IsRomC1CFInternal || IsRomC8CFInternal) ? _noSlotClock.Read(address, _romInternalRegionC1CF[address - 0xC100]) : Machine.Slots[_slotRegionC8CF].ReadIoRegionC8CF(address); + } + + [SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow", MessageId = "address-512")] + public int ReadRamMainRegion02BF(int address) + { + return _ramMainRegion02BF[address - 0x0200]; + } + + [SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow", MessageId = "address-512")] + public int ReadRamAuxRegion02BF(int address) + { + return _ramAuxRegion02BF[address - 0x0200]; + } + + [SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow", MessageId = "address-57344")] + public int ReadRomRegionE0FF(int address) + { + return _romRegionE0FF[address - 0xE000]; + } + #endregion + + #region Write Actions + [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] + [SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode")] + private void WriteIoRegionC0C0(int address, byte data) + { + switch (address) + { + case 0xC000: case 0xC001: // [5-22] + Set80Store(TestBit(address, 0)); + break; + + case 0xC002: case 0xC003: + SetRamRead(TestBit(address, 0)); + break; + + case 0xC004: case 0xC005: + SetRamWrite(TestBit(address, 0)); + break; + + case 0xC006: case 0xC007: + SetRomC1CF(TestBit(address, 0)); + break; + + case 0xC008: case 0xC009: + SetZeroPage(TestBit(address, 0)); + break; + + case 0xC00A: case 0xC00B: + SetRomC3C3(TestBit(address, 0)); + break; + + case 0xC00C: case 0xC00D: // [7-5] + Set80Columns(TestBit(address, 0)); + break; + + case 0xC00E: case 0xC00F: + SetCharSet(TestBit(address, 0)); + break; + + case 0xC010: case 0xC011: case 0xC012: case 0xC013: case 0xC014: case 0xC015: case 0xC016: case 0xC017: // [7-15] + case 0xC018: case 0xC019: case 0xC01A: case 0xC01B: case 0xC01C: case 0xC01D: case 0xC01E: case 0xC01F: + _keyboard.ResetStrobe(); + break; + + case 0xC020: case 0xC021: case 0xC022: case 0xC023: case 0xC024: case 0xC025: case 0xC026: case 0xC027: // [7-8] + case 0xC028: case 0xC029: case 0xC02A: case 0xC02B: case 0xC02C: case 0xC02D: case 0xC02E: case 0xC02F: + _cassette.ToggleOutput(); + break; + + case 0xC030: case 0xC031: case 0xC032: case 0xC033: case 0xC034: case 0xC035: case 0xC036: case 0xC037: // [7-9] + case 0xC038: case 0xC039: case 0xC03A: case 0xC03B: case 0xC03C: case 0xC03D: case 0xC03E: case 0xC03F: + _speaker.ToggleOutput(); + break; + + case 0xC040: case 0xC041: case 0xC042: case 0xC043: case 0xC044: case 0xC045: case 0xC046: case 0xC047: // [2-18] + case 0xC048: case 0xC049: case 0xC04A: case 0xC04B: case 0xC04C: case 0xC04D: case 0xC04E: case 0xC04F: + break; + + case 0xC050: case 0xC051: + SetText(TestBit(address, 0)); + break; + + case 0xC052: case 0xC053: + SetMixed(TestBit(address, 0)); + break; + + case 0xC054: case 0xC055: + SetPage2(TestBit(address, 0)); + break; + + case 0xC056: case 0xC057: + SetHires(TestBit(address, 0)); + break; + + case 0xC058: case 0xC059: + SetAnnunciator0(TestBit(address, 0)); + break; + + case 0xC05A: case 0xC05B: + SetAnnunciator1(TestBit(address, 0)); + break; + + case 0xC05C: case 0xC05D: + SetAnnunciator2(TestBit(address, 0)); + break; + + case 0xC05E: case 0xC05F: + SetAnnunciator3(TestBit(address, 0)); + SetDoubleRes(!TestBit(address, 0)); + break; + + case 0xC060: case 0xC061: case 0xC062: case 0xC063: case 0xC064: case 0xC065: case 0xC066: case 0xC067: // [2-18, 7-5] + case 0xC068: case 0xC069: case 0xC06A: case 0xC06B: case 0xC06C: case 0xC06D: case 0xC06E: case 0xC06F: + break; + + case 0xC070: case 0xC071: case 0xC072: case 0xC073: case 0xC074: case 0xC075: case 0xC076: case 0xC077: + case 0xC078: case 0xC079: case 0xC07A: case 0xC07B: case 0xC07C: case 0xC07D: case 0xC07E: case 0xC07F: + _gamePort.TriggerTimers(); + break; + + case 0xC080: case 0xC081: case 0xC082: case 0xC083: case 0xC084: case 0xC085: case 0xC086: case 0xC087: // slot0 [5-23] + case 0xC088: case 0xC089: case 0xC08A: case 0xC08B: case 0xC08C: case 0xC08D: case 0xC08E: case 0xC08F: + SetHighRam(address, false); + break; + + case 0xC090: case 0xC091: case 0xC092: case 0xC093: case 0xC094: case 0xC095: case 0xC096: case 0xC097: // slot1 + case 0xC098: case 0xC099: case 0xC09A: case 0xC09B: case 0xC09C: case 0xC09D: case 0xC09E: case 0xC09F: + Machine.Slot1.WriteIoRegionC0C0(address, data); + break; + + case 0xC0A0: case 0xC0A1: case 0xC0A2: case 0xC0A3: case 0xC0A4: case 0xC0A5: case 0xC0A6: case 0xC0A7: // slot2 + case 0xC0A8: case 0xC0A9: case 0xC0AA: case 0xC0AB: case 0xC0AC: case 0xC0AD: case 0xC0AE: case 0xC0AF: + Machine.Slot2.WriteIoRegionC0C0(address, data); + break; + + case 0xC0B0: case 0xC0B1: case 0xC0B2: case 0xC0B3: case 0xC0B4: case 0xC0B5: case 0xC0B6: case 0xC0B7: // slot3 + case 0xC0B8: case 0xC0B9: case 0xC0BA: case 0xC0BB: case 0xC0BC: case 0xC0BD: case 0xC0BE: case 0xC0BF: + Machine.Slot3.WriteIoRegionC0C0(address, data); + break; + + case 0xC0C0: case 0xC0C1: case 0xC0C2: case 0xC0C3: case 0xC0C4: case 0xC0C5: case 0xC0C6: case 0xC0C7: // slot4 + case 0xC0C8: case 0xC0C9: case 0xC0CA: case 0xC0CB: case 0xC0CC: case 0xC0CD: case 0xC0CE: case 0xC0CF: + Machine.Slot4.WriteIoRegionC0C0(address, data); + break; + + case 0xC0D0: case 0xC0D1: case 0xC0D2: case 0xC0D3: case 0xC0D4: case 0xC0D5: case 0xC0D6: case 0xC0D7: // slot5 + case 0xC0D8: case 0xC0D9: case 0xC0DA: case 0xC0DB: case 0xC0DC: case 0xC0DD: case 0xC0DE: case 0xC0DF: + Machine.Slot5.WriteIoRegionC0C0(address, data); + break; + + case 0xC0E0: case 0xC0E1: case 0xC0E2: case 0xC0E3: case 0xC0E4: case 0xC0E5: case 0xC0E6: case 0xC0E7: // slot6 + case 0xC0E8: case 0xC0E9: case 0xC0EA: case 0xC0EB: case 0xC0EC: case 0xC0ED: case 0xC0EE: case 0xC0EF: + Machine.Slot6.WriteIoRegionC0C0(address, data); + break; + + case 0xC0F0: case 0xC0F1: case 0xC0F2: case 0xC0F3: case 0xC0F4: case 0xC0F5: case 0xC0F6: case 0xC0F7: // slot7 + case 0xC0F8: case 0xC0F9: case 0xC0FA: case 0xC0FB: case 0xC0FC: case 0xC0FD: case 0xC0FE: case 0xC0FF: + Machine.Slot7.WriteIoRegionC0C0(address, data); + break; + + default: + throw new ArgumentOutOfRangeException("address"); + } + } + + private void WriteIoRegionC1C7(int address, byte data) + { + _slotRegionC8CF = (address >> 8) & 0x07; + if (!IsRomC1CFInternal) + { + Machine.Slots[_slotRegionC8CF].WriteIoRegionC1C7(address, data); + } + } + + private void WriteIoRegionC3C3(int address, byte data) + { + _slotRegionC8CF = 3; + if (!IsRomC3C3External) + { + SetRomC8CF(true); // $C3XX sets IntC8Rom; inhibits I/O Strobe' [5-28, 7-21] + } + if (IsRomC1CFInternal || !IsRomC3C3External) + { + _noSlotClock.Write(address); + } + else + { + Machine.Slot3.WriteIoRegionC1C7(address, data); + } + } + + private void WriteIoRegionC8CF(int address, byte data) + { + if (address == 0xCFFF) + { + SetRomC8CF(false); // $CFFF resets IntC8Rom [5-28, 7-21] + } + if (IsRomC1CFInternal || IsRomC8CFInternal) + { + _noSlotClock.Write(address); + } + else + { + Machine.Slots[_slotRegionC8CF].WriteIoRegionC8CF(address, data); + } + } + + private void WriteRamMode0MainRegion0407(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0400); // lores page1 + } + } + + private void WriteRamMode0MainRegion080B(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0800); // lores page2 + } + } + + private void WriteRamMode1MainRegion0407(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0400); // text40 page1 + } + } + + private void WriteRamMode1MainRegion080B(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0800); // text40 page2 + } + } + + private void WriteRamMode2MainRegion0407(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0400); // text80 page1 + } + } + + private void WriteRamMode2MainRegion080B(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0800); // text80 page2 + } + } + + private void WriteRamMode2AuxRegion0407(int address, byte data) + { + if (_ramAuxRegion02BF[address - 0x0200] != data) + { + _ramAuxRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0400); // text80 page1 + } + } + + private void WriteRamMode2AuxRegion080B(int address, byte data) + { + if (_ramAuxRegion02BF[address - 0x0200] != data) + { + _ramAuxRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0800); // text80 page2 + } + } + + private void WriteRamMode3MainRegion0407(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0400); // lores & text40 page1 + } + } + + private void WriteRamMode3MainRegion080B(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0800); // lores & text40 page2 + } + } + + private void WriteRamMode4MainRegion0407(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0400); // lores & text80 page1 + } + } + + private void WriteRamMode4MainRegion080B(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0800); // lores & text80 page2 + } + } + + private void WriteRamMode4AuxRegion0407(int address, byte data) + { + if (_ramAuxRegion02BF[address - 0x0200] != data) + { + _ramAuxRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixedText(address - 0x0400); // [lores &] text80 page1 + } + } + + private void WriteRamMode4AuxRegion080B(int address, byte data) + { + if (_ramAuxRegion02BF[address - 0x0200] != data) + { + _ramAuxRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixedText(address - 0x0800); // [lores &] text80 page2 + } + } + + private void WriteRamMode5MainRegion203F(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x2000); // hires page1 + } + } + + private void WriteRamMode5MainRegion405F(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x4000); // hires page2 + } + } + + private void WriteRamMode6MainRegion0407(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixedText(address - 0x0400); // [hires &] text40 page1 + } + } + + private void WriteRamMode6MainRegion080B(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixedText(address - 0x0800); // [hires &] text40 page2 + } + } + + private void WriteRamMode6MainRegion203F(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixed(address - 0x2000); // hires [& text40] page1 + } + } + + private void WriteRamMode6MainRegion405F(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixed(address - 0x4000); // hires [& text40] page2 + } + } + + private void WriteRamMode7MainRegion0407(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixedText(address - 0x0400); // [hires &] text80 page1 + } + } + + private void WriteRamMode7MainRegion080B(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixedText(address - 0x0800); // [hires &] text80 page2 + } + } + + private void WriteRamMode7MainRegion203F(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixed(address - 0x2000); // hires [& text80] page1 + } + } + + private void WriteRamMode7MainRegion405F(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixed(address - 0x4000); // hires [& text80] page2 + } + } + + private void WriteRamMode7AuxRegion0407(int address, byte data) + { + if (_ramAuxRegion02BF[address - 0x0200] != data) + { + _ramAuxRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixedText(address - 0x0400); // [hires &] text80 page1 + } + } + + private void WriteRamMode7AuxRegion080B(int address, byte data) + { + if (_ramAuxRegion02BF[address - 0x0200] != data) + { + _ramAuxRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixedText(address - 0x0800); // [hires &] text80 page2 + } + } + + private void WriteRamMode8MainRegion0407(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0400); // 7mlores page1 + } + } + + private void WriteRamMode8MainRegion080B(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0800); // 7mlores page2 + } + } + + private void WriteRamMode9MainRegion0407(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0400); // dlores page1 + } + } + + private void WriteRamMode9MainRegion080B(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0800); // dlores page2 + } + } + + private void WriteRamMode9AuxRegion0407(int address, byte data) + { + if (_ramAuxRegion02BF[address - 0x0200] != data) + { + _ramAuxRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0400); // dlores page1 + } + } + + private void WriteRamMode9AuxRegion080B(int address, byte data) + { + if (_ramAuxRegion02BF[address - 0x0200] != data) + { + _ramAuxRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0800); // dlores page2 + } + } + + private void WriteRamModeAMainRegion0407(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0400); // 7mlores & text40 page1 + } + } + + private void WriteRamModeAMainRegion080B(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0800); // 7mlores & text40 page2 + } + } + + private void WriteRamModeBMainRegion0407(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0400); // dlores & text80 page1 + } + } + + private void WriteRamModeBMainRegion080B(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0800); // dlores & text80 page2 + } + } + + private void WriteRamModeBAuxRegion0407(int address, byte data) + { + if (_ramAuxRegion02BF[address - 0x0200] != data) + { + _ramAuxRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0400); // dlores & text80 page1 + } + } + + private void WriteRamModeBAuxRegion080B(int address, byte data) + { + if (_ramAuxRegion02BF[address - 0x0200] != data) + { + _ramAuxRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x0800); // dlores & text80 page2 + } + } + + private void WriteRamModeCMainRegion203F(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x2000); // ndhires page1 + } + } + + private void WriteRamModeCMainRegion405F(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x4000); // ndhires page2 + } + } + + private void WriteRamModeDMainRegion203F(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x2000); // dhires page1 + } + } + + private void WriteRamModeDMainRegion405F(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x4000); // dhires page2 + } + } + + private void WriteRamModeDAuxRegion203F(int address, byte data) + { + if (_ramAuxRegion02BF[address - 0x0200] != data) + { + _ramAuxRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x2000); // dhires page1 + } + } + + private void WriteRamModeDAuxRegion405F(int address, byte data) + { + if (_ramAuxRegion02BF[address - 0x0200] != data) + { + _ramAuxRegion02BF[address - 0x0200] = data; + _video.DirtyCell(address - 0x4000); // dhires page2 + } + } + + private void WriteRamModeEMainRegion0407(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixedText(address - 0x0400); // [ndhires &] text40 page1 + } + } + + private void WriteRamModeEMainRegion080B(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixedText(address - 0x0800); // [ndhires &] text40 page2 + } + } + + private void WriteRamModeEMainRegion203F(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixed(address - 0x2000); // ndhires [& text40] page1 + } + } + + private void WriteRamModeEMainRegion405F(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixed(address - 0x4000); // ndhires [& text40] page2 + } + } + + private void WriteRamModeFMainRegion0407(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixedText(address - 0x0400); // [dhires &] text80 page1 + } + } + + private void WriteRamModeFMainRegion080B(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixedText(address - 0x0800); // [dhires &] text80 page2 + } + } + + private void WriteRamModeFMainRegion203F(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixed(address - 0x2000); // dhires [& text80] page1 + } + } + + private void WriteRamModeFMainRegion405F(int address, byte data) + { + if (_ramMainRegion02BF[address - 0x0200] != data) + { + _ramMainRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixed(address - 0x4000); // dhires [& text80] page2 + } + } + + private void WriteRamModeFAuxRegion0407(int address, byte data) + { + if (_ramAuxRegion02BF[address - 0x0200] != data) + { + _ramAuxRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixedText(address - 0x0400); // [dhires &] text80 page1 + } + } + + private void WriteRamModeFAuxRegion080B(int address, byte data) + { + if (_ramAuxRegion02BF[address - 0x0200] != data) + { + _ramAuxRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixedText(address - 0x0800); // [dhires &] text80 page2 + } + } + + private void WriteRamModeFAuxRegion203F(int address, byte data) + { + if (_ramAuxRegion02BF[address - 0x0200] != data) + { + _ramAuxRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixed(address - 0x2000); // dhires [& text80] page1 + } + } + + private void WriteRamModeFAuxRegion405F(int address, byte data) + { + if (_ramAuxRegion02BF[address - 0x0200] != data) + { + _ramAuxRegion02BF[address - 0x0200] = data; + _video.DirtyCellMixed(address - 0x4000); // dhires [& text80] page2 + } + } + + private void WriteRomRegionD0FF(int address, byte data) + { + } + #endregion + + #region Softswitch Actions + private void MapRegion0001() + { + if (!IsZeroPageAux) + { + _regionRead[Region0001] = _ramMainRegion0001; + _regionWrite[Region0001] = _ramMainRegion0001; + _zeroPage = _ramMainRegion0001; + } + else + { + _regionRead[Region0001] = _ramAuxRegion0001; + _regionWrite[Region0001] = _ramAuxRegion0001; + _zeroPage = _ramAuxRegion0001; + } + _writeRegion[Region0001] = null; + } + + private void MapRegion02BF() + { + if (!IsRamReadAux) + { + _regionRead[Region02BF] = _ramMainRegion02BF; + _regionRead[Region080B] = _ramMainRegion02BF; + _regionRead[Region405F] = _ramMainRegion02BF; + } + else + { + _regionRead[Region02BF] = _ramAuxRegion02BF; + _regionRead[Region080B] = _ramAuxRegion02BF; + _regionRead[Region405F] = _ramAuxRegion02BF; + } + int mode = VideoMode; + if (!IsRamWriteAux) + { + _regionWrite[Region02BF] = _ramMainRegion02BF; + _regionWrite[Region080B] = _ramMainRegion02BF; + _regionWrite[Region405F] = _ramMainRegion02BF; + _writeRegion[Region02BF] = null; + _writeRegion[Region080B] = WriteRamModeBankRegion[mode][BankMain][Region080B]; + _writeRegion[Region405F] = WriteRamModeBankRegion[mode][BankMain][Region405F]; + } + else + { + _regionWrite[Region02BF] = _ramAuxRegion02BF; + _regionWrite[Region080B] = _ramAuxRegion02BF; + _regionWrite[Region405F] = _ramAuxRegion02BF; + _writeRegion[Region02BF] = null; + _writeRegion[Region080B] = WriteRamModeBankRegion[mode][BankAux][Region080B]; + _writeRegion[Region405F] = WriteRamModeBankRegion[mode][BankAux][Region405F]; + } + MapRegion0407(); + MapRegion203F(); + } + + private void MapRegion0407() + { + if (!IsRamReadAuxRegion0407) + { + _regionRead[Region0407] = _ramMainRegion02BF; + } + else + { + _regionRead[Region0407] = _ramAuxRegion02BF; + } + int mode = VideoMode; + if (!IsRamWriteAuxRegion0407) + { + _regionWrite[Region0407] = _ramMainRegion02BF; + _writeRegion[Region0407] = WriteRamModeBankRegion[mode][BankMain][Region0407]; + } + else + { + _regionWrite[Region0407] = _ramAuxRegion02BF; + _writeRegion[Region0407] = WriteRamModeBankRegion[mode][BankAux][Region0407]; + } + } + + private void MapRegion203F() + { + if (!IsRamReadAuxRegion203F) + { + _regionRead[Region203F] = _ramMainRegion02BF; + } + else + { + _regionRead[Region203F] = _ramAuxRegion02BF; + } + int mode = VideoMode; + if (!IsRamWriteAuxRegion203F) + { + _regionWrite[Region203F] = _ramMainRegion02BF; + _writeRegion[Region203F] = WriteRamModeBankRegion[mode][BankMain][Region203F]; + } + else + { + _regionWrite[Region203F] = _ramAuxRegion02BF; + _writeRegion[Region203F] = WriteRamModeBankRegion[mode][BankAux][Region203F]; + } + } + + private void MapRegionC0CF() + { + _regionRead[RegionC0C0] = null; + if (IsRomC1CFInternal) + { + _regionRead[RegionC1C7] = _romInternalRegionC1CF; + _regionRead[RegionC3C3] = _romInternalRegionC1CF; + _regionRead[RegionC8CF] = _romInternalRegionC1CF; + } + else + { + _regionRead[RegionC1C7] = _romExternalRegionC1CF; + _regionRead[RegionC3C3] = IsRomC3C3External ? _romExternalRegionC1CF : _romInternalRegionC1CF; + _regionRead[RegionC8CF] = !IsRomC8CFInternal ? _romExternalRegionC1CF : _romInternalRegionC1CF; + } + _regionWrite[RegionC0C0] = null; + _regionWrite[RegionC1C7] = null; + _regionWrite[RegionC3C3] = null; + _regionWrite[RegionC8CF] = null; + _writeRegion[RegionC0C0] = _writeIoRegionC0C0; + _writeRegion[RegionC1C7] = _writeIoRegionC1C7; + _writeRegion[RegionC3C3] = _writeIoRegionC3C3; + _writeRegion[RegionC8CF] = _writeIoRegionC8CF; + } + + private void MapRegionD0FF() + { + if (IsHighRamRead) + { + if (!IsHighRamAux) + { + _regionRead[RegionD0DF] = IsHighRamBank1 ? _ramMainBank1RegionD0DF : _ramMainBank2RegionD0DF; + _regionRead[RegionE0FF] = _ramMainRegionE0FF; + } + else + { + _regionRead[RegionD0DF] = IsHighRamBank1 ? _ramAuxBank1RegionD0DF : _ramAuxBank2RegionD0DF; + _regionRead[RegionE0FF] = _ramAuxRegionE0FF; + } + } + else + { + _regionRead[RegionD0DF] = _romRegionD0DF; + _regionRead[RegionE0FF] = _romRegionE0FF; + } + if (IsHighRamWrite) + { + if (!IsHighRamAux) + { + _regionWrite[RegionD0DF] = IsHighRamBank1 ? _ramMainBank1RegionD0DF : _ramMainBank2RegionD0DF; + _regionWrite[RegionE0FF] = _ramMainRegionE0FF; + } + else + { + _regionWrite[RegionD0DF] = IsHighRamBank1 ? _ramAuxBank1RegionD0DF : _ramAuxBank2RegionD0DF; + _regionWrite[RegionE0FF] = _ramAuxRegionE0FF; + } + _writeRegion[RegionD0DF] = null; + _writeRegion[RegionE0FF] = null; + } + else + { + _regionWrite[RegionD0DF] = null; + _regionWrite[RegionE0FF] = null; + _writeRegion[RegionD0DF] = _writeRomRegionD0FF; + _writeRegion[RegionE0FF] = _writeRomRegionD0FF; + } + } + + private void Set80Columns(bool value) + { + if (!TestState(State80Col, value)) + { + SetState(State80Col, value); + MapRegion02BF(); + _video.DirtyScreen(); + } + } + + private void Set80Store(bool value) + { + if (!TestState(State80Store, value)) + { + SetState(State80Store, value); + if (IsPage2) // [5-7, 8-19] + { + MapRegion02BF(); + _video.DirtyScreen(); + } + else + { + MapRegion0407(); + MapRegion203F(); + } + } + } + + private void SetAnnunciator0(bool value) + { + SetState(StateAn0, value); + } + + private void SetAnnunciator1(bool value) + { + SetState(StateAn1, value); + } + + private void SetAnnunciator2(bool value) + { + SetState(StateAn2, value); + } + + private void SetAnnunciator3(bool value) + { + SetState(StateAn3, value); + } + + private void SetCharSet(bool value) + { + if (!TestState(StateAltChrSet, value)) + { + SetState(StateAltChrSet, value); + _video.SetCharSet(); + } + } + + private void SetDoubleRes(bool value) + { + if (!TestState(StateDRes, value)) + { + SetState(StateDRes, value); + MapRegion02BF(); + _video.DirtyScreen(); + } + } + + private void SetHighRam(int address, bool isRead) + { + SetState(StateBank1, TestBit(address, 3)); // A3 [5-22] + SetState(StateHRamRd, TestMask(address, 0x3, 0x3) || TestMask(address, 0x3, 0x0)); // A0.A1+A0'.A1' [5-23] (5-22 misprint) + if (TestBit(address, 0)) // A0 [5-23] + { + if (isRead && TestState(StateHRamPreWrt)) + { + ResetState(StateHRamWrt); // HRamWrt' [5-23] + } + } + else + { + SetState(StateHRamWrt); + } + SetState(StateHRamPreWrt, isRead && TestBit(address, 0)); // A0.R/W' [5-22] + MapRegionD0FF(); + } + + private void SetHires(bool value) + { + if (!TestState(StateHires, value)) + { + SetState(StateHires, value); + if (!Is80Store) // [5-7, 8-19] + { + MapRegion02BF(); + _video.DirtyScreen(); + } + else + { + MapRegion203F(); + } + } + } + + private void SetMixed(bool value) + { + if (!TestState(StateMixed, value)) + { + SetState(StateMixed, value); + MapRegion02BF(); + _video.DirtyScreen(); + } + } + + private void SetPage2(bool value) + { + if (!TestState(StatePage2, value)) + { + SetState(StatePage2, value); + if (!Is80Store) // [5-7, 8-19] + { + MapRegion02BF(); + _video.DirtyScreen(); + } + else + { + MapRegion0407(); + MapRegion203F(); + } + } + } + + private void SetRamRead(bool value) + { + if (!TestState(StateRamRd, value)) + { + SetState(StateRamRd, value); + MapRegion02BF(); + } + } + + private void SetRamWrite(bool value) + { + if (!TestState(StateRamWrt, value)) + { + SetState(StateRamWrt, value); + MapRegion02BF(); + } + } + + private void SetRomC1CF(bool value) + { + if (!TestState(StateIntCXRom, value)) + { + SetState(StateIntCXRom, value); + MapRegionC0CF(); + } + } + + private void SetRomC3C3(bool value) + { + if (!TestState(StateSlotC3Rom, value)) + { + SetState(StateSlotC3Rom, value); + MapRegionC0CF(); + } + } + + private void SetRomC8CF(bool value) + { + if (!TestState(StateIntC8Rom, value)) + { + SetState(StateIntC8Rom, value); + MapRegionC0CF(); + } + } + + private void SetText(bool value) + { + if (!TestState(StateText, value)) + { + SetState(StateText, value); + MapRegion02BF(); + _video.DirtyScreen(); + } + } + + private void SetZeroPage(bool value) + { + if (!TestState(StateAltZP, value)) + { + SetState(StateAltZP, value); + MapRegion0001(); + MapRegionD0FF(); + } + } + #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); + _ramMainRegion02BF[0x03F3 - 0x0200] = (byte)(address >> 8); + _ramMainRegion02BF[0x03F4 - 0x0200] = (byte)((address >> 8) ^ 0xA5); + } + + private static int SetBit7(int data, bool value) + { + return value ? (data | 0x80) : (data & 0x7F); + } + + private static bool TestBit(int data, int bit) + { + return ((data & (0x1 << bit)) != 0x0); + } + + private static bool TestMask(int data, int mask, int value) + { + return ((data & mask) == value); + } + + private void ResetState(int mask) + { + _state &= ~mask; + } + + private void SetState(int mask) + { + _state |= mask; + } + + private void SetState(int mask, bool value) + { + if (value) + { + _state |= mask; + } + else + { + _state &= ~mask; + } + } + + private bool TestState(int mask) + { + return ((_state & mask) != 0x0); + } + + private bool TestState(int mask, bool value) + { + return (((_state & mask) != 0x0) == value); + } + + private bool TestState(int mask, int value) + { + return ((_state & mask) == value); + } + + public bool Is80Columns { get { return TestState(State80Col); } } + public bool Is80Store { get { return TestState(State80Store); } } + public bool IsAnnunciator0 { get { return TestState(StateAn0); } } + public bool IsAnnunciator1 { get { return TestState(StateAn1); } } + public bool IsAnnunciator2 { get { return TestState(StateAn2); } } + public bool IsAnnunciator3 { get { return TestState(StateAn3); } } + public bool IsCharSetAlternate { get { return TestState(StateAltChrSet); } } + public bool IsDoubleRes { get { return TestState(StateDRes); } } + public bool IsHighRamAux { get { return IsZeroPageAux; } } + public bool IsHighRamBank1 { get { return TestState(StateBank1); } } + public bool IsHighRamRead { get { return TestState(StateHRamRd); } } + public bool IsHighRamWrite { get { return !TestState(StateHRamWrt); } } // HRamWrt' [5-23] + public bool IsHires { get { return TestState(StateHires); } } + public bool IsMixed { get { return TestState(StateMixed); } } + public bool IsPage2 { get { return TestState(StatePage2); } } + public bool IsRamReadAux { get { return TestState(StateRamRd); } } + public bool IsRamReadAuxRegion0407 { get { return Is80Store ? IsPage2 : IsRamReadAux; } } + public bool IsRamReadAuxRegion203F { get { return TestState(State80Store | StateHires, State80Store | StateHires) ? IsPage2 : IsRamReadAux; } } + public bool IsRamWriteAux { get { return TestState(StateRamWrt); } } + public bool IsRamWriteAuxRegion0407 { get { return Is80Store ? IsPage2 : IsRamWriteAux; } } + public bool IsRamWriteAuxRegion203F { get { return TestState(State80Store | StateHires, State80Store | StateHires) ? IsPage2 : IsRamWriteAux; } } + public bool IsRomC1CFInternal { get { return TestState(StateIntCXRom); } } + public bool IsRomC3C3External { get { return TestState(StateSlotC3Rom); } } + public bool IsRomC8CFInternal { get { return TestState(StateIntC8Rom); } } + public bool IsText { get { return TestState(StateText); } } + public bool IsVideoPage2 { get { return TestState(State80Store | StatePage2, StatePage2); } } // 80Store inhibits video Page2 [5-7, 8-19] + public bool IsZeroPageAux { get { return TestState(StateAltZP); } } + + 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; + private Speaker _speaker; + private Video _video; + private NoSlotClock _noSlotClock; + + private int _state; + private int _slotRegionC8CF; + + private byte[] _zeroPage; + private byte[][] _regionRead = new byte[RegionCount][]; + private byte[][] _regionWrite = new byte[RegionCount][]; + private Action[] _writeRegion = new Action[RegionCount]; + + private byte[] _ramMainRegion0001 = new byte[0x0200]; + private byte[] _ramMainRegion02BF = new byte[0xBE00]; + private byte[] _ramMainBank1RegionD0DF = new byte[0x1000]; + private byte[] _ramMainBank2RegionD0DF = new byte[0x1000]; + private byte[] _ramMainRegionE0FF = new byte[0x2000]; + private byte[] _ramAuxRegion0001 = new byte[0x0200]; + private byte[] _ramAuxRegion02BF = new byte[0xBE00]; + private byte[] _ramAuxBank1RegionD0DF = new byte[0x1000]; + private byte[] _ramAuxBank2RegionD0DF = new byte[0x1000]; + private byte[] _ramAuxRegionE0FF = new byte[0x2000]; + + private byte[] _romExternalRegionC1CF = new byte[0x0F00]; + private byte[] _romInternalRegionC1CF = new byte[0x0F00]; + private byte[] _romRegionD0DF = new byte[0x1000]; + private byte[] _romRegionE0FF = new byte[0x2000]; + } +} diff --git a/Virtu/MemoryData.cs b/Virtu/MemoryData.cs index e2e9bfa..b3697ec 100644 --- a/Virtu/MemoryData.cs +++ b/Virtu/MemoryData.cs @@ -1,106 +1,106 @@ -using System; - -namespace Jellyfish.Virtu -{ - public partial class Memory - { - private const int BankCount = 2; - - private const int BankMain = 0; - private const int BankAux = 1; - - private const int RegionCount = 12; - - private const int Region0001 = 0; - private const int Region02BF = 1; - private const int Region0407 = 2; - private const int Region080B = 3; - private const int Region203F = 4; - private const int Region405F = 5; - private const int RegionC0C0 = 6; - private const int RegionC1C7 = 7; - private const int RegionC3C3 = 8; - private const int RegionC8CF = 9; - private const int RegionD0DF = 10; - private const int RegionE0FF = 11; - - private static readonly int[] RegionBaseAddress = new int[RegionCount] - { - 0x0000, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0xC000, 0xC100, 0xC100, 0xC100, 0xD000, 0xE000 - }; - - private const int PageCount = 256; - - private static readonly int[] PageRegion = new int[PageCount] - { - Region0001, Region0001, Region02BF, Region02BF, Region0407, Region0407, Region0407, Region0407, - Region080B, Region080B, Region080B, Region080B, Region02BF, Region02BF, Region02BF, Region02BF, - Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, - Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, - Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, - Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, - Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, - Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, - Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, - Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, - Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, - Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, - Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, - Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, - Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, - Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, - Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, - Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, - Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, - Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, - Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, - Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, - Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, - Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, - RegionC0C0, RegionC1C7, RegionC1C7, RegionC3C3, RegionC1C7, RegionC1C7, RegionC1C7, RegionC1C7, - RegionC8CF, RegionC8CF, RegionC8CF, RegionC8CF, RegionC8CF, RegionC8CF, RegionC8CF, RegionC8CF, - RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, - RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, - RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, - RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, - RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, - RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF - }; - - private const int State80Col = 0x000001; - private const int StateText = 0x000002; - private const int StateMixed = 0x000004; - private const int StateHires = 0x000008; - private const int StateDRes = 0x000010; - private const int State80Store = 0x000020; - private const int StateAltChrSet = 0x000040; - private const int StateAltZP = 0x000080; - private const int StateBank1 = 0x000100; - private const int StateHRamRd = 0x000200; - private const int StateHRamPreWrt = 0x000400; - private const int StateHRamWrt = 0x000800; - private const int StatePage2 = 0x001000; - private const int StateRamRd = 0x002000; - private const int StateRamWrt = 0x004000; - private const int StateSlotC3Rom = 0x008000; - private const int StateIntC8Rom = 0x010000; // [5-28] - private const int StateIntCXRom = 0x020000; - private const int StateAn0 = 0x040000; - private const int StateAn1 = 0x080000; - private const int StateAn2 = 0x100000; - private const int StateAn3 = 0x200000; - private const int StateVideo = State80Col | StateText | StateMixed | StateHires | StateDRes; - - private const int StateVideoModeCount = 32; - - private static readonly int[] StateVideoMode = new int[StateVideoModeCount] - { - Video.Mode0, Video.Mode0, Video.Mode1, Video.Mode2, Video.Mode3, Video.Mode4, Video.Mode1, Video.Mode2, - Video.Mode5, Video.Mode5, Video.Mode1, Video.Mode2, Video.Mode6, Video.Mode7, Video.Mode1, Video.Mode2, - Video.Mode8, Video.Mode9, Video.Mode1, Video.Mode2, Video.ModeA, Video.ModeB, Video.Mode1, Video.Mode2, - Video.ModeC, Video.ModeD, Video.Mode1, Video.Mode2, Video.ModeE, Video.ModeF, Video.Mode1, Video.Mode2 - }; - - private readonly Action[][][] WriteRamModeBankRegion; - } -} +using System; + +namespace Jellyfish.Virtu +{ + public partial class Memory + { + private const int BankCount = 2; + + private const int BankMain = 0; + private const int BankAux = 1; + + private const int RegionCount = 12; + + private const int Region0001 = 0; + private const int Region02BF = 1; + private const int Region0407 = 2; + private const int Region080B = 3; + private const int Region203F = 4; + private const int Region405F = 5; + private const int RegionC0C0 = 6; + private const int RegionC1C7 = 7; + private const int RegionC3C3 = 8; + private const int RegionC8CF = 9; + private const int RegionD0DF = 10; + private const int RegionE0FF = 11; + + private static readonly int[] RegionBaseAddress = new int[RegionCount] + { + 0x0000, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0xC000, 0xC100, 0xC100, 0xC100, 0xD000, 0xE000 + }; + + private const int PageCount = 256; + + private static readonly int[] PageRegion = new int[PageCount] + { + Region0001, Region0001, Region02BF, Region02BF, Region0407, Region0407, Region0407, Region0407, + Region080B, Region080B, Region080B, Region080B, Region02BF, Region02BF, Region02BF, Region02BF, + Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, + Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, + Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, + Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, + Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, + Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, Region203F, + Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, + Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, + Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, + Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, Region405F, + Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, + Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, + Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, + Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, + Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, + Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, + Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, + Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, + Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, + Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, + Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, + Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, Region02BF, + RegionC0C0, RegionC1C7, RegionC1C7, RegionC3C3, RegionC1C7, RegionC1C7, RegionC1C7, RegionC1C7, + RegionC8CF, RegionC8CF, RegionC8CF, RegionC8CF, RegionC8CF, RegionC8CF, RegionC8CF, RegionC8CF, + RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, + RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, RegionD0DF, + RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, + RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, + RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, + RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF, RegionE0FF + }; + + private const int State80Col = 0x000001; + private const int StateText = 0x000002; + private const int StateMixed = 0x000004; + private const int StateHires = 0x000008; + private const int StateDRes = 0x000010; + private const int State80Store = 0x000020; + private const int StateAltChrSet = 0x000040; + private const int StateAltZP = 0x000080; + private const int StateBank1 = 0x000100; + private const int StateHRamRd = 0x000200; + private const int StateHRamPreWrt = 0x000400; + private const int StateHRamWrt = 0x000800; + private const int StatePage2 = 0x001000; + private const int StateRamRd = 0x002000; + private const int StateRamWrt = 0x004000; + private const int StateSlotC3Rom = 0x008000; + private const int StateIntC8Rom = 0x010000; // [5-28] + private const int StateIntCXRom = 0x020000; + private const int StateAn0 = 0x040000; + private const int StateAn1 = 0x080000; + private const int StateAn2 = 0x100000; + private const int StateAn3 = 0x200000; + private const int StateVideo = State80Col | StateText | StateMixed | StateHires | StateDRes; + + private const int StateVideoModeCount = 32; + + private static readonly int[] StateVideoMode = new int[StateVideoModeCount] + { + Video.Mode0, Video.Mode0, Video.Mode1, Video.Mode2, Video.Mode3, Video.Mode4, Video.Mode1, Video.Mode2, + Video.Mode5, Video.Mode5, Video.Mode1, Video.Mode2, Video.Mode6, Video.Mode7, Video.Mode1, Video.Mode2, + Video.Mode8, Video.Mode9, Video.Mode1, Video.Mode2, Video.ModeA, Video.ModeB, Video.Mode1, Video.Mode2, + Video.ModeC, Video.ModeD, Video.Mode1, Video.Mode2, Video.ModeE, Video.ModeF, Video.Mode1, Video.Mode2 + }; + + private readonly Action[][][] WriteRamModeBankRegion; + } +} diff --git a/Virtu/NoSlotClock.cs b/Virtu/NoSlotClock.cs index 9ff1292..6e0a298 100644 --- a/Virtu/NoSlotClock.cs +++ b/Virtu/NoSlotClock.cs @@ -1,228 +1,228 @@ -using System; -using System.IO; - -namespace Jellyfish.Virtu -{ - public sealed class NoSlotClock : MachineComponent - { - public NoSlotClock(Machine machine) : - base(machine) - { - } - - 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) - { - // this may read or write the clock - if ((address & 0x4) != 0) - { - return ReadClock(data); - } - - WriteClock(address); - return data; - } - - public void Write(int address) - { - // this may read or write the clock - if ((address & 0x4) != 0) - { - ReadClock(0); - } - else - { - WriteClock(address); - } - } - - private int ReadClock(int data) - { - // for a ROM, A2 high = read, and data out (if any) is on D0 - if (!_clockEnabled) - { - _comparisonRegister.Reset(); - _writeEnabled = true; - return data; - } - - data = _clockRegister.ReadBit(Machine.Video.ReadFloatingBus()); - if (_clockRegister.NextBit()) - { - _clockEnabled = false; - } - return data; - } - - private void WriteClock(int address) - { - // for a ROM, A2 low = write, and data in is on A0 - if (!_writeEnabled) - { - return; - } - - if (!_clockEnabled) - { - if ((_comparisonRegister.CompareBit(address))) - { - if (_comparisonRegister.NextBit()) - { - _clockEnabled = true; - PopulateClockRegister(); - } - } - else - { - // mismatch ignores further writes - _writeEnabled = false; - } - } - else if (_clockRegister.NextBit()) - { - // simulate writes, but our clock register is read-only - _clockEnabled = false; - } - } - - private void PopulateClockRegister() - { - // all values are in packed BCD format (4 bits per decimal digit) - var now = DateTime.Now; - - int centisecond = now.Millisecond / 10; // 00-99 - _clockRegister.WriteNibble(centisecond % 10); - _clockRegister.WriteNibble(centisecond / 10); - - int second = now.Second; // 00-59 - _clockRegister.WriteNibble(second % 10); - _clockRegister.WriteNibble(second / 10); - - int minute = now.Minute; // 00-59 - _clockRegister.WriteNibble(minute % 10); - _clockRegister.WriteNibble(minute / 10); - - int hour = now.Hour; // 01-23 - _clockRegister.WriteNibble(hour % 10); - _clockRegister.WriteNibble(hour / 10); - - int day = (int)now.DayOfWeek + 1; // 01-07 (1 = Sunday) - _clockRegister.WriteNibble(day % 10); - _clockRegister.WriteNibble(day / 10); - - int date = now.Day; // 01-31 - _clockRegister.WriteNibble(date % 10); - _clockRegister.WriteNibble(date / 10); - - int month = now.Month; // 01-12 - _clockRegister.WriteNibble(month % 10); - _clockRegister.WriteNibble(month / 10); - - int year = now.Year % 100; // 00-99 - _clockRegister.WriteNibble(year % 10); - _clockRegister.WriteNibble(year / 10); - } - - private const ulong ClockInitSequence = 0x5CA33AC55CA33AC5; - - private bool _clockEnabled; - private bool _writeEnabled; - private RingRegister _clockRegister; - private RingRegister _comparisonRegister; - - private struct RingRegister - { - public RingRegister(ulong data, ulong mask) - { - _data = data; - _mask = mask; - } - - public void Reset() - { - _mask = 0x1; - } - - public void WriteNibble(int data) - { - WriteBits(data, 4); - } - - public void WriteBits(int data, int count) - { - for (int i = 1; i <= count; i++) - { - WriteBit(data); - NextBit(); - data >>= 1; - } - } - - public void WriteBit(int data) - { - _data = ((data & 0x1) != 0) ? (_data | _mask) : (_data & ~_mask); - } - - public int ReadBit(int data) - { - return ((_data & _mask) != 0) ? (data | 0x1) : (data & ~0x1); - } - - public bool CompareBit(int data) - { - return (((_data & _mask) != 0) == ((data & 0x1) != 0)); - } - - public bool NextBit() - { - if ((_mask <<= 1) == 0) - { - _mask = 0x1; - return true; // wrap - } - return false; - } - - public ulong Data { get { return _data; } } // no auto props - public ulong Mask { get { return _mask; } } - - private ulong _data; - private ulong _mask; - } - } -} +using System; +using System.IO; + +namespace Jellyfish.Virtu +{ + public sealed class NoSlotClock : MachineComponent + { + public NoSlotClock(Machine machine) : + base(machine) + { + } + + 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) + { + // this may read or write the clock + if ((address & 0x4) != 0) + { + return ReadClock(data); + } + + WriteClock(address); + return data; + } + + public void Write(int address) + { + // this may read or write the clock + if ((address & 0x4) != 0) + { + ReadClock(0); + } + else + { + WriteClock(address); + } + } + + private int ReadClock(int data) + { + // for a ROM, A2 high = read, and data out (if any) is on D0 + if (!_clockEnabled) + { + _comparisonRegister.Reset(); + _writeEnabled = true; + return data; + } + + data = _clockRegister.ReadBit(Machine.Video.ReadFloatingBus()); + if (_clockRegister.NextBit()) + { + _clockEnabled = false; + } + return data; + } + + private void WriteClock(int address) + { + // for a ROM, A2 low = write, and data in is on A0 + if (!_writeEnabled) + { + return; + } + + if (!_clockEnabled) + { + if ((_comparisonRegister.CompareBit(address))) + { + if (_comparisonRegister.NextBit()) + { + _clockEnabled = true; + PopulateClockRegister(); + } + } + else + { + // mismatch ignores further writes + _writeEnabled = false; + } + } + else if (_clockRegister.NextBit()) + { + // simulate writes, but our clock register is read-only + _clockEnabled = false; + } + } + + private void PopulateClockRegister() + { + // all values are in packed BCD format (4 bits per decimal digit) + var now = DateTime.Now; + + int centisecond = now.Millisecond / 10; // 00-99 + _clockRegister.WriteNibble(centisecond % 10); + _clockRegister.WriteNibble(centisecond / 10); + + int second = now.Second; // 00-59 + _clockRegister.WriteNibble(second % 10); + _clockRegister.WriteNibble(second / 10); + + int minute = now.Minute; // 00-59 + _clockRegister.WriteNibble(minute % 10); + _clockRegister.WriteNibble(minute / 10); + + int hour = now.Hour; // 01-23 + _clockRegister.WriteNibble(hour % 10); + _clockRegister.WriteNibble(hour / 10); + + int day = (int)now.DayOfWeek + 1; // 01-07 (1 = Sunday) + _clockRegister.WriteNibble(day % 10); + _clockRegister.WriteNibble(day / 10); + + int date = now.Day; // 01-31 + _clockRegister.WriteNibble(date % 10); + _clockRegister.WriteNibble(date / 10); + + int month = now.Month; // 01-12 + _clockRegister.WriteNibble(month % 10); + _clockRegister.WriteNibble(month / 10); + + int year = now.Year % 100; // 00-99 + _clockRegister.WriteNibble(year % 10); + _clockRegister.WriteNibble(year / 10); + } + + private const ulong ClockInitSequence = 0x5CA33AC55CA33AC5; + + private bool _clockEnabled; + private bool _writeEnabled; + private RingRegister _clockRegister; + private RingRegister _comparisonRegister; + + private struct RingRegister + { + public RingRegister(ulong data, ulong mask) + { + _data = data; + _mask = mask; + } + + public void Reset() + { + _mask = 0x1; + } + + public void WriteNibble(int data) + { + WriteBits(data, 4); + } + + public void WriteBits(int data, int count) + { + for (int i = 1; i <= count; i++) + { + WriteBit(data); + NextBit(); + data >>= 1; + } + } + + public void WriteBit(int data) + { + _data = ((data & 0x1) != 0) ? (_data | _mask) : (_data & ~_mask); + } + + public int ReadBit(int data) + { + return ((_data & _mask) != 0) ? (data | 0x1) : (data & ~0x1); + } + + public bool CompareBit(int data) + { + return (((_data & _mask) != 0) == ((data & 0x1) != 0)); + } + + public bool NextBit() + { + if ((_mask <<= 1) == 0) + { + _mask = 0x1; + return true; // wrap + } + return false; + } + + public ulong Data { get { return _data; } } // no auto props + public ulong Mask { get { return _mask; } } + + private ulong _data; + private ulong _mask; + } + } +} diff --git a/Virtu/PeripheralCard.cs b/Virtu/PeripheralCard.cs index 662f61e..7aa7b23 100644 --- a/Virtu/PeripheralCard.cs +++ b/Virtu/PeripheralCard.cs @@ -1,48 +1,48 @@ -namespace Jellyfish.Virtu -{ - public class PeripheralCard : MachineComponent - { - public PeripheralCard(Machine machine) : - base(machine) - { - } - - public virtual int ReadIoRegionC0C0(int address) - { - // read Device Select' address $C0nX; n = slot number + 8 - return ReadFloatingBus(); - } - - public virtual int ReadIoRegionC1C7(int address) - { - // read I/O Select' address $CsXX; s = slot number - return ReadFloatingBus(); - } - - public virtual int ReadIoRegionC8CF(int address) - { - // read I/O Strobe' address $C800-$CFFF - return ReadFloatingBus(); - } - - public virtual void WriteIoRegionC0C0(int address, int data) - { - // write Device Select' address $C0nX; n = slot number + 8 - } - - public virtual void WriteIoRegionC1C7(int address, int data) - { - // write I/O Select' address $CsXX; s = slot number - } - - public virtual void WriteIoRegionC8CF(int address, int data) - { - // write I/O Strobe' address $C800-$CFFF - } - - protected int ReadFloatingBus() - { - return Machine.Video.ReadFloatingBus(); - } - } -} +namespace Jellyfish.Virtu +{ + public class PeripheralCard : MachineComponent + { + public PeripheralCard(Machine machine) : + base(machine) + { + } + + public virtual int ReadIoRegionC0C0(int address) + { + // read Device Select' address $C0nX; n = slot number + 8 + return ReadFloatingBus(); + } + + public virtual int ReadIoRegionC1C7(int address) + { + // read I/O Select' address $CsXX; s = slot number + return ReadFloatingBus(); + } + + public virtual int ReadIoRegionC8CF(int address) + { + // read I/O Strobe' address $C800-$CFFF + return ReadFloatingBus(); + } + + public virtual void WriteIoRegionC0C0(int address, int data) + { + // write Device Select' address $C0nX; n = slot number + 8 + } + + public virtual void WriteIoRegionC1C7(int address, int data) + { + // write I/O Select' address $CsXX; s = slot number + } + + public virtual void WriteIoRegionC8CF(int address, int data) + { + // write I/O Strobe' address $C800-$CFFF + } + + protected int ReadFloatingBus() + { + return Machine.Video.ReadFloatingBus(); + } + } +} diff --git a/Virtu/Properties/Strings.Designer.cs b/Virtu/Properties/Strings.Designer.cs index c2fae9e..311e203 100644 --- a/Virtu/Properties/Strings.Designer.cs +++ b/Virtu/Properties/Strings.Designer.cs @@ -1,108 +1,108 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.17626 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Jellyfish.Virtu.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Strings { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Strings() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Jellyfish.Virtu.Properties.Strings", typeof(Strings).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// 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.. - /// - internal static string ResourceNotFound { - get { - return ResourceManager.GetString("ResourceNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Service type '{0}' already present.. - /// - internal static string ServiceAlreadyPresent { - get { - return ResourceManager.GetString("ServiceAlreadyPresent", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Service type '{0}' must be assignable from service provider '{1}'.. - /// - internal static string ServiceMustBeAssignable { - get { - return ResourceManager.GetString("ServiceMustBeAssignable", resourceCulture); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.17626 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Jellyfish.Virtu.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Strings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Strings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Jellyfish.Virtu.Properties.Strings", typeof(Strings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 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.. + /// + internal static string ResourceNotFound { + get { + return ResourceManager.GetString("ResourceNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Service type '{0}' already present.. + /// + internal static string ServiceAlreadyPresent { + get { + return ResourceManager.GetString("ServiceAlreadyPresent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Service type '{0}' must be assignable from service provider '{1}'.. + /// + internal static string ServiceMustBeAssignable { + get { + return ResourceManager.GetString("ServiceMustBeAssignable", resourceCulture); + } + } + } +} diff --git a/Virtu/Properties/Strings.resx b/Virtu/Properties/Strings.resx index 90993f2..4a8b2bb 100644 --- a/Virtu/Properties/Strings.resx +++ b/Virtu/Properties/Strings.resx @@ -1,135 +1,135 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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. - - - Service type '{0}' already present. - - - Service type '{0}' must be assignable from service provider '{1}'. - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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. + + + Service type '{0}' already present. + + + Service type '{0}' must be assignable from service provider '{1}'. + \ No newline at end of file diff --git a/Virtu/Services/AudioService.cs b/Virtu/Services/AudioService.cs index 8f457e2..1928e30 100644 --- a/Virtu/Services/AudioService.cs +++ b/Virtu/Services/AudioService.cs @@ -1,66 +1,66 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Threading; -using Jellyfish.Library; - -namespace Jellyfish.Virtu.Services -{ - public abstract class AudioService : MachineService - { - protected AudioService(Machine machine) : - base(machine) - { - } - - public void Output(int data) // machine thread - { - if (BitConverter.IsLittleEndian) - { - _buffer[_index + 0] = (byte)(data & 0xFF); - _buffer[_index + 1] = (byte)(data >> 8); - } - else - { - _buffer[_index + 0] = (byte)(data >> 8); - _buffer[_index + 1] = (byte)(data & 0xFF); - } - _index = (_index + 2) % SampleSize; - if (_index == 0) - { - if (Machine.Cpu.IsThrottled) - { - _writeEvent.WaitOne(SampleLatency * 2); // allow timeout; avoids deadlock - } - } - } - - public void Reset() - { - Buffer.BlockCopy(SampleZero, 0, _buffer, 0, SampleSize); - } - - public abstract void SetVolume(float volume); - - protected void Update() // audio thread - { - _writeEvent.Set(); - } - - public const int SampleRate = 44100; // hz - public const int SampleChannels = 1; - public const int SampleBits = 16; - public const int SampleLatency = 40; // ms - public const int SampleSize = (SampleRate * SampleLatency / 1000) * SampleChannels * (SampleBits / 8); - - [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 _writeEvent = new AutoResetEvent(false); - } -} +using System; +using System.Diagnostics.CodeAnalysis; +using System.Threading; +using Jellyfish.Library; + +namespace Jellyfish.Virtu.Services +{ + public abstract class AudioService : MachineService + { + protected AudioService(Machine machine) : + base(machine) + { + } + + public void Output(int data) // machine thread + { + if (BitConverter.IsLittleEndian) + { + _buffer[_index + 0] = (byte)(data & 0xFF); + _buffer[_index + 1] = (byte)(data >> 8); + } + else + { + _buffer[_index + 0] = (byte)(data >> 8); + _buffer[_index + 1] = (byte)(data & 0xFF); + } + _index = (_index + 2) % SampleSize; + if (_index == 0) + { + if (Machine.Cpu.IsThrottled) + { + _writeEvent.WaitOne(SampleLatency * 2); // allow timeout; avoids deadlock + } + } + } + + public void Reset() + { + Buffer.BlockCopy(SampleZero, 0, _buffer, 0, SampleSize); + } + + public abstract void SetVolume(float volume); + + protected void Update() // audio thread + { + _writeEvent.Set(); + } + + public const int SampleRate = 44100; // hz + public const int SampleChannels = 1; + public const int SampleBits = 16; + public const int SampleLatency = 40; // ms + public const int SampleSize = (SampleRate * SampleLatency / 1000) * SampleChannels * (SampleBits / 8); + + [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 _writeEvent = new AutoResetEvent(false); + } +} diff --git a/Virtu/Services/DebugService.cs b/Virtu/Services/DebugService.cs index ecdef36..e562e9f 100644 --- a/Virtu/Services/DebugService.cs +++ b/Virtu/Services/DebugService.cs @@ -1,63 +1,63 @@ -using System; -using System.Diagnostics; -using System.Globalization; -using System.Text; -using System.Threading; -using Jellyfish.Library; - -namespace Jellyfish.Virtu.Services -{ - public class DebugService : MachineService - { - public DebugService(Machine machine) : - base(machine) - { - } - - public void WriteMessage(string message) - { - OnWriteMessage(FormatMessage(message)); - } - - public void WriteMessage(string format, params object[] args) - { - OnWriteMessage(FormatMessage(format, args)); - } - - protected virtual void OnWriteMessage(string message) - { -#if SILVERLIGHT - 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) - { - WriteMessage("[DebugService.FormatMessage] format: {0}; args: {1}; exception: {2}", format, string.Join(", ", args), ex.Message); - } - } - 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)); - } -} +using System; +using System.Diagnostics; +using System.Globalization; +using System.Text; +using System.Threading; +using Jellyfish.Library; + +namespace Jellyfish.Virtu.Services +{ + public class DebugService : MachineService + { + public DebugService(Machine machine) : + base(machine) + { + } + + public void WriteMessage(string message) + { + OnWriteMessage(FormatMessage(message)); + } + + public void WriteMessage(string format, params object[] args) + { + OnWriteMessage(FormatMessage(format, args)); + } + + protected virtual void OnWriteMessage(string message) + { +#if SILVERLIGHT + 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) + { + WriteMessage("[DebugService.FormatMessage] format: {0}; args: {1}; exception: {2}", format, string.Join(", ", args), ex.Message); + } + } + 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/GamePortService.cs b/Virtu/Services/GamePortService.cs index abe2c4c..4ebbc74 100644 --- a/Virtu/Services/GamePortService.cs +++ b/Virtu/Services/GamePortService.cs @@ -1,139 +1,139 @@ -using System; - -namespace Jellyfish.Virtu.Services -{ - public class GamePortService : MachineService - { - public GamePortService(Machine machine) : - base(machine) - { - Paddle0 = Paddle1 = Paddle2 = Paddle3 = 255; // not connected - } - - public virtual void Update() // main thread - { - var keyboard = Machine.Keyboard; - - if (keyboard.UseGamePort) - { - UpdateKey(keyboard.Joystick0UpKey, IsJoystick0Up, ref _isJoystick0UpKeyDown, ref _wasJoystick0UpKeyDown); - UpdateKey(keyboard.Joystick0LeftKey, IsJoystick0Left, ref _isJoystick0LeftKeyDown, ref _wasJoystick0LeftKeyDown); - UpdateKey(keyboard.Joystick0RightKey, IsJoystick0Right, ref _isJoystick0RightKeyDown, ref _wasJoystick0RightKeyDown); - UpdateKey(keyboard.Joystick0DownKey, IsJoystick0Down, ref _isJoystick0DownKeyDown, ref _wasJoystick0DownKeyDown); - UpdateKey(keyboard.Joystick0UpLeftKey, IsJoystick0Up && IsJoystick0Left, ref _isJoystick0UpLeftKeyDown, ref _wasJoystick0UpLeftKeyDown); - UpdateKey(keyboard.Joystick0UpRightKey, IsJoystick0Up && IsJoystick0Right, ref _isJoystick0UpRightKeyDown, ref _wasJoystick0UpRightKeyDown); - UpdateKey(keyboard.Joystick0DownLeftKey, IsJoystick0Down && IsJoystick0Left, ref _isJoystick0DownLeftKeyDown, ref _wasJoystick0DownLeftKeyDown); - UpdateKey(keyboard.Joystick0DownRightKey, IsJoystick0Down && IsJoystick0Right, ref _isJoystick0DownRightKeyDown, ref _wasJoystick0DownRightKeyDown); - UpdateKey(keyboard.Joystick1UpKey, IsJoystick1Up, ref _isJoystick1UpKeyDown, ref _wasJoystick1UpKeyDown); - UpdateKey(keyboard.Joystick1LeftKey, IsJoystick1Left, ref _isJoystick1LeftKeyDown, ref _wasJoystick1LeftKeyDown); - UpdateKey(keyboard.Joystick1RightKey, IsJoystick1Right, ref _isJoystick1RightKeyDown, ref _wasJoystick1RightKeyDown); - UpdateKey(keyboard.Joystick1DownKey, IsJoystick1Down, ref _isJoystick1DownKeyDown, ref _wasJoystick1DownKeyDown); - UpdateKey(keyboard.Joystick1UpLeftKey, IsJoystick1Up && IsJoystick1Left, ref _isJoystick1UpLeftKeyDown, ref _wasJoystick1UpLeftKeyDown); - UpdateKey(keyboard.Joystick1UpRightKey, IsJoystick1Up && IsJoystick1Right, ref _isJoystick1UpRightKeyDown, ref _wasJoystick1UpRightKeyDown); - UpdateKey(keyboard.Joystick1DownLeftKey, IsJoystick1Down && IsJoystick1Left, ref _isJoystick1DownLeftKeyDown, ref _wasJoystick1DownLeftKeyDown); - UpdateKey(keyboard.Joystick1DownRightKey, IsJoystick1Down && IsJoystick1Right, ref _isJoystick1DownRightKeyDown, ref _wasJoystick1DownRightKeyDown); - UpdateKey(keyboard.Button0Key, IsButton0Down, ref _isButton0KeyDown, ref _wasButton0KeyDown); - UpdateKey(keyboard.Button1Key, IsButton1Down, ref _isButton1KeyDown, ref _wasButton1KeyDown); - UpdateKey(keyboard.Button2Key, IsButton2Down, ref _isButton2KeyDown, ref _wasButton2KeyDown); - - if (_lastKey > 0) // repeat last key - { - long time = DateTime.UtcNow.Ticks; - if (time - _lastTime >= _repeatTime) - { - _lastTime = time; - _repeatTime = RepeatSpeed; - keyboard.Latch = _lastKey; - } - } - } - } - - private void UpdateKey(int key, bool isActive, ref bool isKeyDown, ref bool wasKeyDown) - { - wasKeyDown = isKeyDown; - isKeyDown = (key > 0) && isActive; - - if (isKeyDown != wasKeyDown) - { - if (isKeyDown) - { - _lastKey = key; - _lastTime = DateTime.UtcNow.Ticks; - _repeatTime = RepeatDelay; - Machine.Keyboard.Latch = key; - } - else if (key == _lastKey) - { - _lastKey = 0; - } - } - } - - public int Paddle0 { get; protected set; } - public int Paddle1 { get; protected set; } - public int Paddle2 { get; protected set; } - public int Paddle3 { 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; } - public bool IsButton2Down { get; protected set; } - - private static readonly long RepeatDelay = TimeSpan.FromMilliseconds(500).Ticks; - private static readonly long RepeatSpeed = TimeSpan.FromMilliseconds(32).Ticks; - - private bool _isJoystick0UpLeftKeyDown; - private bool _isJoystick0UpKeyDown; - private bool _isJoystick0UpRightKeyDown; - private bool _isJoystick0LeftKeyDown; - private bool _isJoystick0RightKeyDown; - private bool _isJoystick0DownLeftKeyDown; - private bool _isJoystick0DownKeyDown; - private bool _isJoystick0DownRightKeyDown; - private bool _isJoystick1UpLeftKeyDown; - private bool _isJoystick1UpKeyDown; - private bool _isJoystick1UpRightKeyDown; - private bool _isJoystick1LeftKeyDown; - private bool _isJoystick1RightKeyDown; - private bool _isJoystick1DownLeftKeyDown; - private bool _isJoystick1DownKeyDown; - private bool _isJoystick1DownRightKeyDown; - private bool _isButton0KeyDown; - private bool _isButton1KeyDown; - private bool _isButton2KeyDown; - - private bool _wasJoystick0UpLeftKeyDown; - private bool _wasJoystick0UpKeyDown; - private bool _wasJoystick0UpRightKeyDown; - private bool _wasJoystick0LeftKeyDown; - private bool _wasJoystick0RightKeyDown; - private bool _wasJoystick0DownLeftKeyDown; - private bool _wasJoystick0DownKeyDown; - private bool _wasJoystick0DownRightKeyDown; - private bool _wasJoystick1UpLeftKeyDown; - private bool _wasJoystick1UpKeyDown; - private bool _wasJoystick1UpRightKeyDown; - private bool _wasJoystick1LeftKeyDown; - private bool _wasJoystick1RightKeyDown; - private bool _wasJoystick1DownLeftKeyDown; - private bool _wasJoystick1DownKeyDown; - private bool _wasJoystick1DownRightKeyDown; - private bool _wasButton0KeyDown; - private bool _wasButton1KeyDown; - private bool _wasButton2KeyDown; - - private int _lastKey; - private long _lastTime; - private long _repeatTime; - } -} +using System; + +namespace Jellyfish.Virtu.Services +{ + public class GamePortService : MachineService + { + public GamePortService(Machine machine) : + base(machine) + { + Paddle0 = Paddle1 = Paddle2 = Paddle3 = 255; // not connected + } + + public virtual void Update() // main thread + { + var keyboard = Machine.Keyboard; + + if (keyboard.UseGamePort) + { + UpdateKey(keyboard.Joystick0UpKey, IsJoystick0Up, ref _isJoystick0UpKeyDown, ref _wasJoystick0UpKeyDown); + UpdateKey(keyboard.Joystick0LeftKey, IsJoystick0Left, ref _isJoystick0LeftKeyDown, ref _wasJoystick0LeftKeyDown); + UpdateKey(keyboard.Joystick0RightKey, IsJoystick0Right, ref _isJoystick0RightKeyDown, ref _wasJoystick0RightKeyDown); + UpdateKey(keyboard.Joystick0DownKey, IsJoystick0Down, ref _isJoystick0DownKeyDown, ref _wasJoystick0DownKeyDown); + UpdateKey(keyboard.Joystick0UpLeftKey, IsJoystick0Up && IsJoystick0Left, ref _isJoystick0UpLeftKeyDown, ref _wasJoystick0UpLeftKeyDown); + UpdateKey(keyboard.Joystick0UpRightKey, IsJoystick0Up && IsJoystick0Right, ref _isJoystick0UpRightKeyDown, ref _wasJoystick0UpRightKeyDown); + UpdateKey(keyboard.Joystick0DownLeftKey, IsJoystick0Down && IsJoystick0Left, ref _isJoystick0DownLeftKeyDown, ref _wasJoystick0DownLeftKeyDown); + UpdateKey(keyboard.Joystick0DownRightKey, IsJoystick0Down && IsJoystick0Right, ref _isJoystick0DownRightKeyDown, ref _wasJoystick0DownRightKeyDown); + UpdateKey(keyboard.Joystick1UpKey, IsJoystick1Up, ref _isJoystick1UpKeyDown, ref _wasJoystick1UpKeyDown); + UpdateKey(keyboard.Joystick1LeftKey, IsJoystick1Left, ref _isJoystick1LeftKeyDown, ref _wasJoystick1LeftKeyDown); + UpdateKey(keyboard.Joystick1RightKey, IsJoystick1Right, ref _isJoystick1RightKeyDown, ref _wasJoystick1RightKeyDown); + UpdateKey(keyboard.Joystick1DownKey, IsJoystick1Down, ref _isJoystick1DownKeyDown, ref _wasJoystick1DownKeyDown); + UpdateKey(keyboard.Joystick1UpLeftKey, IsJoystick1Up && IsJoystick1Left, ref _isJoystick1UpLeftKeyDown, ref _wasJoystick1UpLeftKeyDown); + UpdateKey(keyboard.Joystick1UpRightKey, IsJoystick1Up && IsJoystick1Right, ref _isJoystick1UpRightKeyDown, ref _wasJoystick1UpRightKeyDown); + UpdateKey(keyboard.Joystick1DownLeftKey, IsJoystick1Down && IsJoystick1Left, ref _isJoystick1DownLeftKeyDown, ref _wasJoystick1DownLeftKeyDown); + UpdateKey(keyboard.Joystick1DownRightKey, IsJoystick1Down && IsJoystick1Right, ref _isJoystick1DownRightKeyDown, ref _wasJoystick1DownRightKeyDown); + UpdateKey(keyboard.Button0Key, IsButton0Down, ref _isButton0KeyDown, ref _wasButton0KeyDown); + UpdateKey(keyboard.Button1Key, IsButton1Down, ref _isButton1KeyDown, ref _wasButton1KeyDown); + UpdateKey(keyboard.Button2Key, IsButton2Down, ref _isButton2KeyDown, ref _wasButton2KeyDown); + + if (_lastKey > 0) // repeat last key + { + long time = DateTime.UtcNow.Ticks; + if (time - _lastTime >= _repeatTime) + { + _lastTime = time; + _repeatTime = RepeatSpeed; + keyboard.Latch = _lastKey; + } + } + } + } + + private void UpdateKey(int key, bool isActive, ref bool isKeyDown, ref bool wasKeyDown) + { + wasKeyDown = isKeyDown; + isKeyDown = (key > 0) && isActive; + + if (isKeyDown != wasKeyDown) + { + if (isKeyDown) + { + _lastKey = key; + _lastTime = DateTime.UtcNow.Ticks; + _repeatTime = RepeatDelay; + Machine.Keyboard.Latch = key; + } + else if (key == _lastKey) + { + _lastKey = 0; + } + } + } + + public int Paddle0 { get; protected set; } + public int Paddle1 { get; protected set; } + public int Paddle2 { get; protected set; } + public int Paddle3 { 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; } + public bool IsButton2Down { get; protected set; } + + private static readonly long RepeatDelay = TimeSpan.FromMilliseconds(500).Ticks; + private static readonly long RepeatSpeed = TimeSpan.FromMilliseconds(32).Ticks; + + private bool _isJoystick0UpLeftKeyDown; + private bool _isJoystick0UpKeyDown; + private bool _isJoystick0UpRightKeyDown; + private bool _isJoystick0LeftKeyDown; + private bool _isJoystick0RightKeyDown; + private bool _isJoystick0DownLeftKeyDown; + private bool _isJoystick0DownKeyDown; + private bool _isJoystick0DownRightKeyDown; + private bool _isJoystick1UpLeftKeyDown; + private bool _isJoystick1UpKeyDown; + private bool _isJoystick1UpRightKeyDown; + private bool _isJoystick1LeftKeyDown; + private bool _isJoystick1RightKeyDown; + private bool _isJoystick1DownLeftKeyDown; + private bool _isJoystick1DownKeyDown; + private bool _isJoystick1DownRightKeyDown; + private bool _isButton0KeyDown; + private bool _isButton1KeyDown; + private bool _isButton2KeyDown; + + private bool _wasJoystick0UpLeftKeyDown; + private bool _wasJoystick0UpKeyDown; + private bool _wasJoystick0UpRightKeyDown; + private bool _wasJoystick0LeftKeyDown; + private bool _wasJoystick0RightKeyDown; + private bool _wasJoystick0DownLeftKeyDown; + private bool _wasJoystick0DownKeyDown; + private bool _wasJoystick0DownRightKeyDown; + private bool _wasJoystick1UpLeftKeyDown; + private bool _wasJoystick1UpKeyDown; + private bool _wasJoystick1UpRightKeyDown; + private bool _wasJoystick1LeftKeyDown; + private bool _wasJoystick1RightKeyDown; + private bool _wasJoystick1DownLeftKeyDown; + private bool _wasJoystick1DownKeyDown; + private bool _wasJoystick1DownRightKeyDown; + private bool _wasButton0KeyDown; + private bool _wasButton1KeyDown; + private bool _wasButton2KeyDown; + + private int _lastKey; + private long _lastTime; + private long _repeatTime; + } +} diff --git a/Virtu/Services/IsolatedStorageService.cs b/Virtu/Services/IsolatedStorageService.cs index 68159a9..f8c0c14 100644 --- a/Virtu/Services/IsolatedStorageService.cs +++ b/Virtu/Services/IsolatedStorageService.cs @@ -1,53 +1,53 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.IO.IsolatedStorage; - -namespace Jellyfish.Virtu.Services -{ - public class IsolatedStorageService : StorageService - { - public IsolatedStorageService(Machine machine) : - base(machine) - { - } - - protected override void OnLoad(string fileName, Action reader) - { - if (reader == null) - { - throw new ArgumentNullException("reader"); - } - - using (var store = GetStore()) - { - using (var stream = store.OpenFile(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) - { - reader(stream); - } - } - } - - protected override void OnSave(string fileName, Action writer) - { - if (writer == null) - { - throw new ArgumentNullException("writer"); - } - - using (var store = GetStore()) - { - using (var stream = store.OpenFile(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) - { - writer(stream); - } - } - } - - [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] - protected virtual IsolatedStorageFile GetStore() - { - return IsolatedStorageFile.GetUserStoreForApplication(); - } - } -} +using System; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.IO.IsolatedStorage; + +namespace Jellyfish.Virtu.Services +{ + public class IsolatedStorageService : StorageService + { + public IsolatedStorageService(Machine machine) : + base(machine) + { + } + + protected override void OnLoad(string fileName, Action reader) + { + if (reader == null) + { + throw new ArgumentNullException("reader"); + } + + using (var store = GetStore()) + { + using (var stream = store.OpenFile(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + reader(stream); + } + } + } + + protected override void OnSave(string fileName, Action writer) + { + if (writer == null) + { + throw new ArgumentNullException("writer"); + } + + using (var store = GetStore()) + { + using (var stream = store.OpenFile(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) + { + writer(stream); + } + } + } + + [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] + protected virtual IsolatedStorageFile GetStore() + { + return IsolatedStorageFile.GetUserStoreForApplication(); + } + } +} diff --git a/Virtu/Services/KeyboardService.cs b/Virtu/Services/KeyboardService.cs index 6068f47..bf7ee46 100644 --- a/Virtu/Services/KeyboardService.cs +++ b/Virtu/Services/KeyboardService.cs @@ -1,43 +1,43 @@ -namespace Jellyfish.Virtu.Services -{ - public abstract class KeyboardService : MachineService - { - protected KeyboardService(Machine machine) : - base(machine) - { - } - - public abstract bool IsKeyDown(int key); - - public virtual void Update() // main thread - { - var keyboard = Machine.Keyboard; - - if (IsResetKeyDown && !keyboard.DisableResetKey) - { - if (!_resetKeyDown) - { - _resetKeyDown = true; // entering reset; pause until key released - Machine.Pause(); - Machine.Reset(); - } - } - else if (_resetKeyDown) - { - _resetKeyDown = false; // leaving reset - Machine.Unpause(); - } - } - - public bool IsAnyKeyDown { get; protected set; } - public bool IsControlKeyDown { get; protected set; } - public bool IsShiftKeyDown { get; protected set; } - - public bool IsOpenAppleKeyDown { get; protected set; } - public bool IsCloseAppleKeyDown { get; protected set; } - - protected bool IsResetKeyDown { get; set; } - - private bool _resetKeyDown; - } -} +namespace Jellyfish.Virtu.Services +{ + public abstract class KeyboardService : MachineService + { + protected KeyboardService(Machine machine) : + base(machine) + { + } + + public abstract bool IsKeyDown(int key); + + public virtual void Update() // main thread + { + var keyboard = Machine.Keyboard; + + if (IsResetKeyDown && !keyboard.DisableResetKey) + { + if (!_resetKeyDown) + { + _resetKeyDown = true; // entering reset; pause until key released + Machine.Pause(); + Machine.Reset(); + } + } + else if (_resetKeyDown) + { + _resetKeyDown = false; // leaving reset + Machine.Unpause(); + } + } + + public bool IsAnyKeyDown { get; protected set; } + public bool IsControlKeyDown { get; protected set; } + public bool IsShiftKeyDown { get; protected set; } + + public bool IsOpenAppleKeyDown { get; protected set; } + public bool IsCloseAppleKeyDown { get; protected set; } + + protected bool IsResetKeyDown { get; set; } + + private bool _resetKeyDown; + } +} diff --git a/Virtu/Services/MachineService.cs b/Virtu/Services/MachineService.cs index 8c2b246..b287daf 100644 --- a/Virtu/Services/MachineService.cs +++ b/Virtu/Services/MachineService.cs @@ -1,20 +1,20 @@ -using System; -using Jellyfish.Library; - -namespace Jellyfish.Virtu.Services -{ - public abstract class MachineService : DisposableBase - { - protected MachineService(Machine machine) - { - Machine = machine; - - _debugService = new Lazy(() => Machine.Services.GetService()); - } - - protected Machine Machine { get; private set; } - protected DebugService DebugService { get { return _debugService.Value; } } - - private Lazy _debugService; - } -} +using System; +using Jellyfish.Library; + +namespace Jellyfish.Virtu.Services +{ + public abstract class MachineService : DisposableBase + { + protected MachineService(Machine machine) + { + Machine = machine; + + _debugService = new Lazy(() => Machine.Services.GetService()); + } + + protected Machine Machine { get; private set; } + protected DebugService DebugService { get { return _debugService.Value; } } + + private Lazy _debugService; + } +} diff --git a/Virtu/Services/MachineServices.cs b/Virtu/Services/MachineServices.cs index b8669ee..50e1884 100644 --- a/Virtu/Services/MachineServices.cs +++ b/Virtu/Services/MachineServices.cs @@ -1,51 +1,51 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using Jellyfish.Virtu.Properties; - -namespace Jellyfish.Virtu.Services -{ - public sealed class MachineServices : IServiceProvider - { - public void AddService(Type serviceType, MachineService serviceProvider) - { - if (serviceType == null) - { - throw new ArgumentNullException("serviceType"); - } - if (_serviceProviders.ContainsKey(serviceType)) - { - throw new ArgumentException(string.Format(CultureInfo.CurrentUICulture, Strings.ServiceAlreadyPresent, serviceType.FullName), "serviceType"); - } - if (serviceProvider == null) - { - throw new ArgumentNullException("serviceProvider"); - } - if (!serviceType.IsAssignableFrom(serviceProvider.GetType())) - { - throw new ArgumentException(string.Format(CultureInfo.CurrentUICulture, Strings.ServiceMustBeAssignable, serviceType.FullName, serviceProvider.GetType().FullName)); - } - - _serviceProviders.Add(serviceType, serviceProvider); - } - - [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")] - public T GetService() - { - return (T)((IServiceProvider)this).GetService(typeof(T)); - } - - public void RemoveService(Type serviceType) - { - _serviceProviders.Remove(serviceType); - } - - object IServiceProvider.GetService(Type serviceType) - { - return _serviceProviders.ContainsKey(serviceType) ? _serviceProviders[serviceType] : null; - } - - private Dictionary _serviceProviders = new Dictionary(); - } -} +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using Jellyfish.Virtu.Properties; + +namespace Jellyfish.Virtu.Services +{ + public sealed class MachineServices : IServiceProvider + { + public void AddService(Type serviceType, MachineService serviceProvider) + { + if (serviceType == null) + { + throw new ArgumentNullException("serviceType"); + } + if (_serviceProviders.ContainsKey(serviceType)) + { + throw new ArgumentException(string.Format(CultureInfo.CurrentUICulture, Strings.ServiceAlreadyPresent, serviceType.FullName), "serviceType"); + } + if (serviceProvider == null) + { + throw new ArgumentNullException("serviceProvider"); + } + if (!serviceType.IsAssignableFrom(serviceProvider.GetType())) + { + throw new ArgumentException(string.Format(CultureInfo.CurrentUICulture, Strings.ServiceMustBeAssignable, serviceType.FullName, serviceProvider.GetType().FullName)); + } + + _serviceProviders.Add(serviceType, serviceProvider); + } + + [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")] + public T GetService() + { + return (T)((IServiceProvider)this).GetService(typeof(T)); + } + + public void RemoveService(Type serviceType) + { + _serviceProviders.Remove(serviceType); + } + + object IServiceProvider.GetService(Type serviceType) + { + return _serviceProviders.ContainsKey(serviceType) ? _serviceProviders[serviceType] : null; + } + + private Dictionary _serviceProviders = new Dictionary(); + } +} diff --git a/Virtu/Services/StorageService.cs b/Virtu/Services/StorageService.cs index b1a438e..dd1b531 100644 --- a/Virtu/Services/StorageService.cs +++ b/Virtu/Services/StorageService.cs @@ -1,213 +1,213 @@ -using System; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.IO; -using System.Security; -using Jellyfish.Virtu.Properties; - -namespace Jellyfish.Virtu.Services -{ - public abstract class StorageService : MachineService - { - protected StorageService(Machine machine) : - base(machine) - { - } - - [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] - public bool Load(string fileName, Action reader) - { - try - { - DebugService.WriteMessage("Loading file '{0}'", fileName); - OnLoad(fileName, reader); - } - catch (Exception ex) - { - DebugService.WriteMessage(ex.ToString()); - return false; - } - - return true; - } - -#if !WINDOWS - [SecuritySafeCritical] -#endif - [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] - public static bool LoadFile(string fileName, Action reader) - { - if (reader == null) - { - throw new ArgumentNullException("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 ex) - { - DebugService.Default.WriteMessage(ex.ToString()); - return false; - } - - return true; - } - -#if !WINDOWS - [SecuritySafeCritical] -#endif - [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] - public static bool LoadFile(FileInfo fileInfo, Action reader) - { - if (fileInfo == null) - { - throw new ArgumentNullException("fileInfo"); - } - if (reader == null) - { - throw new ArgumentNullException("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 ex) - { - DebugService.Default.WriteMessage(ex.ToString()); - return false; - } - - return true; - } - - [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] - public static bool LoadResource(string resourceName, Action reader) - { - if (reader == null) - { - throw new ArgumentNullException("reader"); - } - - try - { - DebugService.Default.WriteMessage("Loading resource '{0}'", resourceName); - using (var stream = GetResourceStream(resourceName)) - { - reader(stream); - } - } - catch (Exception ex) - { - DebugService.Default.WriteMessage(ex.ToString()); - return false; - } - - return true; - } - - [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] - public bool Save(string fileName, Action writer) - { - try - { - DebugService.WriteMessage("Saving file '{0}'", fileName); - OnSave(fileName, writer); - } - catch (Exception ex) - { - DebugService.WriteMessage(ex.ToString()); - return false; - } - - return true; - } - -#if !WINDOWS - [SecuritySafeCritical] -#endif - [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] - public static bool SaveFile(string fileName, Action writer) - { - if (writer == null) - { - throw new ArgumentNullException("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 ex) - { - DebugService.Default.WriteMessage(ex.ToString()); - return false; - } - - return true; - } - -#if !WINDOWS - [SecuritySafeCritical] -#endif - [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] - public static bool SaveFile(FileInfo fileInfo, Action writer) - { - if (fileInfo == null) - { - throw new ArgumentNullException("fileInfo"); - } - if (writer == null) - { - throw new ArgumentNullException("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 ex) - { - DebugService.Default.WriteMessage(ex.ToString()); - return false; - } - - return true; - } - - protected abstract void OnLoad(string fileName, Action reader); - - protected abstract void OnSave(string fileName, Action writer); - - private static Stream GetResourceStream(string resourceName) - { - resourceName = "Jellyfish.Virtu." + resourceName.Replace('/', '.'); - var resourceStream = typeof(StorageService).Assembly.GetManifestResourceStream(resourceName); - if (resourceStream == null) - { - throw new FileNotFoundException(string.Format(CultureInfo.CurrentUICulture, Strings.ResourceNotFound, resourceName)); - } - - return resourceStream; - } - } -} +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.IO; +using System.Security; +using Jellyfish.Virtu.Properties; + +namespace Jellyfish.Virtu.Services +{ + public abstract class StorageService : MachineService + { + protected StorageService(Machine machine) : + base(machine) + { + } + + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + public bool Load(string fileName, Action reader) + { + try + { + DebugService.WriteMessage("Loading file '{0}'", fileName); + OnLoad(fileName, reader); + } + catch (Exception ex) + { + DebugService.WriteMessage(ex.ToString()); + return false; + } + + return true; + } + +#if !WINDOWS + [SecuritySafeCritical] +#endif + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + public static bool LoadFile(string fileName, Action reader) + { + if (reader == null) + { + throw new ArgumentNullException("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 ex) + { + DebugService.Default.WriteMessage(ex.ToString()); + return false; + } + + return true; + } + +#if !WINDOWS + [SecuritySafeCritical] +#endif + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + public static bool LoadFile(FileInfo fileInfo, Action reader) + { + if (fileInfo == null) + { + throw new ArgumentNullException("fileInfo"); + } + if (reader == null) + { + throw new ArgumentNullException("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 ex) + { + DebugService.Default.WriteMessage(ex.ToString()); + return false; + } + + return true; + } + + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + public static bool LoadResource(string resourceName, Action reader) + { + if (reader == null) + { + throw new ArgumentNullException("reader"); + } + + try + { + DebugService.Default.WriteMessage("Loading resource '{0}'", resourceName); + using (var stream = GetResourceStream(resourceName)) + { + reader(stream); + } + } + catch (Exception ex) + { + DebugService.Default.WriteMessage(ex.ToString()); + return false; + } + + return true; + } + + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + public bool Save(string fileName, Action writer) + { + try + { + DebugService.WriteMessage("Saving file '{0}'", fileName); + OnSave(fileName, writer); + } + catch (Exception ex) + { + DebugService.WriteMessage(ex.ToString()); + return false; + } + + return true; + } + +#if !WINDOWS + [SecuritySafeCritical] +#endif + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + public static bool SaveFile(string fileName, Action writer) + { + if (writer == null) + { + throw new ArgumentNullException("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 ex) + { + DebugService.Default.WriteMessage(ex.ToString()); + return false; + } + + return true; + } + +#if !WINDOWS + [SecuritySafeCritical] +#endif + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + public static bool SaveFile(FileInfo fileInfo, Action writer) + { + if (fileInfo == null) + { + throw new ArgumentNullException("fileInfo"); + } + if (writer == null) + { + throw new ArgumentNullException("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 ex) + { + DebugService.Default.WriteMessage(ex.ToString()); + return false; + } + + return true; + } + + protected abstract void OnLoad(string fileName, Action reader); + + protected abstract void OnSave(string fileName, Action writer); + + private static Stream GetResourceStream(string resourceName) + { + resourceName = "Jellyfish.Virtu." + resourceName.Replace('/', '.'); + var resourceStream = typeof(StorageService).Assembly.GetManifestResourceStream(resourceName); + if (resourceStream == null) + { + throw new FileNotFoundException(string.Format(CultureInfo.CurrentUICulture, Strings.ResourceNotFound, resourceName)); + } + + return resourceStream; + } + } +} diff --git a/Virtu/Services/VideoService.cs b/Virtu/Services/VideoService.cs index 43a81ae..79ae914 100644 --- a/Virtu/Services/VideoService.cs +++ b/Virtu/Services/VideoService.cs @@ -1,17 +1,17 @@ -namespace Jellyfish.Virtu.Services -{ - public abstract class VideoService : MachineService - { - protected VideoService(Machine machine) : - base(machine) - { - } - - public virtual void SetFullScreen(bool isFullScreen) - { - } - - public abstract void SetPixel(int x, int y, uint color); - public abstract void Update(); // main thread - } -} +namespace Jellyfish.Virtu.Services +{ + public abstract class VideoService : MachineService + { + protected VideoService(Machine machine) : + base(machine) + { + } + + public virtual void SetFullScreen(bool isFullScreen) + { + } + + public abstract void SetPixel(int x, int y, uint color); + public abstract void Update(); // main thread + } +} diff --git a/Virtu/Silverlight/Jellyfish.Virtu.Silverlight.csproj b/Virtu/Silverlight/Jellyfish.Virtu.Silverlight.csproj index ad452db..1b5f39d 100644 --- a/Virtu/Silverlight/Jellyfish.Virtu.Silverlight.csproj +++ b/Virtu/Silverlight/Jellyfish.Virtu.Silverlight.csproj @@ -1,270 +1,270 @@ - - - - Debug - AnyCPU - 8.0.50727 - 2.0 - {F8DB6D3A-807D-4E2D-92D5-469273E088DA} - {A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - Jellyfish.Virtu - Jellyfish.Virtu - Silverlight - v5.0 - - $(TargetFrameworkVersion) - true - - - true - true - Jellyfish.Virtu.xap - Properties\AppManifest.xml - Jellyfish.Virtu.MainApp - Jellyfish.Virtu.html - true - true - true - Properties\OutOfBrowserSettings.xml - false - true - - - - - - v3.5 - - - true - full - false - bin\ - DEBUG;TRACE;SILVERLIGHT;CODE_ANALYSIS - true - true - prompt - 4 - true - AllRules.ruleset - false - - - pdbonly - true - bin\ - TRACE;SILVERLIGHT;CODE_ANALYSIS - true - true - prompt - 4 - true - AllRules.ruleset - false - - - false - - - ..\..\..\Jellyfish\StrongName.snk - - - false - - - http://timestamp.verisign.com/scripts/timestamp.dll - - - 7E57BBFFA7D9A57530AC8A09E5236FE0AAB041C2 - - - ..\..\..\Jellyfish\CodeSign.pfx - - - - - - - - - - - - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - MainApp.xaml - - - MainPage.xaml - - - - - Core\Cassette.cs - - - Core\Cpu.cs - - - Core\CpuData.cs - - - Core\Disk525.cs - - - Core\DiskDsk.cs - - - Core\DiskIIController.cs - - - Core\DiskIIDrive.cs - - - Core\DiskNib.cs - - - Core\GamePort.cs - - - GlobalSuppressions.cs - - - Core\Keyboard.cs - - - Core\Machine.cs - - - Core\MachineComponent.cs - - - Core\MachineEvents.cs - - - Core\Memory.cs - - - Core\MemoryData.cs - - - Core\NoSlotClock.cs - - - Core\PeripheralCard.cs - - - Properties\Strings.Designer.cs - True - True - Strings.resx - - - Services\AudioService.cs - - - Services\DebugService.cs - - - Services\GamePortService.cs - - - Services\IsolatedStorageService.cs - - - Services\KeyboardService.cs - - - Services\MachineService.cs - - - Services\MachineServices.cs - - - Services\StorageService.cs - - - Services\VideoService.cs - - - Core\Speaker.cs - - - Core\Video.cs - - - Core\VideoData.cs - - - - - - - - - - - - - - - - - - - - Properties\Strings.resx - ResXFileCodeGenerator - Strings.Designer.cs - - - - - Disks\Default.dsk - - - Roms\AppleIIe.rom - - - Roms\DiskII.rom - - - - - CustomDictionary.xml - - - - - {99CA7796-B72A-4F8C-BCDB-0D688220A331} - Jellyfish.Library.Silverlight - - - - - - - - - - - + + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {F8DB6D3A-807D-4E2D-92D5-469273E088DA} + {A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Jellyfish.Virtu + Jellyfish.Virtu + Silverlight + v5.0 + + $(TargetFrameworkVersion) + true + + + true + true + Jellyfish.Virtu.xap + Properties\AppManifest.xml + Jellyfish.Virtu.MainApp + Jellyfish.Virtu.html + true + true + true + Properties\OutOfBrowserSettings.xml + false + true + + + + + + v3.5 + + + true + full + false + bin\ + DEBUG;TRACE;SILVERLIGHT;CODE_ANALYSIS + true + true + prompt + 4 + true + AllRules.ruleset + false + + + pdbonly + true + bin\ + TRACE;SILVERLIGHT;CODE_ANALYSIS + true + true + prompt + 4 + true + AllRules.ruleset + false + + + false + + + ..\..\..\Jellyfish\StrongName.snk + + + false + + + http://timestamp.verisign.com/scripts/timestamp.dll + + + 7E57BBFFA7D9A57530AC8A09E5236FE0AAB041C2 + + + ..\..\..\Jellyfish\CodeSign.pfx + + + + + + + + + + + + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MainApp.xaml + + + MainPage.xaml + + + + + Core\Cassette.cs + + + Core\Cpu.cs + + + Core\CpuData.cs + + + Core\Disk525.cs + + + Core\DiskDsk.cs + + + Core\DiskIIController.cs + + + Core\DiskIIDrive.cs + + + Core\DiskNib.cs + + + Core\GamePort.cs + + + GlobalSuppressions.cs + + + Core\Keyboard.cs + + + Core\Machine.cs + + + Core\MachineComponent.cs + + + Core\MachineEvents.cs + + + Core\Memory.cs + + + Core\MemoryData.cs + + + Core\NoSlotClock.cs + + + Core\PeripheralCard.cs + + + Properties\Strings.Designer.cs + True + True + Strings.resx + + + Services\AudioService.cs + + + Services\DebugService.cs + + + Services\GamePortService.cs + + + Services\IsolatedStorageService.cs + + + Services\KeyboardService.cs + + + Services\MachineService.cs + + + Services\MachineServices.cs + + + Services\StorageService.cs + + + Services\VideoService.cs + + + Core\Speaker.cs + + + Core\Video.cs + + + Core\VideoData.cs + + + + + + + + + + + + + + + + + + + + Properties\Strings.resx + ResXFileCodeGenerator + Strings.Designer.cs + + + + + Disks\Default.dsk + + + Roms\AppleIIe.rom + + + Roms\DiskII.rom + + + + + CustomDictionary.xml + + + + + {99CA7796-B72A-4F8C-BCDB-0D688220A331} + Jellyfish.Library.Silverlight + + + + + + + + + + + \ No newline at end of file diff --git a/Virtu/Silverlight/Jellyfish.Virtu.Silverlight.sln b/Virtu/Silverlight/Jellyfish.Virtu.Silverlight.sln index 0a356c6..e4fada1 100644 --- a/Virtu/Silverlight/Jellyfish.Virtu.Silverlight.sln +++ b/Virtu/Silverlight/Jellyfish.Virtu.Silverlight.sln @@ -1,26 +1,26 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Library.Silverlight", "..\..\Library\Silverlight\Jellyfish.Library.Silverlight.csproj", "{99CA7796-B72A-4F8C-BCDB-0D688220A331}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Virtu.Silverlight", "Jellyfish.Virtu.Silverlight.csproj", "{F8DB6D3A-807D-4E2D-92D5-469273E088DA}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Debug|Any CPU.Build.0 = Debug|Any CPU - {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Release|Any CPU.ActiveCfg = Release|Any CPU - {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Release|Any CPU.Build.0 = Release|Any CPU - {F8DB6D3A-807D-4E2D-92D5-469273E088DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F8DB6D3A-807D-4E2D-92D5-469273E088DA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F8DB6D3A-807D-4E2D-92D5-469273E088DA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F8DB6D3A-807D-4E2D-92D5-469273E088DA}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Library.Silverlight", "..\..\Library\Silverlight\Jellyfish.Library.Silverlight.csproj", "{99CA7796-B72A-4F8C-BCDB-0D688220A331}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfish.Virtu.Silverlight", "Jellyfish.Virtu.Silverlight.csproj", "{F8DB6D3A-807D-4E2D-92D5-469273E088DA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Debug|Any CPU.Build.0 = Debug|Any CPU + {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Release|Any CPU.ActiveCfg = Release|Any CPU + {99CA7796-B72A-4F8C-BCDB-0D688220A331}.Release|Any CPU.Build.0 = Release|Any CPU + {F8DB6D3A-807D-4E2D-92D5-469273E088DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8DB6D3A-807D-4E2D-92D5-469273E088DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8DB6D3A-807D-4E2D-92D5-469273E088DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8DB6D3A-807D-4E2D-92D5-469273E088DA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Virtu/Silverlight/MainApp.xaml b/Virtu/Silverlight/MainApp.xaml index 1cecb66..6178bd4 100644 --- a/Virtu/Silverlight/MainApp.xaml +++ b/Virtu/Silverlight/MainApp.xaml @@ -1,11 +1,11 @@ - - - - - - - + + + + + + + diff --git a/Virtu/Silverlight/MainApp.xaml.cs b/Virtu/Silverlight/MainApp.xaml.cs index 68119d8..a13a6b2 100644 --- a/Virtu/Silverlight/MainApp.xaml.cs +++ b/Virtu/Silverlight/MainApp.xaml.cs @@ -1,14 +1,14 @@ -using Jellyfish.Library; - -namespace Jellyfish.Virtu -{ - public sealed partial class MainApp : ApplicationBase - { - public MainApp() : - base("Virtu") - { - InitializeComponent(); - InitializeOutOfBrowserUpdate(); - } - } -} +using Jellyfish.Library; + +namespace Jellyfish.Virtu +{ + public sealed partial class MainApp : ApplicationBase + { + public MainApp() : + base("Virtu") + { + InitializeComponent(); + InitializeOutOfBrowserUpdate(); + } + } +} diff --git a/Virtu/Silverlight/MainPage.xaml b/Virtu/Silverlight/MainPage.xaml index 26ce27a..adb677c 100644 --- a/Virtu/Silverlight/MainPage.xaml +++ b/Virtu/Silverlight/MainPage.xaml @@ -1,23 +1,23 @@ - - - - - - - -