From a7e0e728a78af6d00b02557161538f84909ad964 Mon Sep 17 00:00:00 2001 From: Asnivor Date: Mon, 23 Jul 2018 20:48:31 +0100 Subject: [PATCH] CPCHawk: PSG now sounds *almost* right --- .../AmstradCPC/Hardware/Abstraction/IPSG.cs | 4 +- .../Hardware/Disk/NECUPD765.IPortIODevice.cs | 48 +++++++ .../Hardware/Display/AmstradGateArray.cs | 12 +- .../AmstradCPC/Hardware/Display/CRCT_6845.cs | 53 ++++++- .../AmstradCPC/Hardware/Display/CRTDevice.cs | 4 +- .../Hardware/SoundOutput/AY38912.cs | 133 ++++++++++-------- .../AmstradCPC/Hardware/SoundOutput/Beeper.cs | 4 +- .../Machine/CPC6128/CPC6128.Port.cs | 30 +++- .../AmstradCPC/Machine/CPCBase.Media.cs | 11 +- .../AmstradCPC/Machine/CPCBase.Memory.cs | 3 - .../Computers/AmstradCPC/Machine/CPCBase.cs | 3 +- .../AmstradCPC/Media/Tape/CDT/CdtConverter.cs | 65 +++++++++ .../AmstradCPC/SoundProviderMixer.cs | 16 ++- 13 files changed, 287 insertions(+), 99 deletions(-) diff --git a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Abstraction/IPSG.cs b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Abstraction/IPSG.cs index 08435da0d1..826cf338b1 100644 --- a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Abstraction/IPSG.cs +++ b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Abstraction/IPSG.cs @@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC /// /// Represents a PSG device (in this case an AY-3-891x) /// - public interface IPSG : ISoundProvider, IPortIODevice + public interface IPSG : ISoundProvider { /// /// Initlization routine @@ -17,6 +17,8 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC void SetFunction(int data); + //void ClockCycle(); + /// /// Activates a register /// diff --git a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Disk/NECUPD765.IPortIODevice.cs b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Disk/NECUPD765.IPortIODevice.cs index f83b363eaf..6a2c89f506 100644 --- a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Disk/NECUPD765.IPortIODevice.cs +++ b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Disk/NECUPD765.IPortIODevice.cs @@ -71,6 +71,54 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC #endregion + public void ReadStatus(ref int data) + { + // read main status register + // this can happen at any time + data = ReadMainStatus(); + if (writeDebug) + { + //outputString += data + ",,," + ActiveCommand.CommandCode + "\r\n"; + workingArr[0] = data.ToString(); + BuildCSVLine(); + //System.IO.File.WriteAllText(outputfile, outputString); + } + } + + public void ReadData(ref int data) + { + // Z80 is trying to read from the data register + data = ReadDataRegister(); + if (writeDebug) + { + workingArr[2] = data.ToString(); + //outputString += ",," + data + "," + ActiveCommand.CommandCode + "\r\n"; + BuildCSVLine(); + } + } + + public void WriteData(int data) + { + // Z80 is attempting to write to the data register + WriteDataRegister((byte)data); + if (writeDebug) + { + //outputString += "," + data + ",," + ActiveCommand.CommandCode + "\r\n"; + workingArr[1] = data.ToString(); + BuildCSVLine(); + //System.IO.File.WriteAllText(outputfile, outputString); + } + } + + public void Motor(int data) + { + // set disk motor on/off + if (data > 0) + FDD_FLAG_MOTOR = true; + else + FDD_FLAG_MOTOR = false; + } + /// /// Device responds to an IN instruction /// diff --git a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/AmstradGateArray.cs b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/AmstradGateArray.cs index 0420f90167..5658011667 100644 --- a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/AmstradGateArray.cs +++ b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/AmstradGateArray.cs @@ -608,31 +608,31 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC if (CRCT.VSYNC && CRCT.HSYNC) { // both hsync and vsync active - CRT.CurrentLine.AddScanlineCharacter(HCC++, RenderPhase.HSYNCandVSYNC, VideoByte1, VideoByte2, ColourRegisters); + CRT.CurrentLine.AddScanlineCharacter(HCC++, RenderPhase.HSYNCandVSYNC, VideoByte1, VideoByte2, ColourRegisters.ToArray()); //CRT.AddScanlineCharacter(VLC, HCC++, RenderPhase.HSYNCandVSYNC, VideoByte1, VideoByte2, ColourRegisters); } else if (CRCT.VSYNC) { // vsync is active but hsync is not - CRT.CurrentLine.AddScanlineCharacter(HCC++, RenderPhase.VSYNC, VideoByte1, VideoByte2, ColourRegisters); + CRT.CurrentLine.AddScanlineCharacter(HCC++, RenderPhase.VSYNC, VideoByte1, VideoByte2, ColourRegisters.ToArray()); //CRT.AddScanlineCharacter(VLC, HCC++, RenderPhase.VSYNC, VideoByte1, VideoByte2, ColourRegisters); } else if (CRCT.HSYNC) { // hsync is active but vsync is not - CRT.CurrentLine.AddScanlineCharacter(HCC++, RenderPhase.HSYNC, VideoByte1, VideoByte2, ColourRegisters); + CRT.CurrentLine.AddScanlineCharacter(HCC++, RenderPhase.HSYNC, VideoByte1, VideoByte2, ColourRegisters.ToArray()); //CRT.AddScanlineCharacter(VLC, HCC++, RenderPhase.HSYNC, VideoByte1, VideoByte2, ColourRegisters); } else if (!CRCT.DISPTMG) { // border generation - CRT.CurrentLine.AddScanlineCharacter(HCC++, RenderPhase.BORDER, VideoByte1, VideoByte2, ColourRegisters); + CRT.CurrentLine.AddScanlineCharacter(HCC++, RenderPhase.BORDER, VideoByte1, VideoByte2, ColourRegisters.ToArray()); //CRT.AddScanlineCharacter(VLC, HCC++, RenderPhase.BORDER, VideoByte1, VideoByte2, ColourRegisters); } else if (CRCT.DISPTMG) { // pixels generated from video RAM - CRT.CurrentLine.AddScanlineCharacter(HCC++, RenderPhase.DISPLAY, VideoByte1, VideoByte2, ColourRegisters); + CRT.CurrentLine.AddScanlineCharacter(HCC++, RenderPhase.DISPLAY, VideoByte1, VideoByte2, ColourRegisters.ToArray()); } } @@ -656,7 +656,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC { case 0: CRCT.ClockCycle(); - //PSG.ClockCycle(); + //PSG.ClockCycle(FrameClock); WaitLine = false; break; case 1: diff --git a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/CRCT_6845.cs b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/CRCT_6845.cs index 6a6ef8aed4..fd7271f5bb 100644 --- a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/CRCT_6845.cs +++ b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/CRCT_6845.cs @@ -197,6 +197,19 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC } } + /// + /// The offset into vRAM + /// + public int VideoRAMOffset + { + get + { + ushort combined = (ushort)(Regs[12] << 8 | Regs[13]); + int offset = combined & 0x3ff; + return offset; + } + } + /* Easier memory functions */ @@ -210,6 +223,21 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC /// public int ByteCounter; + /// + /// Set at every HSYNC + /// + public int LatchedRAMOffset; + + /// + /// set at every HSYNC + /// + public int LatchedRAMStartAddress; + + /// + /// set at every HSYNC + /// + public int LatchedScreenWidthBytes; + #endregion #region Internal Registers and State @@ -383,12 +411,12 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC /// /// Vertical Character Count /// - private int VCC; + public int VCC; /// /// Vertical Scanline Count /// - private int VLC; + public int VLC; /// /// Internal cycle counter @@ -445,6 +473,11 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC } } + if (HSYNC && HSYNCCounter == 1) + { + + } + // move one horizontal character HCC++; @@ -463,8 +496,15 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC var line = VCC; var row = VLC; - var addr = VideoPageBase + (line * 0x50) + (row * 0x800) + (ByteCounter); - CurrentByteAddress = (ushort)addr; + var addrX = (LatchedRAMOffset * 2) + ((VCC * LatchedScreenWidthBytes) & 0x7ff) + ByteCounter; + // remove artifacts caused by certain hardware scrolling addresses + addrX &= 0x7ff; + var addrY = LatchedRAMStartAddress + (2048 * VLC); + + //var addr = VideoPageBase + (line * (0x50)) + (row * 0x800) + (ByteCounter); + CurrentByteAddress = (ushort)(addrX + addrY); + + ByteCounter += 2; } @@ -558,6 +598,11 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC { HSYNC = true; HSYNCCounter = 0; + + LatchedRAMStartAddress = VideoPageBase; + LatchedRAMOffset = VideoRAMOffset; + LatchedScreenWidthBytes = DisplayWidth * 2; + } } } diff --git a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/CRTDevice.cs b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/CRTDevice.cs index fc9faeb049..23d3e3b641 100644 --- a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/CRTDevice.cs +++ b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/CRTDevice.cs @@ -332,7 +332,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC switch (ScreenMode) { case 0: - Characters[charIndex].Pixels = new int[8]; + Characters[charIndex].Pixels = new int[4]; break; case 1: Characters[charIndex].Pixels = new int[8]; @@ -527,7 +527,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC } // render out the scanline - int pCount = (LineIndex - CRT.TopLinesToTrim) * 2 * CRT.BufferWidth; + int pCount = (LineIndex - CRT.TopLinesToTrim) * vScale * CRT.BufferWidth; // vScale for (int s = 0; s < vScale; s++) diff --git a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/SoundOutput/AY38912.cs b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/SoundOutput/AY38912.cs index e6ec467304..240acb9a2c 100644 --- a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/SoundOutput/AY38912.cs +++ b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/SoundOutput/AY38912.cs @@ -24,10 +24,12 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC private int _tStatesPerFrame; private int _sampleRate; private int _samplesPerFrame; - private int _tStatesPerSample; + private double _tStatesPerSample; private short[] _audioBuffer; private int _audioBufferIndex; private int _lastStateRendered; + private int _clockCyclesPerFrame; + private int _cyclesPerSample; #endregion @@ -39,6 +41,11 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC public AY38912(CPCBase machine) { _machine = machine; + + //_blipL.SetRates(1000000, 44100); + //_blipL.SetRates((_machine.GateArray.FrameLength * 50) / 4, 44100); + //_blipR.SetRates(1000000, 44100); + //_blipR.SetRates((_machine.GateArray.FrameLength * 50) / 4, 44100); } /// @@ -51,46 +58,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC Reset(); } - #endregion - - #region IPortIODevice - - public bool ReadPort(ushort port, ref int value) - { - if (port != 0xfffd) - { - // port read is not addressing this device - return false; - } - - value = PortRead(); - - return true; - } - - public bool WritePort(ushort port, int value) - { - if (port == 0xfffd) - { - // register select - SelectedRegister = value & 0x0f; - return true; - } - else if (port == 0xbffd) - { - // Update the audiobuffer based on the current CPU cycle - // (this process the previous data BEFORE writing to the currently selected register) - int d = (int)(_machine.CurrentFrameCycle); - BufferUpdate(d); - - // write to register - PortWrite(value); - return true; - } - return false; - } - - #endregion + #endregion #region AY Implementation @@ -239,7 +207,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC if (_activeRegister < 16) return _registers[_activeRegister]; } - + return 0; } @@ -366,11 +334,13 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC break; } - + // do audio processing + BufferUpdate((int)_machine.CurrentFrameCycle); + break; } - + } /// @@ -396,7 +366,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC /// public void UpdateSound(int frameCycle) { - BufferUpdate(frameCycle); + BufferUpdate(frameCycle); } #endregion @@ -471,7 +441,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC /// /// The frequency of the AY chip /// - private static int _chipFrequency = 1773400; + private static int _chipFrequency = 1000000; // 1773400; /// /// The rendering resolution of the chip @@ -640,8 +610,6 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC } } - private int mult_const; - /// /// Initializes timing information for the frame /// @@ -651,21 +619,19 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC { _sampleRate = sampleRate; _tStatesPerFrame = frameTactCount; - _samplesPerFrame = 882; + _samplesPerFrame = sampleRate / 50; //882 - _tStatesPerSample = 79; //(int)Math.Round(((double)_tStatesPerFrame * 50D) / - //(16D * (double)_sampleRate), - //MidpointRounding.AwayFromZero); - - //_samplesPerFrame = _tStatesPerFrame / _tStatesPerSample; - _audioBuffer = new short[_samplesPerFrame * 2]; //[_sampleRate / 50]; + _tStatesPerSample = (double)frameTactCount / (double)_samplesPerFrame; // 90; //(int)Math.Round(((double)_tStatesPerFrame * 50D) / + //(16D * (double)_sampleRate), + //MidpointRounding.AwayFromZero); + _audioBuffer = new short[_samplesPerFrame * 2]; _audioBufferIndex = 0; - mult_const = ((_chipFrequency / 8) << 14) / _machine.GateArray.Z80ClockSpeed; - - var aytickspercputick = (double)_machine.GateArray.Z80ClockSpeed / (double)_chipFrequency; - int ayCyclesPerSample = (int)((double)_tStatesPerSample * (double)aytickspercputick); + ticksPerSample = ((double)_chipFrequency / sampleRate / 8); } + private double ticksPerSample; + + private double tickCounter = 0; /// /// Updates the audiobuffer based on the current frame t-state @@ -682,14 +648,18 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC // get the current length of the audiobuffer int bufferLength = _samplesPerFrame; // _audioBuffer.Length; - int toEnd = ((bufferLength * cycle) / _tStatesPerFrame); + double toEnd = ((double)(bufferLength * cycle) / (double)_tStatesPerFrame); // loop through the number of samples we need to render while (_audioBufferIndex < toEnd) { // run the AY chip processing at the correct resolution - for (int i = 0; i < _tStatesPerSample / 14; i++) + tickCounter += ticksPerSample; + + while (tickCounter > 0) { + tickCounter--; + if (++_countA >= _dividerA) { _countA = 0; @@ -795,6 +765,8 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC public void DiscardSamples() { _audioBuffer = new short[_samplesPerFrame * 2]; + //_blipL.Clear(); + //_blipR.Clear(); } public void GetSamplesSync(out short[] samples, out int nsamp) @@ -802,6 +774,43 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC nsamp = _samplesPerFrame; samples = _audioBuffer; DiscardSamples(); + tickCounter = 0; + return; + /* + _blipL.EndFrame((uint)SampleClock); + _blipR.EndFrame((uint)SampleClock); + SampleClock = 0; + + int sampL = _blipL.SamplesAvailable(); + int sampR = _blipR.SamplesAvailable(); + + if (sampL > sampR) + nsamp = sampL; + else + nsamp = sampR; + + short[] buffL = new short[sampL]; + short[] buffR = new short[sampR]; + + _blipL.ReadSamples(buffL, sampL - 1, false); + _blipR.ReadSamples(buffR, sampR - 1, false); + + if (_audioBuffer.Length != nsamp * 2) + _audioBuffer = new short[nsamp * 2]; + + int p = 0; + for (int i = 0; i < nsamp; i++) + { + if (i < sampL) + _audioBuffer[p++] = buffL[i]; + if (i < sampR) + _audioBuffer[p++] = buffR[i]; + } + + //nsamp = _samplesPerFrame; + samples = _audioBuffer; + DiscardSamples(); + */ } #endregion @@ -823,7 +832,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC ser.Sync("_tStatesPerFrame", ref _tStatesPerFrame); ser.Sync("_sampleRate", ref _sampleRate); ser.Sync("_samplesPerFrame", ref _samplesPerFrame); - ser.Sync("_tStatesPerSample", ref _tStatesPerSample); + //ser.Sync("_tStatesPerSample", ref _tStatesPerSample); ser.Sync("_audioBufferIndex", ref _audioBufferIndex); ser.Sync("_audioBuffer", ref _audioBuffer, false); ser.Sync("PortAInput", ref PortAInput); diff --git a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/SoundOutput/Beeper.cs b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/SoundOutput/Beeper.cs index 27c8820c91..5f1f96c92e 100644 --- a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/SoundOutput/Beeper.cs +++ b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/SoundOutput/Beeper.cs @@ -73,7 +73,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC /// /// Device blipbuffer /// - private readonly BlipBuffer blip = new BlipBuffer(1024); + private readonly BlipBuffer blip = new BlipBuffer(883); #endregion @@ -122,7 +122,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC /// public void Init(int sampleRate, int tStatesPerFrame) { - blip.SetRates((tStatesPerFrame * 50), sampleRate); + blip.SetRates((4000000), sampleRate); _sampleRate = sampleRate; _tStatesPerFrame = tStatesPerFrame; } diff --git a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPC6128/CPC6128.Port.cs b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPC6128/CPC6128.Port.cs index 532bfaa574..089bab38b8 100644 --- a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPC6128/CPC6128.Port.cs +++ b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPC6128/CPC6128.Port.cs @@ -49,7 +49,20 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC } else if (DecodeINPort(port) == PortDevice.Expansion) { - + if (!port.Bit(7)) + { + // FDC + if (port.Bit(8) && !port.Bit(0)) + { + // FDC status register + UPDDiskDevice.ReadStatus(ref result); + } + if (port.Bit(8) && port.Bit(0)) + { + // FDC data register + UPDDiskDevice.ReadData(ref result); + } + } } return (byte)result; @@ -104,7 +117,20 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC } else if (d == PortDevice.Expansion) { - + if (!port.Bit(7)) + { + // FDC + if (port.Bit(8) && !port.Bit(0) || port.Bit(8) && port.Bit(0)) + { + // FDC data register + UPDDiskDevice.WriteData(value); + } + if ((!port.Bit(8) && !port.Bit(0)) || (!port.Bit(8) && port.Bit(0))) + { + // FDC motor + UPDDiskDevice.Motor(value); + } + } } } diff --git a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPCBase.Media.cs b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPCBase.Media.cs index fbe8b3b2de..3cf30ce22d 100644 --- a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPCBase.Media.cs +++ b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPCBase.Media.cs @@ -157,19 +157,13 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC /// protected void LoadDiskMedia() { - /* - if (this.GetType() != typeof(ZX128Plus3)) + if (this.GetType() == typeof(CPC464)) { - Spectrum.CoreComm.ShowMessage("You are trying to load one of more disk images.\n\n Please select ZX Spectrum +3 emulation immediately and reboot the core"); + CPC.CoreComm.ShowMessage("You are trying to load one of more disk images.\n\n Please select something other than CPC 464 emulation immediately and reboot the core"); return; } - else - { - //Spectrum.CoreComm.ShowMessage("You are attempting to load a disk into the +3 disk drive.\n\nThis DOES NOT currently work properly but IS under active development."); - } UPDDiskDevice.FDD_LoadDisk(diskImages[diskMediaIndex]); - */ } /// @@ -194,7 +188,6 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC // cdt tape file return CPCMediaType.Tape; } - // not found return CPCMediaType.None; diff --git a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPCBase.Memory.cs b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPCBase.Memory.cs index aca1a891bc..fca9c18f31 100644 --- a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPCBase.Memory.cs +++ b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPCBase.Memory.cs @@ -63,9 +63,6 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC /// public int RAM64KBank; - - - #endregion #region Memory Related Methods diff --git a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPCBase.cs b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPCBase.cs index a12f467615..6dc9ba3ee2 100644 --- a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPCBase.cs +++ b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPCBase.cs @@ -152,8 +152,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC if (_renderSound) { - if (AYDevice != null) - AYDevice.StartFrame(); + AYDevice.StartFrame(); } PollInput(); diff --git a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Tape/CDT/CdtConverter.cs b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Tape/CDT/CdtConverter.cs index 2d55037182..304d53d0ab 100644 --- a/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Tape/CDT/CdtConverter.cs +++ b/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Tape/CDT/CdtConverter.cs @@ -58,6 +58,55 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC #endregion + /// + /// CDT format is essentially exactly the same as the TZX format + /// However all timings are based on spectrum timings (3.5Mhz) + /// so need to be adjusted for the CPC (4Mhz) + /// + /// + /// + private TapeDataBlock ConvertClock(TapeDataBlock db) + { + TapeDataBlock tb = new TapeDataBlock(); + tb.BlockDescription = db.BlockDescription; + tb.BlockID = db.BlockID; + tb.Command = db.Command; + tb.DataPeriods = new List(); + tb.InitialPulseLevel = db.InitialPulseLevel; + tb.MetaData = db.MetaData; + tb.PauseInMS = db.PauseInMS; + + double multiplier = (double)4 / (double)3.5; + double cycleScale = ((40 << 16) / 35); + double origPeriods = db.DataPeriods.Count(); + + for (int i = 0; i < origPeriods; i++) + { + int orig = db.DataPeriods[i]; + int np = (int)((double)orig * multiplier); + int nnp = ClockAdjust(orig); + tb.DataPeriods.Add(np); + } + + return tb; + } + + private int ClockAdjust(int val) + { + int cycleScale = ((40 << 16) / 35); + int res = (val * cycleScale) >> 16; + return res; + } + + private int Scale => ((40 << 16) / 35); + + private int Adjust(int val) + { + return (int)((val * CLOCK_MULTIPLIER)); + } + + private const double CLOCK_MULTIPLIER = 1.142857; + /// /// Returns TRUE if tzx header is detected /// @@ -142,6 +191,17 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC ProcessBlock(data, ID); } + /* + // convert for Amstrad CPC + List newBlocks = new List(); + for (int i = 0; i < _datacorder.DataBlocks.Count(); i++) + { + newBlocks.Add(ConvertClock(_datacorder.DataBlocks[i])); + } + + _datacorder.DataBlocks.Clear(); + _datacorder.DataBlocks.AddRange(newBlocks); + */ } /// @@ -1632,6 +1692,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC int bitsInLastByte = 8 ) { + // first get the block description string description = string.Empty; @@ -1857,12 +1918,16 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC ) { + + int pilotCount = 3220; + /* // pilot count needs to be ascertained from flag byte int pilotCount; if (blockData[0] < 128) pilotCount = 8063; else pilotCount = 3223; + */ // now we can decode var nBlock = DecodeDataBlock diff --git a/BizHawk.Emulation.Cores/Computers/AmstradCPC/SoundProviderMixer.cs b/BizHawk.Emulation.Cores/Computers/AmstradCPC/SoundProviderMixer.cs index 02bbd57117..77e30f5fca 100644 --- a/BizHawk.Emulation.Cores/Computers/AmstradCPC/SoundProviderMixer.cs +++ b/BizHawk.Emulation.Cores/Computers/AmstradCPC/SoundProviderMixer.cs @@ -184,8 +184,8 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC } else { - // just process what we have as-is - } + // just process what we have as-is + } } // mix the soundproviders together @@ -197,10 +197,14 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC short sectorVal = 0; foreach (var sp in SoundProviders) { - if (sp.Buffer[i] > sp.MaxVolume) - sectorVal += (short)sp.MaxVolume; - else - sectorVal += sp.Buffer[i]; + if (i < sp.Buffer.Length) + { + if (sp.Buffer[i] > sp.MaxVolume) + sectorVal += (short)sp.MaxVolume; + else + sectorVal += sp.Buffer[i]; + } + } samples[i] = sectorVal;