CPCHawk: Datacorder & tape sound, GateArray renderer modes 0, 1 & 2
This commit is contained in:
parent
c0fcac5ab1
commit
f35bb99c5f
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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))
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue