CPCHawk: Start of the gate array implementation

This commit is contained in:
Asnivor 2018-07-09 15:58:23 +01:00
parent aec496b561
commit 6863368dd3
7 changed files with 1221 additions and 54 deletions

View File

@ -149,6 +149,7 @@
<Compile Include="Computers\AmstradCPC\Hardware\Disk\NECUPD765.IPortIODevice.cs" /> <Compile Include="Computers\AmstradCPC\Hardware\Disk\NECUPD765.IPortIODevice.cs" />
<Compile Include="Computers\AmstradCPC\Hardware\Disk\NECUPD765.Timing.cs" /> <Compile Include="Computers\AmstradCPC\Hardware\Disk\NECUPD765.Timing.cs" />
<Compile Include="Computers\AmstradCPC\Hardware\Disk\NECUPS765.Static.cs" /> <Compile Include="Computers\AmstradCPC\Hardware\Disk\NECUPS765.Static.cs" />
<Compile Include="Computers\AmstradCPC\Hardware\GateArray\AmstradGateArray.cs" />
<Compile Include="Computers\AmstradCPC\Hardware\Input\StandardKeyboard.cs" /> <Compile Include="Computers\AmstradCPC\Hardware\Input\StandardKeyboard.cs" />
<Compile Include="Computers\AmstradCPC\Hardware\SoundOutput\AY38912.cs" /> <Compile Include="Computers\AmstradCPC\Hardware\SoundOutput\AY38912.cs" />
<Compile Include="Computers\AmstradCPC\Hardware\SoundOutput\Beeper.cs" /> <Compile Include="Computers\AmstradCPC\Hardware\SoundOutput\Beeper.cs" />
@ -164,7 +165,7 @@
<Compile Include="Computers\AmstradCPC\Machine\CPCBase.Port.cs" /> <Compile Include="Computers\AmstradCPC\Machine\CPCBase.Port.cs" />
<Compile Include="Computers\AmstradCPC\Machine\GateArrayBase.cs" /> <Compile Include="Computers\AmstradCPC\Machine\GateArrayBase.cs" />
<Compile Include="Computers\AmstradCPC\Machine\MachineType.cs" /> <Compile Include="Computers\AmstradCPC\Machine\MachineType.cs" />
<Compile Include="Computers\AmstradCPC\Machine\PPIBase.cs" /> <Compile Include="Computers\AmstradCPC\Hardware\PPI\PPI_8255.cs" />
<Compile Include="Computers\AmstradCPC\Media\Disk\CPCExtendedFloppyDisk.cs" /> <Compile Include="Computers\AmstradCPC\Media\Disk\CPCExtendedFloppyDisk.cs" />
<Compile Include="Computers\AmstradCPC\Media\Disk\CPCFloppyDisk.cs" /> <Compile Include="Computers\AmstradCPC\Media\Disk\CPCFloppyDisk.cs" />
<Compile Include="Computers\AmstradCPC\Media\Disk\DiskType.cs" /> <Compile Include="Computers\AmstradCPC\Media\Disk\DiskType.cs" />

View File

@ -24,6 +24,8 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
{ {
_machine = machine; _machine = machine;
ChipType = chipType; ChipType = chipType;
Reset();
} }
#endregion #endregion
@ -52,6 +54,114 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// </summary> /// </summary>
public short MA; public short MA;
#endregion
#region Public Lookups
/*
* These are not accessible on real hardware
* It just makes screen generation easier to have these accessbile from the gate array
*/
/// <summary>
/// The total frame width (in characters)
/// </summary>
public int FrameWidth
{
get
{
return (int)Regs[HOR_TOTAL] + 1;
}
}
/// <summary>
/// The total frame height (in scanlines)
/// </summary>
public int FrameHeight
{
get
{
return ((int)Regs[VER_TOTAL] + 1) * ((int)Regs[MAX_RASTER_ADDR] + 1);
}
}
/// <summary>
/// The width of the display area (in characters)
/// </summary>
public int DisplayWidth
{
get
{
return (int)Regs[HOR_DISPLAYED];
}
}
/// <summary>
/// The width of the display area (in scanlines)
/// </summary>
public int DisplayHeight
{
get
{
return (int)Regs[VER_DISPLAYED] * ((int)Regs[MAX_RASTER_ADDR] + 1);
}
}
/// <summary>
/// The character at which to start HSYNC
/// </summary>
public int HorizontalSyncPos
{
get
{
return (int)Regs[HOR_SYNC_POS];
}
}
/// <summary>
/// Width (in characters) of the HSYNC
/// </summary>
public int HorizontalSyncWidth
{
get
{
return HSYNCWidth;
}
}
/// <summary>
/// The vertical scanline at which to start VSYNC
/// </summary>
public int VerticalSyncPos
{
get
{
return (int)Regs[VER_SYNC_POS] * ((int)Regs[MAX_RASTER_ADDR] + 1);
}
}
/// <summary>
/// Height (in scanlines) of the VSYNC
/// </summary>
public int VerticalSyncHeight
{
get
{
return VSYNCWidth * ((int)Regs[MAX_RASTER_ADDR] + 1);
}
}
/// <summary>
/// The number of scanlines in one character
/// </summary>
public int ScanlinesPerCharacter
{
get
{
return (int)Regs[MAX_RASTER_ADDR] + 1;
}
}
#endregion #endregion
#region Internal Registers and State #region Internal Registers and State
@ -277,7 +387,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
// HSYNC in progress // HSYNC in progress
HSYNCCounter++; HSYNCCounter++;
if (HSYNCCounter == HSYNCWidth) if (HSYNCCounter >= HSYNCWidth)
{ {
// end of HSYNC // end of HSYNC
HSYNCCounter = 0; HSYNCCounter = 0;
@ -304,6 +414,14 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
// end of the current scanline // end of the current scanline
HCC = 0; HCC = 0;
if (ChipType == CRCTType.UMC_UM6845R && VLC <= Regs[MAX_RASTER_ADDR])
{
// https://web.archive.org/web/20170501112330/http://www.grimware.org/doku.php/documentations/devices/crtc
// The MA is reloaded with the value from R12 and R13 when VCC=0 and VLC=0 (that's when a new CRTC screen begin).
// However, CRTC Type 1 keep updating the MA on every new scanline while VCC=0 (and VLC=<R9).
MA = (short)(((Regs[DISP_START_ADDR_H]) & 0xff) << 8 | (Regs[DISP_START_ADDR_L]) & 0xff);
}
if (VSYNC) if (VSYNC)
{ {
// VSYNC in progress // VSYNC in progress
@ -335,6 +453,9 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
EndOfScreen = false; EndOfScreen = false;
VLC = 0; VLC = 0;
VCC = 0; VCC = 0;
// populate MA address
MA = (short)(((Regs[DISP_START_ADDR_H]) & 0xff) << 8 | (Regs[DISP_START_ADDR_L]) & 0xff);
} }
} }
else else
@ -394,6 +515,9 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
// populate initial MA address // populate initial MA address
MA = (short)(((Regs[DISP_START_ADDR_H]) & 0xff) << 8 | (Regs[DISP_START_ADDR_L]) & 0xff); MA = (short)(((Regs[DISP_START_ADDR_H]) & 0xff) << 8 | (Regs[DISP_START_ADDR_L]) & 0xff);
// updates widths
UpdateWidths();
} }
#endregion #endregion
@ -454,38 +578,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
if (SelectedRegister == HOR_AND_VER_SYNC_WIDTHS) if (SelectedRegister == HOR_AND_VER_SYNC_WIDTHS)
{ {
switch (ChipType) UpdateWidths();
{
case CRCTType.Hitachi_HD6845S:
// Bits 7..4 define Vertical Sync Width. If 0 is programmed this gives 16 lines of VSYNC. Bits 3..0 define Horizontal Sync Width.
// If 0 is programmed no HSYNC is generated.
HSYNCWidth = (Regs[HOR_AND_VER_SYNC_WIDTHS] >> 0) & 0x0F;
VSYNCWidth = (Regs[HOR_AND_VER_SYNC_WIDTHS] >> 4) & 0x0F;
break;
case CRCTType.UMC_UM6845R:
// Bits 7..4 are ignored. Vertical Sync is fixed at 16 lines. Bits 3..0 define Horizontal Sync Width. If 0 is programmed no HSYNC is generated.
HSYNCWidth = (Regs[HOR_AND_VER_SYNC_WIDTHS] >> 0) & 0x0F;
VSYNCWidth = 16;
break;
case CRCTType.Motorola_MC6845:
// Bits 7..4 are ignored. Vertical Sync is fixed at 16 lines. Bits 3..0 define Horizontal Sync Width. If 0 is programmed this gives a HSYNC width of 16.
HSYNCWidth = (Regs[HOR_AND_VER_SYNC_WIDTHS] >> 0) & 0x0F;
if (HSYNCWidth == 0)
HSYNCWidth = 16;
VSYNCWidth = 16;
break;
case CRCTType.Amstrad_AMS40489:
case CRCTType.Amstrad_40226:
// Bits 7..4 define Vertical Sync Width. If 0 is programmed this gives 16 lines of VSYNC.Bits 3..0 define Horizontal Sync Width.
// If 0 is programmed this gives a HSYNC width of 16.
HSYNCWidth = (Regs[HOR_AND_VER_SYNC_WIDTHS] >> 0) & 0x0F;
VSYNCWidth = (Regs[HOR_AND_VER_SYNC_WIDTHS] >> 4) & 0x0F;
if (HSYNCWidth == 0)
HSYNCWidth = 16;
if (VSYNCWidth == 0)
VSYNCWidth = 16;
break;
}
} }
} }
@ -593,6 +686,45 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
return addressed; return addressed;
} }
/// <summary>
/// Updates the V and H SYNC widths
/// </summary>
private void UpdateWidths()
{
switch (ChipType)
{
case CRCTType.Hitachi_HD6845S:
// Bits 7..4 define Vertical Sync Width. If 0 is programmed this gives 16 lines of VSYNC. Bits 3..0 define Horizontal Sync Width.
// If 0 is programmed no HSYNC is generated.
HSYNCWidth = (Regs[HOR_AND_VER_SYNC_WIDTHS] >> 0) & 0x0F;
VSYNCWidth = (Regs[HOR_AND_VER_SYNC_WIDTHS] >> 4) & 0x0F;
break;
case CRCTType.UMC_UM6845R:
// Bits 7..4 are ignored. Vertical Sync is fixed at 16 lines. Bits 3..0 define Horizontal Sync Width. If 0 is programmed no HSYNC is generated.
HSYNCWidth = (Regs[HOR_AND_VER_SYNC_WIDTHS] >> 0) & 0x0F;
VSYNCWidth = 16;
break;
case CRCTType.Motorola_MC6845:
// Bits 7..4 are ignored. Vertical Sync is fixed at 16 lines. Bits 3..0 define Horizontal Sync Width. If 0 is programmed this gives a HSYNC width of 16.
HSYNCWidth = (Regs[HOR_AND_VER_SYNC_WIDTHS] >> 0) & 0x0F;
if (HSYNCWidth == 0)
HSYNCWidth = 16;
VSYNCWidth = 16;
break;
case CRCTType.Amstrad_AMS40489:
case CRCTType.Amstrad_40226:
// Bits 7..4 define Vertical Sync Width. If 0 is programmed this gives 16 lines of VSYNC.Bits 3..0 define Horizontal Sync Width.
// If 0 is programmed this gives a HSYNC width of 16.
HSYNCWidth = (Regs[HOR_AND_VER_SYNC_WIDTHS] >> 0) & 0x0F;
VSYNCWidth = (Regs[HOR_AND_VER_SYNC_WIDTHS] >> 4) & 0x0F;
if (HSYNCWidth == 0)
HSYNCWidth = 16;
if (VSYNCWidth == 0)
VSYNCWidth = 16;
break;
}
}
#endregion #endregion
#region PortIODevice #region PortIODevice

View File

@ -10,13 +10,13 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// http://www.cpcwiki.eu/imgs/d/df/PPI_M5L8255AP-5.pdf /// http://www.cpcwiki.eu/imgs/d/df/PPI_M5L8255AP-5.pdf
/// http://www.cpcwiki.eu/index.php/8255 /// http://www.cpcwiki.eu/index.php/8255
/// </summary> /// </summary>
public class PPIBase : IPortIODevice public class PPI_8255 : IPortIODevice
{ {
#region Devices #region Devices
private CPCBase _machine; private CPCBase _machine;
private CRCT_6845 CRTC => _machine.CRCT; private CRCT_6845 CRTC => _machine.CRCT;
private GateArrayBase GateArray => _machine.GateArray; private AmstradGateArray GateArray => _machine.GateArray;
private IPSG PSG => _machine.AYDevice; private IPSG PSG => _machine.AYDevice;
private DatacorderDevice Tape => _machine.TapeDevice; private DatacorderDevice Tape => _machine.TapeDevice;
private IKeyboard Keyboard => _machine.KeyboardDevice; private IKeyboard Keyboard => _machine.KeyboardDevice;
@ -63,7 +63,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
#region Construction #region Construction
public PPIBase(CPCBase machine) public PPI_8255(CPCBase machine)
{ {
_machine = machine; _machine = machine;
Reset(); Reset();

View File

@ -130,6 +130,9 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
if (RomData.RomBytes.Length > 0x4000) if (RomData.RomBytes.Length > 0x4000)
ROM1[i] = RomData.RomBytes[i + 0x4000]; ROM1[i] = RomData.RomBytes[i + 0x4000];
} }
LowerROMPaged = true;
UpperROMPaged = true;
} }
} }
} }

View File

@ -24,8 +24,8 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
FrameLength = 79872; FrameLength = 79872;
CRCT = new CRCT_6845(CRCT_6845.CRCTType.Motorola_MC6845, this); CRCT = new CRCT_6845(CRCT_6845.CRCTType.Motorola_MC6845, this);
GateArray = new GateArray_CPC464(this); GateArray = new AmstradGateArray(this, AmstradGateArray.GateArrayType.Amstrad40007);
PPI = new PPIBase(this); PPI = new PPI_8255(this);
KeyboardDevice = new StandardKeyboard(this); KeyboardDevice = new StandardKeyboard(this);

View File

@ -60,12 +60,12 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// <summary> /// <summary>
/// The Amstrad gate array /// The Amstrad gate array
/// </summary> /// </summary>
public GateArrayBase GateArray { get; set; } public AmstradGateArray GateArray { get; set; }
/// <summary> /// <summary>
/// The PPI contoller chip /// The PPI contoller chip
/// </summary> /// </summary>
public PPIBase PPI { get; set; } public PPI_8255 PPI { get; set; }
/// <summary> /// <summary>
/// The length of a standard frame in CPU cycles /// The length of a standard frame in CPU cycles
@ -154,20 +154,11 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
PollInput(); PollInput();
for (;;) GateArray.SetupVideo();
while (!GateArray.FrameEnd)
{ {
// run the CPU Monitor cycle GateArray.DoCycles();
//CPUMon.ExecuteCycle();
GateArray.ClockCycle();
// cycle the tape device
if (UPDDiskDevice == null || !UPDDiskDevice.FDD_IsDiskLoaded)
TapeDevice.TapeCycle();
// has frame end been reached?
if (GateArray.FrameEnd)
break;
} }
OverFlow = (int)CurrentFrameCycle - GateArray.FrameLength; OverFlow = (int)CurrentFrameCycle - GateArray.FrameLength;