예제 #1
0
        /// <summary>
        /// Signs that the device has been attached to the Spectrum virtual machine
        /// </summary>
        public void OnAttachedToVm(ISpectrumVm hostVm)
        {
            HostVm             = hostVm;
            _borderDevice      = hostVm.BorderDevice;
            _fetchScreenMemory = hostVm.MemoryDevice.OnUlaReadMemory;
            InitializeUlaTactTable();
            _flashPhase = false;
            FrameCount  = 0;

            // --- Calculate color conversion table
            _flashOffColors = new int[0x200];
            _flashOnColors  = new int[0x200];

            for (var attr = 0; attr < 0x100; attr++)
            {
                var ink   = (attr & 0x07) | ((attr & 0x40) >> 3);
                var paper = ((attr & 0x38) >> 3) | ((attr & 0x40) >> 3);
                _flashOffColors[attr]         = paper;
                _flashOffColors[0x100 + attr] = ink;
                _flashOnColors[attr]          = (attr & 0x80) != 0 ? ink : paper;
                _flashOnColors[0x100 + attr]  = (attr & 0x80) != 0 ? paper : ink;
            }

            _screenWidth = hostVm.ScreenDevice.ScreenConfiguration.ScreenWidth;
            _pixelBuffer = new byte[_screenWidth * hostVm.ScreenDevice.ScreenConfiguration.ScreenLines];
        }
예제 #2
0
        private (IZ80CpuTestSupport, int, bool) EmitHeaderWithSync(ISpectrumVm vm, TapeDevice td)
        {
            vm.Cpu.Registers.PC = td.SaveBytesRoutineAddress;
            td.SetTapeMode();
            var debugCpu = vm.Cpu as IZ80CpuTestSupport;
            var pulse    = false;
            var tacts    = 0;

            for (var i = 0; i < TapeDevice.MIN_PILOT_PULSE_COUNT + 10; i++)
            {
                tacts += TapeDataBlockPlayer.PILOT_PL;
                debugCpu.SetTacts(tacts);
                td.ProcessMicBit(pulse);
                pulse = !pulse;
            }
            tacts += TapeDataBlockPlayer.SYNC_1_PL;
            debugCpu.SetTacts(tacts);
            td.ProcessMicBit(pulse);
            pulse  = !pulse;
            tacts += TapeDataBlockPlayer.SYNC_2_PL;
            debugCpu.SetTacts(tacts);
            td.ProcessMicBit(pulse);
            pulse = !pulse;
            return(debugCpu, tacts, pulse);
        }
예제 #3
0
        /// <summary>
        /// Signs that the device has been attached to the Spectrum virtual machine
        /// </summary>
        public void OnAttachedToVm(ISpectrumVm hostVm)
        {
            HostVm = hostVm;
            var screenInfo = hostVm.GetDeviceInfo <IScreenDevice>();

            ScreenConfiguration = hostVm.ScreenConfiguration;
            _pixelRenderer      = (IScreenFrameProvider)screenInfo.Provider ?? new NoopPixelRenderer();
            _memoryDevice       = hostVm.MemoryDevice;
            _contentionType     = hostVm.MemoryConfiguration.ContentionType;
            InitializeScreenRenderingTactTable();
            _flashPhase = false;
            FrameCount  = 0;

            // --- Calculate refresh rate related values
            RefreshRate       = (decimal)hostVm.BaseClockFrequency / ScreenConfiguration.ScreenRenderingFrameTactCount;
            FlashToggleFrames = (int)Math.Round(RefreshRate / 2);

            // --- Calculate color conversion table
            _flashOffColors = new int[0x200];
            _flashOnColors  = new int[0x200];

            for (var attr = 0; attr < 0x100; attr++)
            {
                var ink   = (attr & 0x07) | ((attr & 0x40) >> 3);
                var paper = ((attr & 0x38) >> 3) | ((attr & 0x40) >> 3);
                _flashOffColors[attr]         = paper;
                _flashOffColors[0x100 + attr] = ink;
                _flashOnColors[attr]          = (attr & 0x80) != 0 ? ink : paper;
                _flashOnColors[0x100 + attr]  = (attr & 0x80) != 0 ? paper : ink;
            }

            _screenWidth = hostVm.ScreenDevice.ScreenConfiguration.ScreenWidth;
            _pixelBuffer = new byte[_screenWidth * hostVm.ScreenDevice.ScreenConfiguration.ScreenLines];
        }
예제 #4
0
        private (IZ80CpuTestSupport, int, bool) EmitHeaderAndData(ISpectrumVm vm, TapeDevice td, byte[] data)
        {
            (var debugCpu, var tacts, var pulse) = EmitHeaderWithSync(vm, td);
            foreach (var byteValue in data)
            {
                var dataByte = byteValue;
                for (var i = 0; i < 8; i++)
                {
                    var length = (dataByte & 0x80) == 0
                        ? TapeDataBlockPlayer.BIT_0_PL
                        : TapeDataBlockPlayer.BIT_1_PL;
                    tacts += length;
                    debugCpu.SetTacts(tacts);
                    td.ProcessMicBit(pulse);
                    pulse  = !pulse;
                    tacts += length;
                    debugCpu.SetTacts(tacts);
                    td.ProcessMicBit(pulse);
                    pulse = !pulse;

                    dataByte = (byte)(dataByte << 1);
                }
            }
            return(debugCpu, tacts, pulse);
        }
예제 #5
0
 /// <summary>
 /// Signs that the device has been attached to the Spectrum virtual machine
 /// </summary>
 public void OnAttachedToVm(ISpectrumVm hostVm)
 {
     HostVm        = hostVm;
     _cpu          = hostVm.Cpu;
     _beeperDevice = hostVm.BeeperDevice;
     Reset();
 }
예제 #6
0
        /// <summary>
        /// Signs that the device has been attached to the Spectrum virtual machine
        /// </summary>
        public void OnAttachedToVm(ISpectrumVm hostVm)
        {
            HostVm = hostVm;
            var kempstonInfo = HostVm.GetDeviceInfo <IKempstonDevice>();

            _kempstonProvider = (IKempstonProvider)kempstonInfo?.Provider;
        }
예제 #7
0
 /// <summary>
 /// Signs that the device has been attached to the Spectrum virtual machine
 /// </summary>
 public void OnAttachedToVm(ISpectrumVm hostVm)
 {
     HostVm        = hostVm;
     _cpu          = hostVm.Cpu;
     _screenDevice = hostVm.ScreenDevice;
     _memory       = new byte[0x10000];
 }
예제 #8
0
 /// <summary>
 /// Signs that the device has been attached to the Spectrum virtual machine
 /// </summary>
 public override void OnAttachedToVm(ISpectrumVm hostVm)
 {
     base.OnAttachedToVm(hostVm);
     _cpu              = hostVm?.Cpu;
     _screenDevice     = hostVm?.ScreenDevice;
     _currentSlot3Bank = 0;
 }
예제 #9
0
 /// <summary>
 /// Signs that the provider has been attached to the Spectrum virtual machine
 /// </summary>
 public override void OnAttachedToVm(ISpectrumVm hostVm)
 {
     base.OnAttachedToVm(hostVm);
     _beeperPars = hostVm.BeeperConfiguration;
     WaveFormat  = WaveFormat.CreateIeeeFloatWaveFormat(_beeperPars.AudioSampleRate, 1);
     Reset();
 }
예제 #10
0
 private (IZ80CpuTestSupport, int, bool) EmitFullDataBlock(ISpectrumVm vm, TapeDevice td, byte[] data)
 {
     (var debugCpu, var tacts, var pulse) = EmitHeaderAndData(vm, td, data);
     tacts += TapeDataBlockPlayer.TERM_SYNC;
     debugCpu.SetTacts(tacts);
     td.ProcessMicBit(pulse);
     return(debugCpu, tacts, pulse);
 }
예제 #11
0
        /// <summary>
        /// Signs that the device has been attached to the Spectrum virtual machine
        /// </summary>
        public void OnAttachedToVm(ISpectrumVm hostVm)
        {
            HostVm = hostVm;
            var keyboardInfo = HostVm.GetDeviceInfo <IKeyboardDevice>();

            _keyboardProvider = (IKeyboardProvider)keyboardInfo?.Provider;
            _keyboardProvider?.SetKeyStatusHandler(SetStatus);
        }
예제 #12
0
 /// <summary>
 /// Signs that the device has been attached to the Spectrum virtual machine
 /// </summary>
 public override void OnAttachedToVm(ISpectrumVm hostVm)
 {
     base.OnAttachedToVm(hostVm);
     _screenDevice   = hostVm.ScreenDevice;
     _beeperDevice   = hostVm.BeeperDevice;
     _keyboardDevice = hostVm.KeyboardDevice;
     _tapeDevice     = hostVm.TapeDevice;
 }
예제 #13
0
 public SpectrumVmStateFileManager(string modelName, ISpectrumVm spectrum, ISpectrumVmController controller,
                                   Func <string> cacheFolderFunc)
 {
     ModelName        = modelName;
     SpectrumVm       = spectrum;
     VmController     = controller;
     _cacheFolderFunc = cacheFolderFunc;
 }
예제 #14
0
 /// <summary>
 /// Signs that the provider has been attached to the Spectrum virtual machine
 /// </summary>
 public override void OnAttachedToVm(ISpectrumVm hostVm)
 {
     base.OnAttachedToVm(hostVm);
     _audioPars = Type == AudioProviderType.Beeper
         ? hostVm.AudioConfiguration :
                  hostVm.SoundConfiguration;
     WaveFormat = WaveFormat.CreateIeeeFloatWaveFormat(_audioPars.AudioSampleRate, 1);
     Reset();
 }
예제 #15
0
        /// <summary>
        /// Creates an instance of the virtual machine
        /// </summary>
        /// <param name="modelKey">The model key of the virtual machine</param>
        /// <param name="editionKey">The edition key of the virtual machine</param>
        /// <param name="devices">Devices to create the machine</param>
        private SpectrumMachine(string modelKey, string editionKey, DeviceInfoCollection devices)
        {
            // --- Store model information
            ModelKey   = modelKey;
            EditionKey = editionKey;

            // --- Create the engine and set up properties
            SpectrumVm = new SpectrumEngine(devices);

            Cpu = new CpuZ80(SpectrumVm.Cpu);

            var roms = new List <ReadOnlyMemorySlice>();

            for (var i = 0; i < SpectrumVm.RomConfiguration.NumberOfRoms; i++)
            {
                roms.Add(new ReadOnlyMemorySlice(SpectrumVm.RomDevice.GetRomBytes(i)));
            }
            Roms = new ReadOnlyCollection <ReadOnlyMemorySlice>(roms);

            PagingInfo = new MemoryPagingInfo(SpectrumVm.MemoryDevice);
            Memory     = new SpectrumMemoryContents(SpectrumVm.MemoryDevice, SpectrumVm.Cpu);

            var ramBanks = new List <MemorySlice>();

            if (SpectrumVm.MemoryConfiguration.RamBanks != null)
            {
                for (var i = 0; i < SpectrumVm.MemoryConfiguration.RamBanks; i++)
                {
                    ramBanks.Add(new MemorySlice(SpectrumVm.MemoryDevice.GetRamBank(i)));
                }
            }
            RamBanks = new ReadOnlyCollection <MemorySlice>(ramBanks);

            Keyboard              = new KeyboardEmulator(SpectrumVm);
            ScreenConfiguration   = SpectrumVm.ScreenConfiguration;
            ScreenRenderingTable  = new ScreenRenderingTable(SpectrumVm.ScreenDevice);
            ScreenBitmap          = new ScreenBitmap(SpectrumVm.ScreenDevice);
            ScreenRenderingStatus = new ScreenRenderingStatus(SpectrumVm);
            BeeperConfiguration   = SpectrumVm.AudioConfiguration;
            BeeperSamples         = new AudioSamples(SpectrumVm.BeeperDevice);
            BeeperProvider        = SpectrumVm.BeeperProvider;
            SoundConfiguration    = SpectrumVm.SoundConfiguration;
            SoundProvider         = SpectrumVm.SoundProvider;
            AudioSamples          = new AudioSamples(SpectrumVm.SoundDevice);
            Breakpoints           = new CodeBreakpoints(SpectrumVm.DebugInfoProvider);

            // --- Hook device events
            SpectrumVm.TapeLoadDevice.LoadCompleted += (s, e) => FastLoadCompleted?.Invoke(s, e);
            SpectrumVm.TapeSaveDevice.LeftSaveMode  += (s, e) => LeftSaveMode?.Invoke(s, e);

            // --- Initialize machine state
            _clockProvider           = GetProvider <IClockProvider>();
            _physicalFrameClockCount = _clockProvider.GetFrequency() / (double)SpectrumVm.BaseClockFrequency *
                                       ScreenConfiguration.ScreenRenderingFrameTactCount;
            MachineState = VmState.None;
            ExecutionCompletionReason = ExecutionCompletionReason.None;
        }
예제 #16
0
 /// <summary>
 /// Signs that the device has been attached to the Spectrum virtual machine
 /// </summary>
 public void OnAttachedToVm(ISpectrumVm hostVm)
 {
     HostVm          = hostVm;
     _cpu            = hostVm.Cpu;
     _borderDevice   = hostVm.BorderDevice;
     _beeperDevice   = hostVm.BeeperDevice;
     _keyboardDevice = hostVm.KeyboardDevice;
     _tapeDevice     = hostVm.TapeDevice;
 }
예제 #17
0
 /// <summary>
 /// Signs that the device has been attached to the Spectrum virtual machine
 /// </summary>
 public void OnAttachedToVm(ISpectrumVm hostVm)
 {
     HostVm = hostVm;
     _audioConfiguration = hostVm.AudioConfiguration;
     _beeperProvider     = hostVm.BeeperProvider;
     _frameTacts         = hostVm.FrameTacts;
     _tactsPerSample     = _audioConfiguration.TactsPerSample;
     Reset();
 }
 /// <summary>
 /// Signs that the device has been attached to the Spectrum virtual machine
 /// </summary>
 public override void OnAttachedToVm(ISpectrumVm hostVm)
 {
     base.OnAttachedToVm(hostVm);
     _slots = new[]
     {
         0, 5, 2, 0
     };
     _isInAllRamMode = false;
 }
예제 #19
0
 /// <summary>
 /// Signs that the device has been attached to the Spectrum virtual machine
 /// </summary>
 public void OnAttachedToVm(ISpectrumVm hostVm)
 {
     HostVm = hostVm;
     BeeperConfiguration = new BeeperConfiguration();
     _frameTacts         = hostVm.FrameTacts;
     _tactsPerSample     = BeeperConfiguration.TactsPerSample;
     Pulses = new List <EarBitPulse>(1000);
     Reset();
 }
예제 #20
0
 /// <summary>
 /// Signs that the device has been attached to the Spectrum virtual machine
 /// </summary>
 public void OnAttachedToVm(ISpectrumVm hostVm)
 {
     HostVm = hostVm;
     _soundConfiguration = hostVm.SoundConfiguration;
     _soundProvider      = hostVm.SoundProvider;
     _frameTacts         = hostVm.FrameTacts;
     _tactsPerSample     = _soundConfiguration.TactsPerSample;
     _lpf = new BandPassFilter(32, _soundConfiguration.AudioSampleRate, 150.0, 8000.0);
     Reset();
 }
예제 #21
0
 /// <summary>
 /// Signs that the device has been attached to the Spectrum virtual machine
 /// </summary>
 public virtual void OnAttachedToVm(ISpectrumVm hostVm)
 {
     HostVm       = hostVm;
     Cpu          = hostVm.Cpu;
     ScreenDevice = hostVm.ScreenDevice;
     foreach (var handler in Handlers)
     {
         handler.OnAttachedToVm(hostVm);
         handler.Reset();
     }
 }
예제 #22
0
 /// <summary>
 /// Signs that the device has been attached to the Spectrum virtual machine
 /// </summary>
 public override void OnAttachedToVm(ISpectrumVm hostVm)
 {
     base.OnAttachedToVm(hostVm);
     _cpu          = hostVm?.Cpu;
     _screenDevice = hostVm?.ScreenDevice;
     _slots        = new[]
     {
         0, 5, 2, 0
     };
     SpecialMode = false;
 }
예제 #23
0
 /// <summary>
 /// Signs that the device has been attached to the Spectrum virtual machine
 /// </summary>
 public override void OnAttachedToVm(ISpectrumVm hostVm)
 {
     base.OnAttachedToVm(hostVm);
     _isUla3           = hostVm.UlaIssue == "3";
     _cpu              = hostVm.Cpu;
     _screenDevice     = hostVm.ScreenDevice;
     _beeperDevice     = hostVm.BeeperDevice;
     _keyboardDevice   = hostVm.KeyboardDevice;
     _tapeDevice       = hostVm.TapeDevice;
     _bit3LastValue    = true;
     _bit4LastValue    = true;
     _bit4ChangedFrom0 = 0;
     _bit4ChangedFrom1 = 0;
 }
        /// <summary>
        /// Signs that the device has been attached to the Spectrum virtual machine
        /// </summary>
        public override void OnAttachedToVm(ISpectrumVm hostVm)
        {
            base.OnAttachedToVm(hostVm);
            _romConfig    = hostVm.RomConfiguration;
            _nextDevice   = hostVm.NextDevice;
            _divIdeDevice = hostVm.DivIdeDevice;

            // --- Create space for ROM pages (use 10 x 8K pages)
            var romCount = _romConfig.NumberOfRoms * 2;

            _romPages = new byte[romCount][];
            for (var i = 0; i < romCount; i++)
            {
                _romPages[i] = new byte[0x2000];
            }

            // --- Obtain Next memory size
            var memSize = HostVm.MemoryConfiguration.NextMemorySize;

            if (memSize < 1024)
            {
                memSize = 512;
            }
            else if (memSize >= 1024 && memSize < 1536)
            {
                memSize = 1024;
            }
            else if (memSize >= 1536 && memSize < 2048)
            {
                memSize = 1536;
            }
            else
            {
                memSize = 2048;
            }

            // --- Calculate number of RAM pages
            RamPageCount = 16 + 64 * (memSize - 512) / 512;

            // --- Allocate RAM
            _ramPages = new byte[RamPageCount][];
            for (var i = 0; i < RamPageCount; i++)
            {
                _ramPages[i] = new byte[0x2000];
            }

            Reset();
        }
예제 #25
0
        /// <summary>
        /// Signs that the device has been attached to the Spectrum virtual machine
        /// </summary>
        public void OnAttachedToVm(ISpectrumVm hostVm)
        {
            HostVm        = hostVm;
            _cpu          = hostVm?.Cpu;
            _screenDevice = hostVm?.ScreenDevice;

            // --- Create the ROM pages
            _romPage0 = new byte[PAGE_LENGTH];
            _romPage1 = new byte[PAGE_LENGTH];

            _ramBanks = new byte[8][];
            // --- Create RAM pages
            for (var i = 0; i < 8; i++)
            {
                _ramBanks[i] = new byte[PAGE_LENGTH];
            }

            _currentRomPage   = _romPage0;
            _currentSlot3Bank = 0;
        }
예제 #26
0
        /// <summary>
        /// Exports the memory of the specified virtual machine
        /// </summary>
        /// <param name="spectrumVm"></param>
        public void ExportMemory(ISpectrumVm spectrumVm)
        {
            // --- Parse addresses
            if (!ushort.TryParse(ExportParams.StartAddress, out var startAddress))
            {
                return;
            }
            if (!ushort.TryParse(ExportParams.EndAddress, out var endAddress))
            {
                return;
            }
            try
            {
                var contents = spectrumVm.MemoryDevice.CloneMemory()
                               .Skip(startAddress)
                               .Take(endAddress - startAddress + 1)
                               .ToArray();
                var dirName = Path.GetDirectoryName(ExportParams.Filename);
                if (!string.IsNullOrEmpty(dirName) && !Directory.Exists(dirName))
                {
                    Directory.CreateDirectory(dirName);
                }
                File.WriteAllBytes(ExportParams.Filename, contents);
            }
            catch (Exception ex)
            {
                VsxDialogs.Show($"Error while exporting to file {ExportParams.Filename}: {ex.Message}",
                                "Export disassembly error.", MessageBoxButton.OK, VsxMessageBoxIcon.Error);
            }

            if (!ExportParams.AddToProject)
            {
                return;
            }

            SpectrumProject.AddFileToProject(SpectNetPackage.Default.Options.MemoryExportFolder,
                                             ExportParams.Filename,
                                             INVALID_FOLDER_MESSAGE, FILE_EXISTS_MESSAGE);
        }
예제 #27
0
        /// <summary>
        /// Signs that the device has been attached to the Spectrum virtual machine
        /// </summary>
        public override void OnAttachedToVm(ISpectrumVm hostVm)
        {
            base.OnAttachedToVm(hostVm);
            RomCount     = hostVm?.RomConfiguration?.NumberOfRoms ?? _defaultRomCount;
            RamBankCount = hostVm?.MemoryConfiguration?.RamBanks ?? _defaultRamBankCount;

            // --- Create the ROM pages
            Roms = new byte[RomCount][];
            for (var i = 0; i < RomCount; i++)
            {
                Roms[i] = new byte[0x4000];
            }

            RamBanks = new byte[RamBankCount][];
            // --- Create RAM pages
            for (var i = 0; i < RamBankCount; i++)
            {
                RamBanks[i] = new byte[0x4000];
            }

            SelectedRomIndex = 0;
        }
예제 #28
0
        /// <summary>
        /// Signs that the device has been attached to the Spectrum virtual machine
        /// </summary>
        public void OnAttachedToVm(ISpectrumVm hostVm)
        {
            HostVm        = hostVm;
            _cpu          = hostVm.Cpu;
            _beeperDevice = hostVm.BeeperDevice;
            _memoryDevice = hostVm.MemoryDevice;

            var romDevice = HostVm.RomDevice;

            LoadBytesRoutineAddress =
                romDevice.GetKnownAddress(SpectrumRomDevice.LOAD_BYTES_ROUTINE_ADDRESS,
                                          HostVm.RomConfiguration.Spectrum48RomIndex) ?? 0;
            SaveBytesRoutineAddress =
                romDevice.GetKnownAddress(SpectrumRomDevice.SAVE_BYTES_ROUTINE_ADDRESS,
                                          HostVm.RomConfiguration.Spectrum48RomIndex) ?? 0;
            LoadBytesInvalidHeaderAddress =
                romDevice.GetKnownAddress(SpectrumRomDevice.LOAD_BYTES_INVALID_HEADER_ADDRESS,
                                          HostVm.RomConfiguration.Spectrum48RomIndex) ?? 0;
            LoadBytesResumeAddress =
                romDevice.GetKnownAddress(SpectrumRomDevice.LOAD_BYTES_RESUME_ADDRESS,
                                          HostVm.RomConfiguration.Spectrum48RomIndex) ?? 0;
            Reset();
        }
예제 #29
0
 /// <summary>
 /// Signs that the device has been attached to the Spectrum virtual machine
 /// </summary>
 public void OnAttachedToVm(ISpectrumVm hostVm)
 {
     HostVm        = hostVm;
     _memoryDevice = hostVm.MemoryDevice;
 }
예제 #30
0
 /// <summary>
 /// Signs that the device has been attached to the Spectrum virtual machine
 /// </summary>
 public void OnAttachedToVm(ISpectrumVm hostVm)
 {
 }