diff --git a/src/Spice86.Core/CLI/CommandLineParser.cs b/src/Spice86.Core/CLI/CommandLineParser.cs
index e2cd07853..a01a76fe6 100644
--- a/src/Spice86.Core/CLI/CommandLineParser.cs
+++ b/src/Spice86.Core/CLI/CommandLineParser.cs
@@ -11,17 +11,11 @@
using System.IO;
using System.Reflection;
-///
-/// Parses the command line options to create a .
-///
-public static class CommandLineParser {
- ///
- /// Parses the command line into a object.
- ///
- /// The application command line arguments
- /// A object representing the command line arguments
- /// When the command line arguments are unrecognized.
- public static Configuration ParseCommandLine(string[] args) {
+
+///
+public class CommandLineParser : ICommandLineParser {
+ ///
+ public Configuration ParseCommandLine(string[] args) {
ParserResult result = Parser.Default.ParseArguments(args);
return result.MapResult(initialConfig => {
initialConfig.Exe = ParseExePath(initialConfig.Exe);
diff --git a/src/Spice86.Core/CLI/ICommandLineParser.cs b/src/Spice86.Core/CLI/ICommandLineParser.cs
new file mode 100644
index 000000000..220c7612c
--- /dev/null
+++ b/src/Spice86.Core/CLI/ICommandLineParser.cs
@@ -0,0 +1,16 @@
+namespace Spice86.Core.CLI;
+
+using System.Diagnostics;
+
+///
+/// Parses the command line options to create a .
+///
+public interface ICommandLineParser {
+ ///
+ /// Parses the command line into a object.
+ ///
+ /// The application command line arguments
+ /// A object representing the command line arguments
+ /// When the command line arguments are unrecognized.
+ public Configuration ParseCommandLine(string[] args);
+}
diff --git a/src/Spice86/App.axaml.cs b/src/Spice86/App.axaml.cs
index 45c8d3f4e..7f34d7944 100644
--- a/src/Spice86/App.axaml.cs
+++ b/src/Spice86/App.axaml.cs
@@ -1,6 +1,7 @@
namespace Spice86;
using Avalonia;
+using Avalonia.Data.Core.Plugins;
using Avalonia.Markup.Xaml;
///
@@ -12,4 +13,12 @@ internal partial class App : Application {
/// Initializes the Spice86 UI.
///
public override void Initialize() => AvaloniaXamlLoader.Load(this);
+
+ public override void OnFrameworkInitializationCompleted() {
+ // If you use CommunityToolkit, line below is needed to remove Avalonia data validation.
+ // Without this line you will get duplicate validations from both Avalonia and CT
+ BindingPlugins.DataValidators.RemoveAt(0);
+
+ base.OnFrameworkInitializationCompleted();
+ }
}
\ No newline at end of file
diff --git a/src/Spice86/DependencyInjection/ServiceCollectionExtensions.cs b/src/Spice86/DependencyInjection/ServiceCollectionExtensions.cs
new file mode 100644
index 000000000..c32e6e61f
--- /dev/null
+++ b/src/Spice86/DependencyInjection/ServiceCollectionExtensions.cs
@@ -0,0 +1,42 @@
+namespace Spice86.DependencyInjection;
+
+using Avalonia.Controls;
+using Avalonia.Platform.Storage;
+using Avalonia.Threading;
+
+using Microsoft.Extensions.DependencyInjection;
+
+using Spice86.Core.CLI;
+using Spice86.Infrastructure;
+using Spice86.Logging;
+using Spice86.Shared.Interfaces;
+
+public static class ServiceCollectionExtensions {
+ public static void AddConfiguration(this IServiceCollection serviceCollection, string[] args) {
+ serviceCollection.AddSingleton();
+ serviceCollection.AddSingleton(serviceProvider => {
+ ICommandLineParser commandLineParser = serviceProvider.GetRequiredService();
+ return commandLineParser.ParseCommandLine(args);
+ });
+ }
+
+ public static void AddLogging(this IServiceCollection serviceCollection) {
+ serviceCollection.AddSingleton();
+ serviceCollection.AddSingleton((serviceProvider) => {
+ Configuration configuration = serviceProvider.GetRequiredService();
+ LoggerService loggerService = new LoggerService(serviceProvider.GetRequiredService());
+ Startup.SetLoggingLevel(loggerService, configuration);
+ return loggerService;
+ });
+ }
+
+ public static void AddGuiInfrastructure(this IServiceCollection serviceCollection, TopLevel mainWindow) {
+ serviceCollection.AddSingleton();
+ serviceCollection.AddSingleton();
+ serviceCollection.AddSingleton((_) => new UIDispatcher(Dispatcher.UIThread));
+ serviceCollection.AddSingleton();
+ serviceCollection.AddSingleton((_) => mainWindow.StorageProvider);
+ serviceCollection.AddSingleton();
+ serviceCollection.AddSingleton((_) => new TextClipboard(mainWindow.Clipboard));
+ }
+}
\ No newline at end of file
diff --git a/src/Spice86/Infrastructure/HostStorageProvider.cs b/src/Spice86/Infrastructure/HostStorageProvider.cs
index c53a9dc10..f6a028e04 100644
--- a/src/Spice86/Infrastructure/HostStorageProvider.cs
+++ b/src/Spice86/Infrastructure/HostStorageProvider.cs
@@ -31,11 +31,6 @@ public class HostStorageProvider : IHostStorageProvider {
return await _storageProvider.SaveFilePickerAsync(options);
}
- ///
- public async Task> OpenFilePickerAsync(FilePickerOpenOptions options) {
- return await _storageProvider.OpenFilePickerAsync(options);
- }
-
///
public async Task> OpenFolderPickerAsync(FolderPickerOpenOptions options) {
return await _storageProvider.OpenFolderPickerAsync(options);
@@ -92,27 +87,4 @@ public async Task DumpEmulatorStateToFile(Configuration configuration, IProgramE
}
}
}
-
- public async Task PickExecutableFile(string lastExecutableDirectory) {
- FilePickerOpenOptions options = new() {
- Title = "Start Executable...",
- AllowMultiple = false,
- FileTypeFilter = new[] {
- new FilePickerFileType("DOS Executables") {
- Patterns = new[] {"*.com", "*.exe", "*.EXE", "*.COM"}
- },
- new FilePickerFileType("All files") {
- Patterns = new[] {"*"}
- }
- }
- };
- IStorageFolder? folder = await TryGetWellKnownFolderAsync(WellKnownFolder.Documents);
- options.SuggestedStartLocation = folder;
- if (Directory.Exists(lastExecutableDirectory)) {
- options.SuggestedStartLocation = await TryGetFolderFromPathAsync(lastExecutableDirectory);
- }
-
- IReadOnlyList files = await OpenFilePickerAsync(options);
- return files.FirstOrDefault();
- }
}
diff --git a/src/Spice86/Infrastructure/IHostStorageProvider.cs b/src/Spice86/Infrastructure/IHostStorageProvider.cs
index f204c2c92..2c108249e 100644
--- a/src/Spice86/Infrastructure/IHostStorageProvider.cs
+++ b/src/Spice86/Infrastructure/IHostStorageProvider.cs
@@ -55,13 +55,6 @@ public interface IHostStorageProvider {
/// A list of selected folders.
Task> OpenFolderPickerAsync(FolderPickerOpenOptions options);
- ///
- /// Opens file picker dialog.
- ///
- /// The file picker configuration.
- /// A list of selected files.
- Task> OpenFilePickerAsync(FilePickerOpenOptions options);
-
///
/// Spawns the file pciker to saves a bitmap to a file.
///
@@ -76,13 +69,6 @@ public interface IHostStorageProvider {
/// The emulated program's executor, to save the emulator dump and other reverse-engineering information.
Task DumpEmulatorStateToFile(Configuration configuration, IProgramExecutor programExecutor);
- ///
- /// Spanws the file picker to pick an executable file, and returns the first file picked by the user.
- ///
- /// The directory of the last file picked, if any.
- /// The operation as an awaitable Task, containing the first picked file, or null.
- Task PickExecutableFile(string lastExecutableDirectory);
-
///
/// Spanws the file picker to save a binary file.
///
diff --git a/src/Spice86/Interfaces/IPauseStatus.cs b/src/Spice86/Interfaces/IPauseStatus.cs
index 2529f710d..a18828e7d 100644
--- a/src/Spice86/Interfaces/IPauseStatus.cs
+++ b/src/Spice86/Interfaces/IPauseStatus.cs
@@ -1,6 +1,5 @@
namespace Spice86.Interfaces;
-using Spice86.Core.Emulator.InternalDebugger;
using System.ComponentModel;
public interface IPauseStatus : INotifyPropertyChanged {
diff --git a/src/Spice86/MemoryWrappers/EmulatedMemoryStream.cs b/src/Spice86/MemoryWrappers/CodeMemoryStream.cs
similarity index 65%
rename from src/Spice86/MemoryWrappers/EmulatedMemoryStream.cs
rename to src/Spice86/MemoryWrappers/CodeMemoryStream.cs
index 257cf38b5..f6fde2620 100644
--- a/src/Spice86/MemoryWrappers/EmulatedMemoryStream.cs
+++ b/src/Spice86/MemoryWrappers/CodeMemoryStream.cs
@@ -2,16 +2,16 @@ namespace Spice86.MemoryWrappers;
using Spice86.Core.Emulator.Memory;
-public class EmulatedMemoryStream : Stream {
+public class CodeMemoryStream : Stream {
private readonly IMemory _memory;
private long _length;
private readonly bool _canRead;
private readonly bool _canWrite;
private readonly bool _canSeek;
- public EmulatedMemoryStream(IMemory memory) {
+ public CodeMemoryStream(IMemory memory) {
_memory = memory;
_length = memory.Length;
- _canWrite = true;
+ _canWrite = false;
_canSeek = true;
_canRead = true;
}
@@ -21,16 +21,10 @@ public override void Flush() {
}
public override int Read(byte[] buffer, int offset, int count) {
- int bytesRead = 0;
- for (int i = 0; i < buffer.Length; i++) {
- if (i + offset > buffer.Length || Position > _memory.Length) {
- break;
- }
- buffer[i + offset] = _memory[(uint)Position];
- bytesRead++;
- Position++;
- }
- return bytesRead;
+ byte[] ramCopy = _memory.ReadRam((uint)Math.Min(count, _memory.Length - Position), (uint)Position);
+ ramCopy.CopyTo(buffer, offset);
+ Position += ramCopy.Length;
+ return ramCopy.Length;
}
public override long Seek(long offset, SeekOrigin origin) {
@@ -53,13 +47,7 @@ public override void SetLength(long value) {
}
public override void Write(byte[] buffer, int offset, int count) {
- for (int i = 0; i < count; i++) {
- if (i + offset > buffer.Length || Position > _memory.Length) {
- break;
- }
- _memory[(uint)Position] = buffer[i + offset];
- Position++;
- }
+ throw new NotSupportedException();
}
public override bool CanRead => _canRead;
diff --git a/src/Spice86/MemoryWrappers/MemoryBinaryDocument.cs b/src/Spice86/MemoryWrappers/DataMemoryDocument.cs
similarity index 91%
rename from src/Spice86/MemoryWrappers/MemoryBinaryDocument.cs
rename to src/Spice86/MemoryWrappers/DataMemoryDocument.cs
index 8d8b4e230..c76a61b17 100644
--- a/src/Spice86/MemoryWrappers/MemoryBinaryDocument.cs
+++ b/src/Spice86/MemoryWrappers/DataMemoryDocument.cs
@@ -5,12 +5,12 @@
using System;
-public class MemoryBinaryDocument : IBinaryDocument {
+public class DataMemoryDocument : IBinaryDocument {
private readonly IMemory _memory;
private readonly uint _startAddress;
private readonly uint _endAddress;
- public MemoryBinaryDocument(IMemory memory, uint startAddress, uint endAddress) {
+ public DataMemoryDocument(IMemory memory, uint startAddress, uint endAddress) {
IsReadOnly = false;
CanInsert = false;
CanRemove = false;
diff --git a/src/Spice86/Program.cs b/src/Spice86/Program.cs
index 8fc001efb..abf73023e 100644
--- a/src/Spice86/Program.cs
+++ b/src/Spice86/Program.cs
@@ -1,19 +1,20 @@
namespace Spice86;
using Avalonia;
-using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls;
+using Avalonia.Controls.ApplicationLifetimes;
+
+using Microsoft.Extensions.DependencyInjection;
using Spice86.Core.CLI;
using Spice86.Core.Emulator;
-using Spice86.Shared.Interfaces;
+using Spice86.Core.Emulator.Devices.Timer;
+using Spice86.Core.Emulator.Function.Dump;
+using Spice86.DependencyInjection;
using Spice86.Infrastructure;
-using Avalonia.Threading;
-
-using Microsoft.Extensions.DependencyInjection;
-
-using Spice86.Logging;
+using Spice86.Shared.Interfaces;
using Spice86.ViewModels;
+using Spice86.Views;
///
/// Entry point for Spice86 application.
@@ -41,53 +42,53 @@ public class Program {
/// The command-line arguments.
[STAThread]
public static void Main(string[] args) {
- Configuration configuration = CommandLineParser.ParseCommandLine(args);
-
- var serviceCollection = new ServiceCollection();
- serviceCollection.AddSingleton();
- serviceCollection.AddSingleton();
-
+ ServiceCollection serviceCollection = InjectCommonServices(args);
+ //We need to build the service provider before retrieving the configuration service
ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
- ILoggerService loggerService = serviceProvider.GetRequiredService();
- Startup.SetLoggingLevel(loggerService, configuration);
-
- if (!configuration.HeadlessMode) {
- AppBuilder appBuilder = BuildAvaloniaApp();
- ClassicDesktopStyleApplicationLifetime desktop = SetupWithClassicDesktopLifetime(appBuilder, args);
- App? app = (App?)appBuilder.Instance;
-
- if (app is null) {
- return;
- }
-
- Views.MainWindow mainWindow = new();
- using var mainWindowViewModel = new MainWindowViewModel(new WindowService(), new AvaloniaKeyScanCodeConverter(),
- new ProgramExecutorFactory(configuration, loggerService),
- new UIDispatcher(Dispatcher.UIThread), new HostStorageProvider(mainWindow.StorageProvider),
- new TextClipboard(mainWindow.Clipboard), new UIDispatcherTimerFactory(), configuration, loggerService);
- mainWindow.DataContext = mainWindowViewModel;
- desktop.MainWindow = mainWindow;
- desktop.Start(args);
- }
- else {
- ProgramExecutor programExecutor = new(configuration, loggerService, null);
+ Configuration configuration = serviceProvider.GetRequiredService();
+ if (configuration.HeadlessMode) {
+ ProgramExecutor programExecutor = new(configuration, serviceProvider.GetRequiredService(), null);
programExecutor.Run();
+ } else {
+ ClassicDesktopStyleApplicationLifetime desktop = CreateDesktopApp();
+ MainWindow mainWindow = new();
+ serviceCollection.AddGuiInfrastructure(mainWindow);
+ //We need to rebuild the service provider after adding new services to the collection
+ using MainWindowViewModel mainWindowViewModel = serviceCollection.BuildServiceProvider().GetRequiredService();
+ StartGraphicalUserInterface(desktop, mainWindowViewModel, mainWindow, args);
}
}
-
- ///
- /// Configures and builds an Avalonia application instance.
- ///
- /// The built instance.
+
+ private static void StartGraphicalUserInterface(ClassicDesktopStyleApplicationLifetime desktop, MainWindowViewModel mainWindowViewModel, MainWindow mainWindow, string[] args) {
+ mainWindow.DataContext = mainWindowViewModel;
+ desktop.MainWindow = mainWindow;
+ desktop.Start(args);
+ }
+
+ private static ClassicDesktopStyleApplicationLifetime CreateDesktopApp() {
+ AppBuilder appBuilder = BuildAvaloniaApp();
+ ClassicDesktopStyleApplicationLifetime desktop = SetupWithClassicDesktopLifetime(appBuilder);
+ return desktop;
+ }
+
+ private static ServiceCollection InjectCommonServices(string[] args) {
+ var serviceCollection = new ServiceCollection();
+
+ serviceCollection.AddConfiguration(args);
+ serviceCollection.AddLogging();
+
+ serviceCollection.AddScoped();
+ serviceCollection.AddScoped();
+ return serviceCollection;
+ }
+
private static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure()
.UsePlatformDetect()
.LogToTrace()
.WithInterFont();
- private static ClassicDesktopStyleApplicationLifetime SetupWithClassicDesktopLifetime(
- AppBuilder builder, string[] args) {
+ private static ClassicDesktopStyleApplicationLifetime SetupWithClassicDesktopLifetime(AppBuilder builder) {
var lifetime = new ClassicDesktopStyleApplicationLifetime {
- Args = args,
ShutdownMode = ShutdownMode.OnMainWindowClose
};
builder.SetupWithLifetime(lifetime);
diff --git a/src/Spice86/ViewModels/DisassemblyViewModel.cs b/src/Spice86/ViewModels/DisassemblyViewModel.cs
index a94fa08d8..4e87c914d 100644
--- a/src/Spice86/ViewModels/DisassemblyViewModel.cs
+++ b/src/Spice86/ViewModels/DisassemblyViewModel.cs
@@ -144,7 +144,7 @@ private void UpdateDisassembly() {
return;
}
_needToUpdateDisassembly = false;
- CodeReader codeReader = CreateCodeReader(_memory, out EmulatedMemoryStream emulatedMemoryStream);
+ CodeReader codeReader = CreateCodeReader(_memory, out CodeMemoryStream emulatedMemoryStream);
Decoder decoder = InitializeDecoder(codeReader, StartAddress.Value);
try {
DecodeInstructions(_state, _memory, emulatedMemoryStream, decoder, StartAddress.Value);
@@ -153,13 +153,13 @@ private void UpdateDisassembly() {
}
}
- private void DecodeInstructions(State state, IMemory memory, EmulatedMemoryStream emulatedMemoryStream,
+ private void DecodeInstructions(State state, IMemory memory, CodeMemoryStream codeMemoryStream,
Decoder decoder, uint startAddress) {
int byteOffset = 0;
- emulatedMemoryStream.Position = startAddress;
+ codeMemoryStream.Position = startAddress;
var instructions = new List();
while (instructions.Count < NumberOfInstructionsShown) {
- long instructionAddress = emulatedMemoryStream.Position;
+ long instructionAddress = codeMemoryStream.Position;
decoder.Decode(out Instruction instruction);
CpuInstructionInfo instructionInfo = new() {
Instruction = instruction,
@@ -194,9 +194,9 @@ private Decoder InitializeDecoder(CodeReader codeReader, uint currentIp) {
return decoder;
}
- private static CodeReader CreateCodeReader(IMemory memory, out EmulatedMemoryStream emulatedMemoryStream) {
- emulatedMemoryStream = new EmulatedMemoryStream(memory);
- CodeReader codeReader = new StreamCodeReader(emulatedMemoryStream);
+ private static CodeReader CreateCodeReader(IMemory memory, out CodeMemoryStream codeMemoryStream) {
+ codeMemoryStream = new CodeMemoryStream(memory);
+ CodeReader codeReader = new StreamCodeReader(codeMemoryStream);
return codeReader;
}
}
\ No newline at end of file
diff --git a/src/Spice86/ViewModels/MainWindowViewModel.cs b/src/Spice86/ViewModels/MainWindowViewModel.cs
index e055a95eb..36aa12173 100644
--- a/src/Spice86/ViewModels/MainWindowViewModel.cs
+++ b/src/Spice86/ViewModels/MainWindowViewModel.cs
@@ -1,12 +1,10 @@
namespace Spice86.ViewModels;
using Avalonia;
-using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
-using Avalonia.Platform.Storage;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
@@ -104,11 +102,6 @@ internal void OnKeyUp(KeyEventArgs e) {
_avaloniaKeyScanCodeConverter.GetKeyReleasedScancode((Key)e.Key))));
}
- [RelayCommand]
- public void EndProgram() {
- ClearDialogCommand.Execute(null);
- }
-
[RelayCommand]
public async Task SaveBitmap() {
if (Bitmap is not null) {
@@ -172,11 +165,6 @@ public bool IsPaused {
}
}
- [ObservableProperty]
- [NotifyCanExecuteChangedFor(nameof(StartMostRecentlyUsedCommand))]
- private AvaloniaList _mostRecentlyUsed = new();
-
-
public int Width { get; private set; }
public int Height { get; private set; }
@@ -190,16 +178,16 @@ public bool IsPaused {
[NotifyCanExecuteChangedFor(nameof(PauseCommand))]
[NotifyCanExecuteChangedFor(nameof(PlayCommand))]
[NotifyCanExecuteChangedFor(nameof(DumpEmulatorStateToFileCommand))]
- private bool _isMachineRunning;
+ private bool _isEmulatorRunning;
- [RelayCommand(CanExecute = nameof(IsMachineRunning))]
+ [RelayCommand(CanExecute = nameof(IsEmulatorRunning))]
public async Task DumpEmulatorStateToFile() {
if (ProgramExecutor is not null) {
await _hostStorageProvider.DumpEmulatorStateToFile(Configuration, ProgramExecutor);
}
}
- [RelayCommand(CanExecute = nameof(IsMachineRunning))]
+ [RelayCommand(CanExecute = nameof(IsEmulatorRunning))]
public void Pause() {
if (ProgramExecutor is null) {
return;
@@ -207,7 +195,7 @@ public void Pause() {
IsPaused = ProgramExecutor.IsPaused = true;
}
- [RelayCommand(CanExecute = nameof(IsMachineRunning))]
+ [RelayCommand(CanExecute = nameof(IsEmulatorRunning))]
public void Play() {
if (ProgramExecutor is null) {
return;
@@ -221,55 +209,6 @@ public void Play() {
[ObservableProperty]
private string? _mainTitle;
- [RelayCommand(CanExecute = nameof(CanStartMostRecentlyUsed))]
- public async Task StartMostRecentlyUsed(object? parameter) {
- int index = Convert.ToInt32(parameter);
- if (MostRecentlyUsed.Count > index) {
- await StartNewExecutable(MostRecentlyUsed[index].FullName);
- }
- }
-
- private bool CanStartMostRecentlyUsed() => MostRecentlyUsed.Count > 0;
-
- [RelayCommand]
- public async Task DebugExecutable() {
- _closeAppOnEmulatorExit = false;
- await StartNewExecutable();
- Pause();
- }
-
- [RelayCommand]
- public async Task StartExecutable(object? filePath) {
- _closeAppOnEmulatorExit = false;
- await StartNewExecutable(filePath as string);
- }
-
- private async Task StartNewExecutable(string? filePath = null) {
- if(!string.IsNullOrWhiteSpace(filePath) &&
- File.Exists(filePath)) {
- await RestartEmulatorWithNewProgram(filePath);
- }
- else if (_hostStorageProvider.CanOpen) {
- IStorageFile? file = await _hostStorageProvider.PickExecutableFile(_lastExecutableDirectory);
- if (file is not null) {
- filePath = file.Path.LocalPath;
- await RestartEmulatorWithNewProgram(filePath);
- }
- }
- }
-
- private async Task RestartEmulatorWithNewProgram(string filePath) {
- Configuration.Exe = filePath;
- Configuration.ExeArgs = "";
- Configuration.CDrive = Path.GetDirectoryName(Configuration.Exe);
- Configuration.UseCodeOverride = false;
- Play();
- await _uiDispatcher.InvokeAsync(DisposeEmulator, DispatcherPriority.MaxValue);
- IsMachineRunning = false;
- _closeAppOnEmulatorExit = false;
- RunEmulator();
- }
-
private double _timeMultiplier = 1;
public double? TimeMultiplier {
@@ -282,7 +221,7 @@ public double? TimeMultiplier {
}
}
- [RelayCommand(CanExecute = nameof(IsMachineRunning))]
+ [RelayCommand(CanExecute = nameof(IsEmulatorRunning))]
public void ShowPerformance() => IsPerformanceVisible = !IsPerformanceVisible;
[RelayCommand]
@@ -324,34 +263,11 @@ public void OnMainWindowInitialized(Action uiUpdateMethod) {
}
}
- [ObservableProperty]
- private string? _firstProgramName = "";
-
- [ObservableProperty]
- private string? _secondProgramName = "";
-
- [ObservableProperty]
- private string? _thirdProgramName = "";
-
- private void AddOrReplaceMostRecentlyUsed(string filePath) {
- if (MostRecentlyUsed.Any(x => x.FullName == filePath)) {
- return;
- }
- MostRecentlyUsed.Insert(0,new FileInfo(filePath));
- if (MostRecentlyUsed.Count > 3) {
- MostRecentlyUsed.RemoveAt(3);
- }
- FirstProgramName = MostRecentlyUsed.ElementAtOrDefault(0)?.Name;
- SecondProgramName = MostRecentlyUsed.ElementAtOrDefault(1)?.Name;
- ThirdProgramName = MostRecentlyUsed.ElementAtOrDefault(2)?.Name;
- }
-
private bool RunEmulator() {
if (string.IsNullOrWhiteSpace(Configuration.Exe) ||
string.IsNullOrWhiteSpace(Configuration.CDrive)) {
return false;
}
- AddOrReplaceMostRecentlyUsed(Configuration.Exe);
_lastExecutableDirectory = Configuration.CDrive;
StatusMessage = "Emulator starting...";
AsmOverrideStatus = Configuration switch {
@@ -362,7 +278,7 @@ private bool RunEmulator() {
};
SetLogLevel(Configuration.SilencedLogs ? "Silent" : _loggerService.LogLevelSwitch.MinimumLevel.ToString());
SetMainTitle();
- RunMachine();
+ StartEmulatorThread();
return true;
}
@@ -428,7 +344,7 @@ private void Dispose(bool disposing) {
}, DispatcherPriority.MaxValue);
_drawingSemaphoreSlim?.Dispose();
PlayCommand.Execute(null);
- IsMachineRunning = false;
+ IsEmulatorRunning = false;
DisposeEmulator();
if (_emulatorThread?.IsAlive == true) {
_emulatorThread.Join();
@@ -475,8 +391,8 @@ private void SetLogLevel(string logLevel) {
}
}
- private void RunMachine() {
- _emulatorThread = new Thread(MachineThread) {
+ private void StartEmulatorThread() {
+ _emulatorThread = new Thread(EmulatorThread) {
Name = "Emulator"
};
_emulatorThread.Start();
@@ -487,7 +403,7 @@ private void OnEmulatorErrorOccured(Exception e) => _uiDispatcher.Post(() => {
ShowError(e);
});
- private void MachineThread() {
+ private void EmulatorThread() {
try {
try {
StartProgramExecutor();
@@ -498,7 +414,7 @@ private void MachineThread() {
OnEmulatorErrorOccured(e);
}
} finally {
- _uiDispatcher.Post(() => IsMachineRunning = false);
+ _uiDispatcher.Post(() => IsEmulatorRunning = false);
_uiDispatcher.Post(() => StatusMessage = "Emulator: stopped.");
_uiDispatcher.Post(() => AsmOverrideStatus = "");
}
@@ -526,7 +442,7 @@ private void StartProgramExecutor() {
PerformanceViewModel = new(_uiDispatcherTimerFactory, ProgramExecutor, new PerformanceMeasurer(), this);
_windowService.CloseDebugWindow();
TimeMultiplier = Configuration.TimeMultiplier;
- _uiDispatcher.Post(() => IsMachineRunning = true);
+ _uiDispatcher.Post(() => IsEmulatorRunning = true);
_uiDispatcher.Post(() => StatusMessage = "Emulator started.");
ProgramExecutor?.Run();
if (_closeAppOnEmulatorExit) {
diff --git a/src/Spice86/ViewModels/MemoryViewModel.cs b/src/Spice86/ViewModels/MemoryViewModel.cs
index 62aaedf56..5561507ef 100644
--- a/src/Spice86/ViewModels/MemoryViewModel.cs
+++ b/src/Spice86/ViewModels/MemoryViewModel.cs
@@ -23,7 +23,7 @@ public partial class MemoryViewModel : ViewModelBaseWithErrorDialog, IInternalDe
private bool _needToUpdateBinaryDocument;
[ObservableProperty]
- private MemoryBinaryDocument? _memoryBinaryDocument;
+ private DataMemoryDocument? _memoryBinaryDocument;
public bool NeedsToVisitEmulator => _memory is null;
@@ -142,7 +142,7 @@ private void UpdateBinaryDocument() {
if (_memory is null || StartAddress is null || EndAddress is null) {
return;
}
- MemoryBinaryDocument = new MemoryBinaryDocument(_memory, StartAddress.Value, EndAddress.Value);
+ MemoryBinaryDocument = new DataMemoryDocument(_memory, StartAddress.Value, EndAddress.Value);
MemoryBinaryDocument.MemoryReadInvalidOperation -= OnMemoryReadInvalidOperation;
MemoryBinaryDocument.MemoryReadInvalidOperation += OnMemoryReadInvalidOperation;
}
diff --git a/src/Spice86/Views/MainWindow.axaml b/src/Spice86/Views/MainWindow.axaml
index e12180cd6..9d0c39f16 100644
--- a/src/Spice86/Views/MainWindow.axaml
+++ b/src/Spice86/Views/MainWindow.axaml
@@ -23,18 +23,10 @@
-