CPCHawk: Datacorder & tape sound, GateArray renderer modes 0, 1 & 2

This commit is contained in:
Asnivor 2018-07-18 12:28:39 +01:00
parent c0fcac5ab1
commit f35bb99c5f
11 changed files with 247 additions and 350 deletions

View File

@ -91,11 +91,16 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
[DefaultValue(true)]
public bool DeterministicEmulation { get; set; }
[DisplayName("CPC model")]
[DisplayName("CPC Model")]
[Description("The model of Amstrad CPC machine to be emulated")]
[DefaultValue(MachineType.CPC464)]
public MachineType MachineType { get; set; }
[DisplayName("Auto Start/Stop Tape")]
[Description("If true, CPCHawk will automatically start and stop the tape when the tape motor is triggered")]
[DefaultValue(true)]
public bool AutoStartStopTape { get; set; }
public AmstradCPCSyncSettings Clone()
{
return (AmstradCPCSyncSettings)MemberwiseClone();

View File

@ -167,6 +167,34 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
SendMessage(sb.ToString().TrimEnd('\n'), MessageCategory.Emulator);
}
/// <summary>
/// Tape message that is fired when tape is playing
/// </summary>
public void OSD_TapeMotorActive()
{
if (_tapeInfo.Count == 0)
return;
StringBuilder sb = new StringBuilder();
sb.Append("MOTOR ON (" + _machine.TapeMediaIndex + ": " + _tapeInfo[_machine.TapeMediaIndex].Name + ")");
SendMessage(sb.ToString().TrimEnd('\n'), MessageCategory.Tape);
}
/// <summary>
/// Tape message that is fired when tape is playing
/// </summary>
public void OSD_TapeMotorInactive()
{
if (_tapeInfo.Count == 0)
return;
StringBuilder sb = new StringBuilder();
sb.Append("MOTOR OFF (" + _machine.TapeMediaIndex + ": " + _tapeInfo[_machine.TapeMediaIndex].Name + ")");
SendMessage(sb.ToString().TrimEnd('\n'), MessageCategory.Tape);
}
/// <summary>
/// Tape message that is fired when tape is playing
/// </summary>
@ -176,7 +204,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
return;
StringBuilder sb = new StringBuilder();
sb.Append("PLAYING (" + _machine.TapeMediaIndex + ": " + _tapeInfo[_machine.TapeMediaIndex].Name + ")");
sb.Append("PLAYING MANUAL (" + _machine.TapeMediaIndex + ": " + _tapeInfo[_machine.TapeMediaIndex].Name + ")");
SendMessage(sb.ToString().TrimEnd('\n'), MessageCategory.Tape);
}
@ -190,7 +218,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
return;
StringBuilder sb = new StringBuilder();
sb.Append("STOPPED (" + _machine.TapeMediaIndex + ": " + _tapeInfo[_machine.TapeMediaIndex].Name + ")");
sb.Append("STOPPED MANUAL (" + _machine.TapeMediaIndex + ": " + _tapeInfo[_machine.TapeMediaIndex].Name + ")");
SendMessage(sb.ToString().TrimEnd('\n'), MessageCategory.Tape);
}

View File

@ -46,7 +46,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
{
case MachineType.CPC464:
ControllerDefinition = AmstradCPCControllerDefinition;
Init(MachineType.CPC464, _files);
Init(MachineType.CPC464, _files, ((AmstradCPCSyncSettings)syncSettings as AmstradCPCSyncSettings).AutoStartStopTape);
break;
default:
throw new InvalidOperationException("Machine not yet emulated");
@ -139,7 +139,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
private MachineType _machineType;
private void Init(MachineType machineType, List<byte[]> files)
private void Init(MachineType machineType, List<byte[]> files, bool autoTape)
{
_machineType = machineType;
@ -147,7 +147,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
switch (machineType)
{
case MachineType.CPC464:
_machine = new CPC464(this, _cpu, files);
_machine = new CPC464(this, _cpu, files, autoTape);
var _systemRom16 = GetFirmware(0x4000, "464ROM");
var romData16 = RomData.InitROM(machineType, _systemRom16);
_machine.InitROM(romData16);

View File

@ -8,22 +8,22 @@ using System.Text;
namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
{
/// <summary>
/// Represents the tape device (or build-in datacorder as it was called +2 and above)
/// Represents the tape device
/// </summary>
public class DatacorderDevice : IPortIODevice
public class DatacorderDevice
{
#region Construction
private CPCBase _machine { get; set; }
private Z80A _cpu { get; set; }
private IBeeperDevice _buzzer { get; set; }
private CPCBase _machine;
private Z80A _cpu => _machine.CPU;
private IBeeperDevice _buzzer => _machine.TapeBuzzer;
/// <summary>
/// Default constructor
/// </summary>
public DatacorderDevice()
public DatacorderDevice(bool autoTape)
{
_autoPlay = autoTape;
}
/// <summary>
@ -33,8 +33,6 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
public void Init(CPCBase machine)
{
_machine = machine;
_cpu = _machine.CPU;
_buzzer = machine.TapeBuzzer;
}
#endregion
@ -44,7 +42,38 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// <summary>
/// Signs whether the tape motor is running
/// </summary>
public bool TapeMotor;
private bool tapeMotor;
public bool TapeMotor
{
get { return tapeMotor; }
set
{
if (tapeMotor == value)
return;
tapeMotor = value;
if (tapeMotor)
{
_machine.CPC.OSD_TapeMotorActive();
if (_autoPlay)
{
Play();
}
}
else
{
_machine.CPC.OSD_TapeMotorInactive();
if (_autoPlay)
{
Stop();
}
}
}
}
/// <summary>
/// Internal counter used to trigger tape buzzer output
@ -140,7 +169,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// </summary>
public void EndFrame()
{
MonitorFrame();
//MonitorFrame();
}
public void StartFrame()
@ -160,8 +189,11 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
if (_tapeIsPlaying)
return;
if (!_autoPlay)
_machine.CPC.OSD_TapePlaying();
_machine.CPC.OSD_TapeMotorActive();
// update the lastCycle
_lastCycle = _cpu.TotalExecutedCycles;
@ -368,7 +400,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// </summary>
public void TapeCycle()
{
if (TapeIsPlaying)
if (TapeMotor)
{
counter++;
@ -391,10 +423,8 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
// decide how many cycles worth of data we are capturing
long cycles = cpuCycle - _lastCycle;
//bool is48k = _machine.IsIn48kMode();
// check whether tape is actually playing
if (_tapeIsPlaying == false)
if (tapeMotor == false)
{
// it's not playing. Update lastCycle and return
_lastCycle = cpuCycle;
@ -415,7 +445,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
// decrement cycles
cycles -= _waitEdge;
if (_position == 0 && _tapeIsPlaying)
if (_position == 0 && tapeMotor)
{
// start of block - take care of initial pulse level for PZX
switch (_dataBlocks[_currentDataBlockIndex].BlockDescription)
@ -437,6 +467,53 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
break;
}
// most of these amstrad tapes appear to have a pause block at the start
// skip this if it is the first block
switch (_dataBlocks[_currentDataBlockIndex].BlockDescription)
{
case BlockType.PAUS:
case BlockType.PAUSE_BLOCK:
case BlockType.Pause_or_Stop_the_Tape:
if (_currentDataBlockIndex == 0)
{
// this is the first block on the tape
SkipBlock(true);
}
else
{
// there may be non-data blocks before this
bool okToSkipPause = true;
for (int i = _currentDataBlockIndex; i >= 0; i--)
{
switch (_dataBlocks[i].BlockDescription)
{
case BlockType.Archive_Info:
case BlockType.BRWS:
case BlockType.Custom_Info_Block:
case BlockType.Emulation_Info:
case BlockType.Glue_Block:
case BlockType.Hardware_Type:
case BlockType.Message_Block:
case BlockType.PZXT:
case BlockType.Text_Description:
break;
default:
okToSkipPause = false;
break;
}
if (!okToSkipPause)
break;
}
if (okToSkipPause)
{
SkipBlock(true);
}
}
break;
}
// notify about the current block
var bl = _dataBlocks[_currentDataBlockIndex];
@ -576,188 +653,11 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
currentState = !currentState;
}
/// <summary>
/// Flash loading implementation
/// (Deterministic Emulation must be FALSE)
/// </summary>
private bool FlashLoad()
{
// deterministic emulation must = false
//if (_machine.Spectrum.SyncSettings.DeterministicEmulation)
//return;
var util = _machine.CPC;
if (_currentDataBlockIndex < 0)
_currentDataBlockIndex = 0;
if (_currentDataBlockIndex >= DataBlocks.Count)
return false;
//var val = GetEarBit(_cpu.TotalExecutedCycles);
//_buzzer.ProcessPulseValue(true, val);
ushort addr = _cpu.RegPC;
if (_machine.CPC.SyncSettings.DeterministicEmulation)
{
}
var tb = DataBlocks[_currentDataBlockIndex];
var tData = tb.BlockData;
if (tData == null || tData.Length < 2)
{
// skip this
return false;
}
var toRead = tData.Length - 1;
if (toRead < _cpu.Regs[_cpu.E] + (_cpu.Regs[_cpu.D] << 8))
{
}
else
{
toRead = _cpu.Regs[_cpu.E] + (_cpu.Regs[_cpu.D] << 8);
}
if (toRead <= 0)
return false;
var parity = tData[0];
if (parity != _cpu.Regs[_cpu.F_s] + (_cpu.Regs[_cpu.A_s] << 8) >> 8)
return false;
util.SetCpuRegister("Shadow AF", 0x0145);
for (var i = 0; i < toRead; i++)
{
var v = tData[i + 1];
_cpu.Regs[_cpu.L] = v;
parity ^= v;
var d = (ushort)(_cpu.Regs[_cpu.Ixl] + (_cpu.Regs[_cpu.Ixh] << 8) + 1);
_machine.WriteBus(d, v);
}
var pc = (ushort)0x05DF;
if (_cpu.Regs[_cpu.E] + (_cpu.Regs[_cpu.D] << 8) == toRead &&
toRead + 1 < tData.Length)
{
var v = tData[toRead + 1];
_cpu.Regs[_cpu.L] = v;
parity ^= v;
_cpu.Regs[_cpu.B] = 0xB0;
}
else
{
_cpu.Regs[_cpu.L] = 1;
_cpu.Regs[_cpu.B] = 0;
_cpu.Regs[_cpu.F] = 0x50;
_cpu.Regs[_cpu.A] = parity;
pc = 0x05EE;
}
_cpu.Regs[_cpu.H] = parity;
var de = _cpu.Regs[_cpu.E] + (_cpu.Regs[_cpu.D] << 8);
util.SetCpuRegister("DE", de - toRead);
var ix = _cpu.Regs[_cpu.Ixl] + (_cpu.Regs[_cpu.Ixh] << 8);
util.SetCpuRegister("IX", ix + toRead);
util.SetCpuRegister("PC", pc);
_currentDataBlockIndex++;
return true;
}
#endregion
#region TapeMonitor
private long _lastINCycle = 0;
private int _monitorCount;
private int _monitorTimeOut;
private ushort _monitorLastPC;
private ushort[] _monitorLastRegs = new ushort[7];
/// <summary>
/// Resets the TapeMonitor
/// </summary>
private void MonitorReset()
{
_lastINCycle = 0;
_monitorCount = 0;
_monitorLastPC = 0;
_monitorLastRegs = null;
}
/// <summary>
/// An iteration of the monitor process
/// </summary>
public void MonitorRead()
{
long cpuCycle = _cpu.TotalExecutedCycles;
int delta = (int)(cpuCycle - _lastINCycle);
_lastINCycle = cpuCycle;
var nRegs = new ushort[]
{
_cpu.Regs[_cpu.A],
_cpu.Regs[_cpu.B],
_cpu.Regs[_cpu.C],
_cpu.Regs[_cpu.D],
_cpu.Regs[_cpu.E],
_cpu.Regs[_cpu.H],
_cpu.Regs[_cpu.L]
};
if (delta > 0 &&
delta < 96 &&
_cpu.RegPC == _monitorLastPC &&
_monitorLastRegs != null)
{
int dCnt = 0;
int dVal = 0;
for (int i = 0; i < nRegs.Length; i++)
{
if (_monitorLastRegs[i] != nRegs[i])
{
dVal = _monitorLastRegs[i] - nRegs[i];
dCnt++;
}
}
if (dCnt == 1 &&
(dVal == 1 || dVal == -1))
{
_monitorCount++;
if (_monitorCount >= 16 && _autoPlay)
{
if (!_tapeIsPlaying)
{
Play();
_machine.CPC.OSD_TapePlayingAuto();
}
_monitorTimeOut = 50;
}
}
else
{
_monitorCount = 0;
}
}
_monitorLastRegs = nRegs;
_monitorLastPC = _cpu.RegPC;
}
public void AutoStopTape()
{
@ -783,6 +683,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
_machine.CPC.OSD_TapePlayingAuto();
}
/*
public int MaskableInterruptCount = 0;
private void MonitorFrame()
@ -851,6 +752,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
}
}
}
*/
#endregion
@ -866,15 +768,14 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// <summary>
/// Device responds to an IN instruction
/// </summary>
/// <param name="port"></param>
/// <param name="result"></param>
/// <returns></returns>
public bool ReadPort(ushort port, ref int result)
public bool ReadPort()
{
if (TapeIsPlaying)
{
GetEarBit(_cpu.TotalExecutedCycles);
}
/*
if (currentState)
{
result |= TAPE_BIT;
@ -883,55 +784,15 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
{
result &= ~TAPE_BIT;
}
*/
if (!TapeIsPlaying)
{
if (_machine.UPDDiskDevice == null || !_machine.UPDDiskDevice.FDD_IsDiskLoaded)
MonitorRead();
//if (_machine.UPDDiskDevice == null || !_machine.UPDDiskDevice.FDD_IsDiskLoaded)
//MonitorRead();
}
if (_machine.UPDDiskDevice == null || !_machine.UPDDiskDevice.FDD_IsDiskLoaded)
MonitorRead();
/*
if (TapeIsPlaying)
{
if (GetEarBit(_cpu.TotalExecutedCycles))
{
result &= ~(TAPE_BIT); // reset is EAR ON
}
else
{
result |= (TAPE_BIT); // set is EAR Off
}
}
else
{
if (_machine.KeyboardDevice.IsIssue2Keyboard)
{
if ((_machine.LASTULAOutByte & (EAR_BIT + MIC_BIT)) == 0)
{
result &= ~(TAPE_BIT);
}
else
{
result |= (TAPE_BIT);
}
}
else
{
if ((_machine.LASTULAOutByte & EAR_BIT) == 0)
{
result &= ~(TAPE_BIT);
}
else
{
result |= TAPE_BIT;
}
}
}
*/
//if (_machine.UPDDiskDevice == null || !_machine.UPDDiskDevice.FDD_IsDiskLoaded)
//MonitorRead();
return true;
}
@ -939,17 +800,18 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// <summary>
/// Device responds to an OUT instruction
/// </summary>
/// <param name="port"></param>
/// <param name="result"></param>
/// <param name="state"></param>
/// <returns></returns>
public bool WritePort(ushort port, int result)
public void WritePort(bool state)
{
// not implemented
/*
if (!TapeIsPlaying)
{
currentState = ((byte)result & 0x10) != 0;
}
return true;
*/
}
#endregion
@ -970,12 +832,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
ser.Sync("_lastCycle", ref _lastCycle);
ser.Sync("_waitEdge", ref _waitEdge);
ser.Sync("currentState", ref currentState);
ser.Sync("_lastINCycle", ref _lastINCycle);
ser.Sync("_monitorCount", ref _monitorCount);
ser.Sync("_monitorTimeOut", ref _monitorTimeOut);
ser.Sync("_monitorLastPC", ref _monitorLastPC);
ser.Sync("_monitorLastRegs", ref _monitorLastRegs, false);
ser.Sync("TapeMotor", ref TapeMotor);
ser.Sync("TapeMotor", ref tapeMotor);
ser.EndSection();
}

View File

@ -168,6 +168,11 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
{
_RMR = value;
//ScreenMode = _RMR & 0x03;
var sm = _RMR & 0x03;
if (sm != 1)
{
}
if ((_RMR & 0x08) != 0)
_machine.UpperROMPaged = false;
@ -254,7 +259,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// <summary>
/// Master frame clock counter
/// </summary>
private int FrameClock;
public int FrameClock;
/// <summary>
/// Simulates the gate array memory /WAIT line
@ -354,7 +359,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
// check for frame end
if (FrameClock == FrameLength)
{
FrameClock = 0;
//FrameClock = 0;
FrameEnd = true;
}
}
@ -502,7 +507,6 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
// update screenmode
ScreenMode = RMR & 0x03;
CRT.CurrentLine.InitScanline(ScreenMode, VLC);
//CRT.InitScanline(VLC, ScreenMode);
}
else if (!CRCT.HSYNC)
{
@ -786,6 +790,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
ser.Sync("CurrentPen", ref CurrentPen);
ser.Sync("ClockCounter", ref ClockCounter);
ser.Sync("FrameClock", ref FrameClock);
ser.Sync("FrameEnd", ref FrameEnd);
ser.Sync("WaitLine", ref WaitLine);
ser.Sync("_interruptCounter", ref _interruptCounter);
ser.Sync("ScreenMode", ref ScreenMode);
@ -796,6 +801,12 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
ser.Sync("InterruptRaised", ref InterruptRaised);
ser.Sync("InterruptHoldCounter", ref InterruptHoldCounter);
ser.Sync("_MA", ref _MA);
ser.Sync("IsNewFrame", ref IsNewFrame);
ser.Sync("IsNewLine", ref IsNewLine);
ser.Sync("HCC", ref HCC);
ser.Sync("VLC", ref VLC);
ser.Sync("VideoByte1", ref VideoByte1);
ser.Sync("VideoByte2", ref VideoByte2);
ser.EndSection();
}

View File

@ -206,7 +206,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
public ushort CurrentByteAddress;
/// <summary>
/// ByteCOunter
/// ByteCounter
/// </summary>
public int ByteCounter;
@ -890,6 +890,8 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
ser.Sync("VSYNC", ref VSYNC);
ser.Sync("DISPTMG", ref DISPTMG);
ser.Sync("MA", ref MA);
ser.Sync("CurrentByteAddress", ref CurrentByteAddress);
ser.Sync("ByteCounter", ref ByteCounter);
ser.Sync("Regs", ref Regs, false);
ser.Sync("SelectedRegister", ref SelectedRegister);
ser.Sync("HCC", ref HCC);

View File

@ -231,7 +231,13 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
public void SyncState(Serializer ser)
{
ser.BeginSection("CRT");
ser.BeginSection("CRT");
ser.Sync("BufferWidth", ref _bufferWidth);
ser.Sync("BufferHeight", ref _bufferHeight);
ser.Sync("VirtualHeight", ref _virtualHeight);
ser.Sync("VirtualWidth", ref _virtualWidth);
ser.Sync("ScreenBuffer", ref ScreenBuffer, false);
ser.Sync("ScanlineCounter", ref ScanlineCounter);
ser.EndSection();
}
@ -322,7 +328,24 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
private void AddBorderValue(int charIndex, int colourValue)
{
Characters[charIndex].Phase = RenderPhase.BORDER;
Characters[charIndex].Pixels = new int[8];
switch (ScreenMode)
{
case 0:
Characters[charIndex].Pixels = new int[8];
break;
case 1:
Characters[charIndex].Pixels = new int[8];
break;
case 2:
Characters[charIndex].Pixels = new int[16];
break;
case 3:
Characters[charIndex].Pixels = new int[8];
break;
}
for (int i = 0; i < Characters[charIndex].Pixels.Length; i++)
{
@ -345,8 +368,9 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
switch (ScreenMode)
{
// 4 bits per pixel - 2 bytes - 4 pixels (8 CRT pixels)
// RECT
case 0:
Characters[charIndex].Pixels = new int[4];
Characters[charIndex].Pixels = new int[8];
int m0Count = 0;
@ -356,18 +380,23 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
int m0B0P1 = ((m0B0P1i & 0x40) >> 6) | ((m0B0P1i & 0x04) >> 1) | ((m0B0P1i & 0x10) >> 2) | ((m0B0P1i & 0x01 << 3));
Characters[charIndex].Pixels[m0Count++] = CRTDevice.CPCHardwarePalette[pens[m0B0P0]];
Characters[charIndex].Pixels[m0Count++] = CRTDevice.CPCHardwarePalette[pens[m0B0P0]];
Characters[charIndex].Pixels[m0Count++] = CRTDevice.CPCHardwarePalette[pens[m0B0P1]];
Characters[charIndex].Pixels[m0Count++] = CRTDevice.CPCHardwarePalette[pens[m0B0P1]];
int m0B1P0i = vid1 & 170;
int m0B1P0i = vid2 & 170;
int m0B1P0 = ((m0B1P0i & 0x80) >> 7) | ((m0B1P0i & 0x08) >> 2) | ((m0B1P0i & 0x20) >> 3) | ((m0B1P0i & 0x02 << 2));
int m0B1P1i = vid1 & 85;
int m0B1P1i = vid2 & 85;
int m0B1P1 = ((m0B1P1i & 0x40) >> 6) | ((m0B1P1i & 0x04) >> 1) | ((m0B1P1i & 0x10) >> 2) | ((m0B1P1i & 0x01 << 3));
Characters[charIndex].Pixels[m0Count++] = CRTDevice.CPCHardwarePalette[pens[m0B1P0]];
Characters[charIndex].Pixels[m0Count++] = CRTDevice.CPCHardwarePalette[pens[m0B1P0]];
Characters[charIndex].Pixels[m0Count++] = CRTDevice.CPCHardwarePalette[pens[m0B1P1]];
Characters[charIndex].Pixels[m0Count++] = CRTDevice.CPCHardwarePalette[pens[m0B1P1]];
break;
// 2 bits per pixel - 2 bytes - 8 pixels (16 CRT pixels)
// SQUARE
case 1:
Characters[charIndex].Pixels = new int[8];
@ -394,18 +423,21 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
Characters[charIndex].Pixels[m1Count++] = CRTDevice.CPCHardwarePalette[pens[m1B1P3]];
break;
// 1 bit per pixel - 2 bytes - 16 pixels (32 CRT pixels)
// 1 bit per pixel - 2 bytes - 16 pixels (16 CRT pixels)
// RECT
case 2:
Characters[charIndex].Pixels = new int[16];
int m2Count = 0;
int[] pixBuff = new int[16];
for (int bit = 7; bit >= 0; bit--)
{
int val = vid1.Bit(bit) ? 1 : 0;
Characters[charIndex].Pixels[m2Count++] = CRTDevice.CPCHardwarePalette[pens[val]];
}
}
for (int bit = 7; bit >= 0; bit--)
{
int val = vid2.Bit(bit) ? 1 : 0;
@ -414,6 +446,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
break;
// 4 bits per pixel - 2 bytes - 4 pixels (8 CRT pixels)
// RECT
case 3:
Characters[charIndex].Pixels = new int[4];
@ -460,8 +493,27 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// Processes and adds the scanline to the Screen Buffer
/// </summary>
public void CommitScanline()
{
int hPix = GetPixelCount() * 2;
{
int hScale = 1;
int vScale = 1;
switch (ScreenMode)
{
case 0:
case 1:
case 3:
hScale = 2;
vScale = 2;
break;
case 2:
hScale = 1;
vScale = 2;
break;
}
int hPix = GetPixelCount() * hScale;
//int hPix = GetPixelCount() * 2;
int leftOver = CRT.BufferWidth - hPix;
int lPad = leftOver / 2;
int rPad = lPad;
@ -477,8 +529,8 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
// render out the scanline
int pCount = (LineIndex - CRT.TopLinesToTrim) * 2 * CRT.BufferWidth;
// double up
for (int s = 0; s < 2; s++)
// vScale
for (int s = 0; s < vScale; s++)
{
// left padding
for (int lP = 0; lP < lPad; lP++)
@ -494,8 +546,13 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
for (int p = 0; p < c.Pixels.Length; p++)
{
CRT.ScreenBuffer[pCount++] = c.Pixels[p];
CRT.ScreenBuffer[pCount++] = c.Pixels[p];
// hScale
for (int h = 0; h < hScale; h++)
{
CRT.ScreenBuffer[pCount++] = c.Pixels[p];
}
//CRT.ScreenBuffer[pCount++] = c.Pixels[p];
}
}

View File

@ -73,7 +73,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// <summary>
/// Device blipbuffer
/// </summary>
private readonly BlipBuffer blip = new BlipBuffer(882);
private readonly BlipBuffer blip = new BlipBuffer(1024);
#endregion

View File

@ -56,56 +56,6 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
}
return (byte)result;
if ((port & 0x8000) == 0)
{
if ((port & 0x4000) != 0)
{
GateArray.ReadPort(port, ref result);
}
else
{
// ram
}
}
else if ((port & 0x4000) == 0)
{
CRCT.ReadPort(port, ref result);
}
else if ((port & 0x0300) == 0)
{
// rom
}
else if ((port & 0x1000) == 0)
{
// printer
}
else if ((port & 0x0800) == 0)
{
PPI.ReadPort(port, ref result);
}
else if ((port & 0x0400) == 0)
{
// exp
}
return (byte)result;
if (CRCT.ReadPort(port, ref result))
{
return (byte)result;
}
else if (PPI.ReadPort(port, ref result))
{
return (byte)result;
}
else if (GateArray.ReadPort(port, ref result))
{
return (byte)result;
}
return (byte)result;
}
/// <summary>
@ -156,18 +106,6 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
}
return;
if (GateArray.WritePort(port, value))
{ }
if (CRCT.WritePort(port, value))
{ }
// rom select
// printer port
if (PPI.WritePort(port, value))
{ }
}
}
}

View File

@ -16,7 +16,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// </summary>
/// <param name="spectrum"></param>
/// <param name="cpu"></param>
public CPC464(AmstradCPC cpc, Z80A cpu, List<byte[]> files)
public CPC464(AmstradCPC cpc, Z80A cpu, List<byte[]> files, bool autoTape)
{
CPC = cpc;
CPU = cpu;
@ -37,7 +37,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
KeyboardDevice = new StandardKeyboard(this);
TapeDevice = new DatacorderDevice();
TapeDevice = new DatacorderDevice(autoTape);
TapeDevice.Init(this);
InitializeMedia(files);

View File

@ -109,7 +109,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// <summary>
/// Gets the current frame cycle according to the CPU tick count
/// </summary>
public virtual long CurrentFrameCycle => CPU.TotalExecutedCycles - LastFrameStartCPUTick;
public virtual long CurrentFrameCycle => GateArray.FrameClock; // CPU.TotalExecutedCycles - LastFrameStartCPUTick;
/// <summary>
/// Non-Deterministic bools
@ -170,10 +170,10 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
TapeDevice.TapeCycle();
}
OverFlow = (int)CurrentFrameCycle - GateArray.FrameLength;
//OverFlow = (int)CurrentFrameCycle - GateArray.FrameLength;
// we have reached the end of a frame
LastFrameStartCPUTick = CPU.TotalExecutedCycles - OverFlow;
LastFrameStartCPUTick = CPU.TotalExecutedCycles; // - OverFlow;
if (AYDevice != null)
AYDevice.EndFrame();
@ -199,6 +199,8 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
//System.IO.File.WriteAllText(UPDDiskDevice.outputfile, UPDDiskDevice.outputString);
}
}
GateArray.FrameClock = 0;
}
#endregion
@ -334,14 +336,11 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
ser.Sync("RAM3", ref RAM3, false);
CRCT.SyncState(ser);
//KeyboardDevice.SyncState(ser);
//BuzzerDevice.SyncState(ser);
CRT.SyncState(ser);
GateArray.SyncState(ser);
KeyboardDevice.SyncState(ser);
TapeBuzzer.SyncState(ser);
AYDevice.SyncState(ser);
//.SyncState(ser);
//CPUMon.SyncState(ser);
ser.Sync("tapeMediaIndex", ref tapeMediaIndex);
if (ser.IsReader)