/// <summary> /// Initializes a class instance using a collection of devices /// </summary> public SpectrumEngine(DeviceInfoCollection deviceData, string ulaIssue = "3") { DeviceData = deviceData ?? throw new ArgumentNullException(nameof(deviceData)); UlaIssue = ulaIssue == "3" ? "3" : "2"; // --- Prepare the memory device var memoryInfo = GetDeviceInfo <IMemoryDevice>(); MemoryDevice = memoryInfo?.Device ?? new Spectrum48MemoryDevice(); MemoryConfiguration = (IMemoryConfiguration)memoryInfo?.ConfigurationData; // --- Prepare the port device var portInfo = GetDeviceInfo <IPortDevice>(); PortDevice = portInfo?.Device ?? new Spectrum48PortDevice(); // --- Init the CPU var cpuConfig = GetDeviceConfiguration <IZ80Cpu, ICpuConfiguration>(); var mult = 1; if (cpuConfig != null) { BaseClockFrequency = cpuConfig.BaseClockFrequency; mult = cpuConfig.ClockMultiplier; if (mult < 1) { mult = 1; } else if (mult >= 2 && mult <= 3) { mult = 2; } else if (mult >= 4 && mult <= 7) { mult = 4; } else if (mult > 8) { mult = 8; } } ClockMultiplier = mult; Cpu = new Z80Cpu(MemoryDevice, PortDevice, cpuConfig?.SupportsNextOperations ?? false) { UseGateArrayContention = MemoryConfiguration.ContentionType == MemoryContentionType.GateArray }; // --- Init the ROM var romInfo = GetDeviceInfo <IRomDevice>(); RomProvider = (IRomProvider)romInfo.Provider; RomDevice = romInfo.Device ?? new SpectrumRomDevice(); RomConfiguration = (IRomConfiguration)romInfo.ConfigurationData; // --- Init the screen device var screenInfo = GetDeviceInfo <IScreenDevice>(); var pixelRenderer = (IScreenFrameProvider)screenInfo.Provider; ScreenConfiguration = new ScreenConfiguration((IScreenConfiguration)screenInfo.ConfigurationData); ScreenDevice = screenInfo.Device ?? new Spectrum48ScreenDevice(); ShadowScreenDevice = new Spectrum48ScreenDevice(); // --- Init the beeper device var beeperInfo = GetDeviceInfo <IBeeperDevice>(); AudioConfiguration = (IAudioConfiguration)beeperInfo?.ConfigurationData; BeeperProvider = (IBeeperProvider)beeperInfo?.Provider; BeeperDevice = beeperInfo?.Device ?? new BeeperDevice(); // --- Init the keyboard device var keyboardInfo = GetDeviceInfo <IKeyboardDevice>(); KeyboardProvider = (IKeyboardProvider)keyboardInfo?.Provider; KeyboardDevice = keyboardInfo?.Device ?? new KeyboardDevice(); // --- Init the Kempston device var kempstonInfo = GetDeviceInfo <IKempstonDevice>(); KempstonProvider = (IKempstonProvider)kempstonInfo?.Provider; KempstonDevice = kempstonInfo?.Device ?? new KempstonDevice(); // --- Init the interrupt device InterruptDevice = new InterruptDevice(InterruptTact); // --- Init the tape device var tapeSaveInfo = GetDeviceInfo <ITapeSaveDevice>(); TapeSaveProvider = (ITapeSaveProvider)tapeSaveInfo?.Provider; var tapeLoadInfo = GetDeviceInfo <ITapeLoadDevice>(); TapeLoadProvider = (ITapeLoadProvider)tapeLoadInfo?.Provider; var tapeDevice = new TapeDevice(TapeLoadProvider, TapeSaveProvider); TapeLoadDevice = tapeDevice; TapeSaveDevice = tapeDevice; // === Init optional devices // --- Init the sound device var soundInfo = GetDeviceInfo <ISoundDevice>(); SoundConfiguration = (IAudioConfiguration)soundInfo?.ConfigurationData; SoundProvider = (ISoundProvider)soundInfo?.Provider; SoundDevice = soundInfo == null ? null : soundInfo.Device ?? new SoundDevice(); // --- Init the floppy device var floppyInfo = GetDeviceInfo <IFloppyDevice>(); if (floppyInfo != null) { FloppyDevice = floppyInfo.Device; FloppyConfiguration = (IFloppyConfiguration)floppyInfo.ConfigurationData ?? new FloppyConfiguration(); } // --- Carry out frame calculations ResetUlaTact(); FrameTacts = ScreenConfiguration.ScreenRenderingFrameTactCount; FrameCount = 0; Overflow = 0; HasFrameCompleted = true; _lastBreakpoint = null; // --- Attach providers AttachProvider(RomProvider); AttachProvider(pixelRenderer); AttachProvider(BeeperProvider); AttachProvider(KeyboardProvider); AttachProvider(KempstonProvider); AttachProvider(TapeLoadProvider); AttachProvider(DebugInfoProvider); // --- Attach optional providers if (SoundProvider != null) { AttachProvider(SoundProvider); } // --- Collect Spectrum devices _spectrumDevices.Add(RomDevice); _spectrumDevices.Add(MemoryDevice); _spectrumDevices.Add(PortDevice); _spectrumDevices.Add(ScreenDevice); _spectrumDevices.Add(ShadowScreenDevice); _spectrumDevices.Add(BeeperDevice); _spectrumDevices.Add(KeyboardDevice); _spectrumDevices.Add(KempstonDevice); _spectrumDevices.Add(InterruptDevice); _spectrumDevices.Add(TapeLoadDevice); // --- Collect optional devices if (SoundDevice != null) { _spectrumDevices.Add(SoundDevice); } if (FloppyDevice != null) { _spectrumDevices.Add(FloppyDevice); } // --- Now, prepare devices to find each other foreach (var device in _spectrumDevices) { device.OnAttachedToVm(this); } // --- Prepare bound devices _frameBoundDevices = _spectrumDevices .OfType <IRenderFrameBoundDevice>() .ToList(); _cpuBoundDevices = _spectrumDevices .OfType <ICpuOperationBoundDevice>() .ToList(); DebugInfoProvider = new SpectrumDebugInfoProvider(); // --- Init the ROM InitRom(RomDevice, RomConfiguration); }
/// <summary> /// Initializes a class instance using a collection of devices /// </summary> public SpectrumEngine(DeviceInfoCollection deviceData) { DeviceData = deviceData ?? throw new ArgumentNullException(nameof(deviceData)); // --- Check for Spectrum Next var nextInfo = GetDeviceInfo <INextFeatureSetDevice>(); NextDevice = nextInfo?.Device; // --- Prepare the memory device var memoryInfo = GetDeviceInfo <IMemoryDevice>(); MemoryDevice = memoryInfo?.Device ?? new Spectrum48MemoryDevice(); MemoryConfiguration = (IMemoryConfiguration)memoryInfo?.ConfigurationData; // --- Prepare the port device var portInfo = GetDeviceInfo <IPortDevice>(); PortDevice = portInfo?.Device ?? new Spectrum48PortDevice(); // --- Init the CPU var cpuConfig = GetDeviceConfiguration <IZ80Cpu, ICpuConfiguration>(); var mult = 1; if (cpuConfig != null) { BaseClockFrequency = cpuConfig.BaseClockFrequency; mult = cpuConfig.ClockMultiplier; if (mult < 1) { mult = 1; } else if (mult >= 2 && mult <= 3) { mult = 2; } else if (mult >= 4 && mult <= 7) { mult = 4; } else if (mult > 8) { mult = 8; } } ClockMultiplier = mult; Cpu = new Z80Cpu(MemoryDevice, PortDevice, cpuConfig?.SupportsNextOperations ?? false, NextDevice) { UseGateArrayContention = MemoryConfiguration.ContentionType == MemoryContentionType.GateArray }; // --- Init the ROM var romInfo = GetDeviceInfo <IRomDevice>(); RomProvider = (IRomProvider)romInfo.Provider; RomDevice = romInfo.Device ?? new SpectrumRomDevice(); RomConfiguration = (IRomConfiguration)romInfo.ConfigurationData; // --- Init the clock var clockInfo = GetDeviceInfo <IClockDevice>(); Clock = (IClockProvider)clockInfo.Provider ?? throw new InvalidOperationException("The virtual machine needs a clock provider!"); // --- Init the screen device var screenInfo = GetDeviceInfo <IScreenDevice>(); var pixelRenderer = (IScreenFrameProvider)screenInfo.Provider; ScreenConfiguration = new ScreenConfiguration((IScreenConfiguration)screenInfo.ConfigurationData); ScreenDevice = screenInfo.Device ?? new Spectrum48ScreenDevice(); // --- Init the beeper device var beeperInfo = GetDeviceInfo <IBeeperDevice>(); AudioConfiguration = (IAudioConfiguration)beeperInfo?.ConfigurationData; BeeperProvider = (IBeeperProvider)beeperInfo?.Provider; BeeperDevice = beeperInfo?.Device ?? new BeeperDevice(); // --- Init the keyboard device var keyboardInfo = GetDeviceInfo <IKeyboardDevice>(); KeyboardProvider = (IKeyboardProvider)keyboardInfo?.Provider; KeyboardDevice = keyboardInfo?.Device ?? new KeyboardDevice(); // --- Init the interrupt device InterruptDevice = new InterruptDevice(InterruptTact); // --- Init the tape device var tapeInfo = GetDeviceInfo <ITapeDevice>(); TapeProvider = (ITapeProvider)tapeInfo?.Provider; TapeDevice = tapeInfo?.Device ?? new TapeDevice(TapeProvider); // === Init optional devices // --- Init the sound device var soundInfo = GetDeviceInfo <ISoundDevice>(); SoundConfiguration = (IAudioConfiguration)soundInfo?.ConfigurationData; SoundProvider = (ISoundProvider)soundInfo?.Provider; SoundDevice = soundInfo == null ? null : soundInfo.Device ?? new SoundDevice(); // --- Init the DivIDE device var divIdeInfo = GetDeviceInfo <IDivIdeDevice>(); DivIdeDevice = divIdeInfo?.Device; // --- Carry out frame calculations ResetUlaTact(); _frameTacts = ScreenConfiguration.ScreenRenderingFrameTactCount; PhysicalFrameClockCount = Clock.GetFrequency() / (double)BaseClockFrequency * _frameTacts; FrameCount = 0; Overflow = 0; _frameCompleted = true; _lastBreakpoint = null; RunsInMaskableInterrupt = false; // --- Attach providers AttachProvider(RomProvider); AttachProvider(Clock); AttachProvider(pixelRenderer); AttachProvider(BeeperProvider); AttachProvider(KeyboardProvider); AttachProvider(TapeProvider); AttachProvider(DebugInfoProvider); // --- Attach optional providers if (SoundProvider != null) { AttachProvider(SoundProvider); } // --- Collect Spectrum devices _spectrumDevices.Add(RomDevice); _spectrumDevices.Add(MemoryDevice); _spectrumDevices.Add(PortDevice); _spectrumDevices.Add(ScreenDevice); _spectrumDevices.Add(BeeperDevice); _spectrumDevices.Add(KeyboardDevice); _spectrumDevices.Add(InterruptDevice); _spectrumDevices.Add(TapeDevice); // --- Collect optional devices if (SoundDevice != null) { _spectrumDevices.Add(SoundDevice); } if (NextDevice != null) { _spectrumDevices.Add(NextDevice); } if (DivIdeDevice != null) { _spectrumDevices.Add(DivIdeDevice); } // --- Now, prepare devices to find each other foreach (var device in _spectrumDevices) { device.OnAttachedToVm(this); } // --- Prepare bound devices _frameBoundDevices = _spectrumDevices .OfType <IFrameBoundDevice>() .ToList(); _cpuBoundDevices = _spectrumDevices .OfType <ICpuOperationBoundDevice>() .ToList(); DebugInfoProvider = new SpectrumDebugInfoProvider(); // --- Init the ROM InitRom(RomDevice, RomConfiguration); }
/// <summary>Initializes a new instance of the <see cref="T:System.Object" /> class.</summary> public Spectrum48( IRomProvider romProvider, IClockProvider clockProvider, IKeyboardProvider keyboardProvider, IScreenFrameProvider pixelRenderer, IEarBitFrameProvider earBitFrameProvider = null, ITapeContentProvider loadContentProvider = null, ISaveToTapeProvider tapeSaveToTapeProvider = null) { // --- Init the CPU MemoryDevice = new Spectrum48MemoryDevice(); PortDevice = new Spectrum48PortDevice(); Cpu = new Z80Cpu(MemoryDevice, PortDevice); OsInitialized = false; // --- Setup the clock Clock = clockProvider; // --- Set up Spectrum devices BorderDevice = new BorderDevice(); ScreenDevice = new Spectrum48ScreenDevice(pixelRenderer); BeeperDevice = new BeeperDevice(earBitFrameProvider); KeyboardDevice = new KeyboardDevice(keyboardProvider); InterruptDevice = new InterruptDevice(InterruptTact); TapeDevice = new TapeDevice(loadContentProvider, tapeSaveToTapeProvider); // --- Carry out frame calculations ResetUlaTact(); _frameTacts = ScreenDevice.ScreenConfiguration.UlaFrameTactCount; PhysicalFrameClockCount = Clock.GetFrequency() / (double)ClockFrequeny * _frameTacts; FrameCount = 0; Overflow = 0; _frameCompleted = true; // --- Collect Spectrum devices _spectrumDevices.Add(MemoryDevice); _spectrumDevices.Add(PortDevice); _spectrumDevices.Add(BorderDevice); _spectrumDevices.Add(ScreenDevice); _spectrumDevices.Add(BeeperDevice); _spectrumDevices.Add(KeyboardDevice); _spectrumDevices.Add(InterruptDevice); _spectrumDevices.Add(TapeDevice); // --- Now, prepare devices to find each other foreach (var device in _spectrumDevices) { device.OnAttachedToVm(this); } // --- Prepare bound devices _frameBoundDevices = _spectrumDevices .OfType <IFrameBoundDevice>() .ToList(); _cpuBoundDevices = _spectrumDevices .OfType <ICpuOperationBoundDevice>() .ToList(); DebugInfoProvider = new SpectrumDebugInfoProvider(); // --- Init the ROM InitRom(romProvider, "ZXSpectrum48"); }