[CPCHawk] New CRTC1 impl.

This commit is contained in:
Asnivor 2024-10-11 16:00:55 +01:00
parent aac3da9e0d
commit 95cf257d96
9 changed files with 328 additions and 714 deletions

View File

@ -15,12 +15,13 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// </summary>
public override int CrtcType => 0;
/// <summary>
/// CRTC is clocked at 1MHz (16 GA cycles)
/// </summary>
public override void Clock() => throw new InvalidOperationException("CRTC Type 0 not implemented yet");
/*
public override void Clock()
{
base.Clock();
CheckReset();
int maxScanLine;
@ -130,7 +131,6 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
hhclock = true;
}
/* Hor active video */
if (HCC == 0)
{
// active display
@ -143,7 +143,6 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
latch_hdisp = false;
}
/* Hor sync */
if (hssstart || // start of horizontal sync
HSYNC) // already in horizontal sync
{
@ -163,7 +162,6 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
HSYNC = false;
}
/* Ver active video */
if (VCC == 0)
{
// active display
@ -203,7 +201,6 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
}
/* Address Generation */
int line = VLC;
if (R8_Interlace == 3)
@ -222,7 +219,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
_RA = VLC;
}
_LA = _vma;
ma = _vma;
// DISPTMG Generation
if (!latch_hdisp || !latch_vdisp)
@ -238,7 +235,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
DISPTMG = true;
}
}
*/
/// <summary>
/// R3l: CRTC-type horizontal sync width independent helper function

View File

@ -14,13 +14,277 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// </summary>
public override int CrtcType => 1;
private int cnt;
/// <summary>
/// CRTC is clocked at 1MHz (16 GA cycles)
/// </summary>
public override void Clock()
{
CheckReset();
cnt++;
// linear address generator clocked
ma = (ma + 1) & 0x3FFF;
// horizontal character counter clocked
HCC++;
if (HCC == R0_HorizontalTotal + 1) // C0 == R0
{
// new scanline
// increment raster counter
VLC++;
if (VLC == R9_MaxScanline + 1) // C9 == R9
{
// new character row
// vertical character counter reset
VLC = 0;
// incremement vertical character counter
VCC++;
if (VCC == R6_VerticalDisplayed) // C4 == R6
{
// vertical display is disabled
latch_vdisp = false;
}
if (VCC == R4_VerticalTotal + 1) // C4 == R4
{
// new CRTC frame
// vertical character counter reset
VCC = 0;
// vertical display enabled
latch_vdisp = true;
// cached VMA loaded with register start address
ma_store = (Register[R12_START_ADDR_H] << 8) | Register[R13_START_ADDR_L];
}
if (VCC == R7_VerticalSyncPosition) // C4 == R7
{
// VSYNC enabled
VSYNC = true;
// reset vertical sync counter
VSC = 0;
}
ma_row_start = ma_store;
}
if (VSYNC)
{
// increment vertical sync counter
VSC++;
if (VSC == R3_VerticalSyncWidth // C3h == R3h
|| VSC == 0) // VSC counter wrap-around
{
// VSYNC disabled
VSYNC = false;
cnt = 0;
}
}
// H display is enabled
latch_hdisp = true;
// horizontal character counter reset
HCC = 0;
// VMA updated with row start address
ma = ma_row_start;
}
if (HCC == R1_HorizontalDisplayed) // CO == R1
{
// H display is disabled
latch_hdisp = false;
// current VMA is copied into memory
ma_store = ma;
}
if (HCC == R2_HorizontalSyncPosition) // C0 == R2
{
// HSYNC is enabled
HSYNC = true;
// reset horizontal sync counter
HSC = 0;
}
if (HSYNC)
{
// HSYNC still enabled - increment counter
HSC++;
if (HSC == R3_HorizontalSyncWidth // C3l == R3l
|| HSC == 0) // HSC counter wrap-around
{
// disable HSYNC
HSYNC = false;
}
}
// outputs
if (!latch_hdisp || !latch_vdisp)
{
// HSYNC output pin is fed through a NOR gate with either 2 or 3 inputs
// - H Display
// - V Display
DISPTMG = false;
}
else
{
DISPTMG = true;
}
}
public void Clock2()
{
base.Clock();
ma = (ma + 1) & 0x3FFF;
HCC++;
// C0 == R0
if (HCC == R0_HorizontalTotal + 1)
{
// new scanline
HCC = 0;
// C9 == R9
if (++VLC == R9_MaxScanline + 1 || latch_vadjust)
{
VLC = 0;
// C4 == R4
if (++VCC == R4_VerticalTotal + 1)
{
latch_vadjust = true;
_vmaRowStart = (Register[R12_START_ADDR_H] << 8) | Register[R13_START_ADDR_L];
// C5 == R5
if (VTAC == R5_VerticalTotalAdjust)
{
latch_vadjust = false;
VCC = 0;
VTAC = 0;
}
else
{
VTAC++;
}
}
else
{
// MA set to row start at the beginning of each line
_vmaRowStart += R1_HorizontalDisplayed;
}
// C4 == 0
if (VCC == 0)
{
latch_vdisp = true;
}
if (VCC == R6_VerticalDisplayed)
{
latch_vdisp = false;
}
}
if (!latch_vadjust)
{
// C4 == R7
if (VCC == R7_VerticalSyncPosition && VLC == 0)
{
VSYNC = true;
VSC = 0;
}
if (VSYNC)
{
VSC++;
// C3h == R3h
if (VSC == R3_VerticalSyncWidth || VSC == 0)
{
VSYNC = false;
}
}
}
}
if (HCC == 0)
{
ma = _vmaRowStart;
}
// C0 == R2
if (HCC == R2_HorizontalSyncPosition)
{
HSYNC = true;
HSC = 0;
}
if (HSYNC)
{
if (R3_HorizontalSyncWidth > 0)
{
HSC++;
}
// C3l == R3l
if (HSC == R3_HorizontalSyncWidth)
{
HSYNC = false;
}
}
int dSkew = R8_Skew_CUDISP > 2 ? -1 : R8_Skew_CUDISP;
// C0 == 0
if (dSkew >= 0 && HCC == dSkew)
{
latch_hdisp = true;
}
// C0 == R1
if (dSkew >= 0 && HCC == R1_HorizontalDisplayed + dSkew)
{
latch_hdisp = false;
}
// outputs
if (!latch_hdisp || !latch_vdisp)
{
// HSYNC output pin is fed through a NOR gate with either 2 or 3 inputs
// - H Display
// - V Display
DISPTMG = false;
}
else
{
DISPTMG = true;
}
}
public void Clocko()
{
CheckReset();
int maxScanLine;
if (HCC == R0_HorizontalTotal)
@ -227,7 +491,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
_RA = VLC;
}
_LA = _vma;
ma = _vma;
// DISPTMG Generation
if (!latch_hdisp || !latch_vdisp)

View File

@ -1,5 +1,4 @@
using BizHawk.Common.NumberExtensions;

namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
{
/// <summary>
@ -16,231 +15,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// </summary>
public override int CrtcType => 2;
/// <summary>
/// CRTC is clocked at 1MHz (16 GA cycles)
/// </summary>
public override void Clock()
{
base.Clock();
int maxScanLine;
if (HCC == R0_HorizontalTotal)
{
// end of displayable area reached
// set up for the next line
HCC = 0;
// TODO: handle interlace setup
if (R8_Interlace == 3)
{
// in interlace sync and video mask off bit 0 of the max scanline address
maxScanLine = R9_MaxScanline & 0b11110;
}
else
{
maxScanLine = R9_MaxScanline;
}
if (VLC == maxScanLine)
{
// we have reached the final scanline within this vertical character row
// move to next character
VLC = 0;
// TODO: implement vertical adjust
if (VCC == R4_VerticalTotal)
{
// check the interlace mode
if (R8_Interlace.Bit(0))
{
// toggle the field
_field = !_field;
}
else
{
// stay on the even field
_field = false;
}
// we have reached the end of the vertical display area
// address loaded from start address register at the top of each field
_vmaRowStart = (Register[R12_START_ADDR_H] << 8) | Register[R13_START_ADDR_L];
// reset the vertical character counter
VCC = 0;
// increment field counter
CFC++;
}
else
{
// row start address is increased by Horiztonal Displayed
_vmaRowStart += R1_HorizontalDisplayed;
// increment vertical character counter
VCC++;
}
}
else
{
// next scanline
if (R8_Interlace == 3)
{
// interlace sync+video mode
// vertical line counter increments by 2
VLC += 2;
// ensure vertical line counter is an even value
VLC &= ~1;
}
else
{
// non-interlace mode
// increment vertical line counter
VLC++;
}
}
// MA set to row start at the beginning of each line
_vma = _vmaRowStart;
}
else
{
// next horizontal character (1us)
// increment horizontal character counter
HCC++;
// increment VMA
_vma++;
}
hssstart = false;
hhclock = false;
if (HCC == R2_HorizontalSyncPosition)
{
// start of horizontal sync
hssstart = true;
}
if (HCC == R2_HorizontalSyncPosition / 2)
{
// we are half way through the line
hhclock = true;
}
/* Hor active video */
if (HCC == 0)
{
// active display
latch_hdisp = true;
}
if (HCC == R1_HorizontalDisplayed)
{
// inactive display
latch_hdisp = false;
}
/* Hor sync */
if (hssstart || // start of horizontal sync
HSYNC) // already in horizontal sync
{
// start of horizontal sync
HSYNC = true;
HSC++;
}
else
{
// reset hsync counter
HSC = 0;
}
if (HSC == R3_HorizontalSyncWidth)
{
// end of horizontal sync
HSYNC = false;
}
/* Ver active video */
if (VCC == 0)
{
// active display
latch_vdisp = true;
}
if (VCC == R6_VerticalDisplayed)
{
// inactive display
latch_vdisp = false;
}
// vertical sync occurs at different times depending on the interlace field
// even field: the same time as HSYNC
// odd field: half a line later than HSYNC
if ((!_field && hssstart) || (_field && hhclock))
{
if ((VCC == R7_VerticalSyncPosition && VLC == 0) // vsync starts on the first line
|| VSYNC) // vsync is already in progress
{
// start of vertical sync
VSYNC = true;
// increment vertical sync counter
VSC++;
}
else
{
// reset vsync counter
VSC = 0;
}
if (VSYNC && VSC == R3_VerticalSyncWidth - 1)
{
// end of vertical sync
VSYNC = false;
}
}
/* Address Generation */
int line = VLC;
if (R8_Interlace == 3)
{
// interlace sync+video mode
// the least significant bit is based on the current field number
int fNum = _field ? 1 : 0;
int lNum = VLC.Bit(0) ? 1 : 0;
line &= ~1;
_RA = line & (fNum | lNum);
}
else
{
// raster address is just the VLC
_RA = VLC;
}
_LA = _vma;
// DISPTMG Generation
if (!latch_hdisp || !latch_vdisp)
{
// HSYNC output pin is fed through a NOR gate with either 2 or 3 inputs
// - H Display
// - V Display
// - TODO: R8 DISPTMG Skew (only on certain CRTC types)
DISPTMG = false;
}
else
{
DISPTMG = true;
}
}
public override void Clock() => throw new InvalidOperationException("CRTC Type 2 not implemented yet");
/// <summary>
/// R3l: CRTC-type horizontal sync width independent helper function

View File

@ -1,5 +1,4 @@
using BizHawk.Common.NumberExtensions;

namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
{
/// <summary>
@ -14,231 +13,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// </summary>
public override int CrtcType => 3;
/// <summary>
/// CRTC is clocked at 1MHz (16 GA cycles)
/// </summary>
public override void Clock()
{
base.Clock();
int maxScanLine;
if (HCC == R0_HorizontalTotal)
{
// end of displayable area reached
// set up for the next line
HCC = 0;
// TODO: handle interlace setup
if (R8_Interlace == 3)
{
// in interlace sync and video mask off bit 0 of the max scanline address
maxScanLine = R9_MaxScanline & 0b11110;
}
else
{
maxScanLine = R9_MaxScanline;
}
if (VLC == maxScanLine)
{
// we have reached the final scanline within this vertical character row
// move to next character
VLC = 0;
// TODO: implement vertical adjust
if (VCC == R4_VerticalTotal)
{
// check the interlace mode
if (R8_Interlace.Bit(0))
{
// toggle the field
_field = !_field;
}
else
{
// stay on the even field
_field = false;
}
// we have reached the end of the vertical display area
// address loaded from start address register at the top of each field
_vmaRowStart = (Register[R12_START_ADDR_H] << 8) | Register[R13_START_ADDR_L];
// reset the vertical character counter
VCC = 0;
// increment field counter
CFC++;
}
else
{
// row start address is increased by Horiztonal Displayed
_vmaRowStart += R1_HorizontalDisplayed;
// increment vertical character counter
VCC++;
}
}
else
{
// next scanline
if (R8_Interlace == 3)
{
// interlace sync+video mode
// vertical line counter increments by 2
VLC += 2;
// ensure vertical line counter is an even value
VLC &= ~1;
}
else
{
// non-interlace mode
// increment vertical line counter
VLC++;
}
}
// MA set to row start at the beginning of each line
_vma = _vmaRowStart;
}
else
{
// next horizontal character (1us)
// increment horizontal character counter
HCC++;
// increment VMA
_vma++;
}
hssstart = false;
hhclock = false;
if (HCC == R2_HorizontalSyncPosition)
{
// start of horizontal sync
hssstart = true;
}
if (HCC == R2_HorizontalSyncPosition / 2)
{
// we are half way through the line
hhclock = true;
}
/* Hor active video */
if (HCC == 0)
{
// active display
latch_hdisp = true;
}
if (HCC == R1_HorizontalDisplayed)
{
// inactive display
latch_hdisp = false;
}
/* Hor sync */
if (hssstart || // start of horizontal sync
HSYNC) // already in horizontal sync
{
// start of horizontal sync
HSYNC = true;
HSC++;
}
else
{
// reset hsync counter
HSC = 0;
}
if (HSC == R3_HorizontalSyncWidth)
{
// end of horizontal sync
HSYNC = false;
}
/* Ver active video */
if (VCC == 0)
{
// active display
latch_vdisp = true;
}
if (VCC == R6_VerticalDisplayed)
{
// inactive display
latch_vdisp = false;
}
// vertical sync occurs at different times depending on the interlace field
// even field: the same time as HSYNC
// odd field: half a line later than HSYNC
if ((!_field && hssstart) || (_field && hhclock))
{
if ((VCC == R7_VerticalSyncPosition && VLC == 0) // vsync starts on the first line
|| VSYNC) // vsync is already in progress
{
// start of vertical sync
VSYNC = true;
// increment vertical sync counter
VSC++;
}
else
{
// reset vsync counter
VSC = 0;
}
if (VSYNC && VSC == R3_VerticalSyncWidth - 1)
{
// end of vertical sync
VSYNC = false;
}
}
/* Address Generation */
int line = VLC;
if (R8_Interlace == 3)
{
// interlace sync+video mode
// the least significant bit is based on the current field number
int fNum = _field ? 1 : 0;
int lNum = VLC.Bit(0) ? 1 : 0;
line &= ~1;
_RA = line & (fNum | lNum);
}
else
{
// raster address is just the VLC
_RA = VLC;
}
_LA = _vma;
// DISPTMG Generation
if (!latch_hdisp || !latch_vdisp)
{
// HSYNC output pin is fed through a NOR gate with either 2 or 3 inputs
// - H Display
// - V Display
// - TODO: R8 DISPTMG Skew (only on certain CRTC types)
DISPTMG = false;
}
else
{
DISPTMG = true;
}
}
public override void Clock() => throw new InvalidOperationException("CRTC Type 3 not implemented yet");
/// <summary>
/// R3l: CRTC-type horizontal sync width independent helper function

View File

@ -1,5 +1,4 @@
using BizHawk.Common.NumberExtensions;

namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
{
/// <summary>
@ -15,231 +14,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// </summary>
public override int CrtcType => 4;
/// <summary>
/// CRTC is clocked at 1MHz (16 GA cycles)
/// </summary>
public override void Clock()
{
base.Clock();
int maxScanLine;
if (HCC == R0_HorizontalTotal)
{
// end of displayable area reached
// set up for the next line
HCC = 0;
// TODO: handle interlace setup
if (R8_Interlace == 3)
{
// in interlace sync and video mask off bit 0 of the max scanline address
maxScanLine = R9_MaxScanline & 0b11110;
}
else
{
maxScanLine = R9_MaxScanline;
}
if (VLC == maxScanLine)
{
// we have reached the final scanline within this vertical character row
// move to next character
VLC = 0;
// TODO: implement vertical adjust
if (VCC == R4_VerticalTotal)
{
// check the interlace mode
if (R8_Interlace.Bit(0))
{
// toggle the field
_field = !_field;
}
else
{
// stay on the even field
_field = false;
}
// we have reached the end of the vertical display area
// address loaded from start address register at the top of each field
_vmaRowStart = (Register[R12_START_ADDR_H] << 8) | Register[R13_START_ADDR_L];
// reset the vertical character counter
VCC = 0;
// increment field counter
CFC++;
}
else
{
// row start address is increased by Horiztonal Displayed
_vmaRowStart += R1_HorizontalDisplayed;
// increment vertical character counter
VCC++;
}
}
else
{
// next scanline
if (R8_Interlace == 3)
{
// interlace sync+video mode
// vertical line counter increments by 2
VLC += 2;
// ensure vertical line counter is an even value
VLC &= ~1;
}
else
{
// non-interlace mode
// increment vertical line counter
VLC++;
}
}
// MA set to row start at the beginning of each line
_vma = _vmaRowStart;
}
else
{
// next horizontal character (1us)
// increment horizontal character counter
HCC++;
// increment VMA
_vma++;
}
hssstart = false;
hhclock = false;
if (HCC == R2_HorizontalSyncPosition)
{
// start of horizontal sync
hssstart = true;
}
if (HCC == R2_HorizontalSyncPosition / 2)
{
// we are half way through the line
hhclock = true;
}
/* Hor active video */
if (HCC == 0)
{
// active display
latch_hdisp = true;
}
if (HCC == R1_HorizontalDisplayed)
{
// inactive display
latch_hdisp = false;
}
/* Hor sync */
if (hssstart || // start of horizontal sync
HSYNC) // already in horizontal sync
{
// start of horizontal sync
HSYNC = true;
HSC++;
}
else
{
// reset hsync counter
HSC = 0;
}
if (HSC == R3_HorizontalSyncWidth)
{
// end of horizontal sync
HSYNC = false;
}
/* Ver active video */
if (VCC == 0)
{
// active display
latch_vdisp = true;
}
if (VCC == R6_VerticalDisplayed)
{
// inactive display
latch_vdisp = false;
}
// vertical sync occurs at different times depending on the interlace field
// even field: the same time as HSYNC
// odd field: half a line later than HSYNC
if ((!_field && hssstart) || (_field && hhclock))
{
if ((VCC == R7_VerticalSyncPosition && VLC == 0) // vsync starts on the first line
|| VSYNC) // vsync is already in progress
{
// start of vertical sync
VSYNC = true;
// increment vertical sync counter
VSC++;
}
else
{
// reset vsync counter
VSC = 0;
}
if (VSYNC && VSC == R3_VerticalSyncWidth - 1)
{
// end of vertical sync
VSYNC = false;
}
}
/* Address Generation */
int line = VLC;
if (R8_Interlace == 3)
{
// interlace sync+video mode
// the least significant bit is based on the current field number
int fNum = _field ? 1 : 0;
int lNum = VLC.Bit(0) ? 1 : 0;
line &= ~1;
_RA = line & (fNum | lNum);
}
else
{
// raster address is just the VLC
_RA = VLC;
}
_LA = _vma;
// DISPTMG Generation
if (!latch_hdisp || !latch_vdisp)
{
// HSYNC output pin is fed through a NOR gate with either 2 or 3 inputs
// - H Display
// - V Display
// - TODO: R8 DISPTMG Skew (only on certain CRTC types)
DISPTMG = false;
}
else
{
DISPTMG = true;
}
}
public override void Clock() => throw new InvalidOperationException("CRTC Type 4 not implemented yet");
/// <summary>
/// R3l: CRTC-type horizontal sync width independent helper function

View File

@ -137,7 +137,17 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// Character pos address (0 index).
/// Feeds the MA lines
/// </summary>
protected int _LA;
protected int ma;
/// <summary>
/// Memory address reset latch
/// </summary>
protected int ma_row_start;
/// <summary>
/// Internal latch for storing intermediate MA values
/// </summary>
protected int ma_store;
/// <summary>
/// Generated by the Vertical Control Raster Counter
@ -173,21 +183,21 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
{
var MA = new BitArray(16);
MA[0] = CLK;
MA[1] = _LA.Bit(0);
MA[2] = _LA.Bit(1);
MA[3] = _LA.Bit(2);
MA[4] = _LA.Bit(3);
MA[5] = _LA.Bit(4);
MA[6] = _LA.Bit(5);
MA[7] = _LA.Bit(6);
MA[8] = _LA.Bit(7);
MA[9] = _LA.Bit(8);
MA[10] = _LA.Bit(9);
MA[11] = _RA.Bit(0);
MA[12] = _RA.Bit(1);
MA[13] = _RA.Bit(2);
MA[14] = _LA.Bit(12);
MA[15] = _LA.Bit(13);
MA[1] = ma.Bit(0);
MA[2] = ma.Bit(1);
MA[3] = ma.Bit(2);
MA[4] = ma.Bit(3);
MA[5] = ma.Bit(4);
MA[6] = ma.Bit(5);
MA[7] = ma.Bit(6);
MA[8] = ma.Bit(7);
MA[9] = ma.Bit(8);
MA[10] = ma.Bit(9);
MA[11] = VLC.Bit(0);
MA[12] = VLC.Bit(1);
MA[13] = VLC.Bit(2);
MA[14] = ma.Bit(12);
MA[15] = ma.Bit(13);
int[] array = new int[1];
MA.CopyTo(array, 0);
return (ushort)array[0];
@ -616,7 +626,10 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// <summary>
/// CRTC is clocked at 1MHz (16 GA cycles)
/// </summary>
public virtual void Clock()
public virtual void Clock() { }
public virtual void CheckReset()
{
if (_inReset > 0)
{
@ -633,7 +646,9 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
_field = false;
_vmaRowStart = 0;
_vma = 0;
_LA = 0;
ma = 0;
ma_row_start = 0;
ma_store = 0;
_RA = 0;
latch_hdisp = false;
latch_vdisp = false;
@ -755,7 +770,9 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
ser.Sync(nameof(_HSYNC), ref _HSYNC);
ser.Sync(nameof(_DISPTMG), ref _DISPTMG);
ser.Sync(nameof(_CUDISP), ref _CUDISP);
ser.Sync(nameof(_LA), ref _LA);
ser.Sync(nameof(ma), ref ma);
ser.Sync(nameof(ma_row_start), ref ma_row_start);
ser.Sync(nameof(ma_store), ref ma_store);
ser.Sync(nameof(_RA), ref _RA);
ser.Sync(nameof(_addressRegister), ref _addressRegister);
ser.Sync(nameof(Register), ref Register, false);

View File

@ -51,6 +51,9 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
}
private int _GAClockCounter;
public double CRTCClockCounter => (double)GAClockCounter / 16;
public double CPUClockClounter => (double)GAClockCounter / 4;
/// <summary>
/// Previous frame clock count. Latched at the end of the frame (VSYNC off)
@ -514,6 +517,9 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
}
}
private int GAClockCounterOriginVSYNC;
private double GACunlockCounterOriginVSYNCCRTC => (double)GAClockCounterOriginVSYNC / 16;
/// <summary>
/// Fired when CRTC VSYNC active signal is detected
/// </summary>
@ -525,6 +531,10 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
GA_VSYNC = true;
// black colour enabled for vsync
C_VSYNC_Black = true;
// signal start of new frame
GAClockCounterOriginVSYNC = 0;
FrameEnd = true;
}
/// <summary>
@ -609,6 +619,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
// We will do this for now to get the accuracy right, but will probably need to optimise this down the line
//OutputPixel(0);
GAClockCounter++;
GAClockCounterOriginVSYNC++;
// Based on timing oscilloscope traces from

View File

@ -16,7 +16,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
CPC = cpc;
CPU = cpu;
CRTC = CRTC.Create(0);
CRTC = CRTC.Create(1);
GateArray = new GateArray(this, GateArrayType.Amstrad40010);
CRTScreen = new CRTScreen(ScreenType.CTM064x, borderType);

View File

@ -148,7 +148,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
GateArray.GAClockCounter = 0;
GateArray.FrameEnd = false;
while (!CRTScreen.FrameEnd)
while (!GateArray.FrameEnd)
{
GateArray.Clock();
@ -157,7 +157,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
TapeDevice.TapeCycle();
}
CRTScreen.FrameEnd = false;
GateArray.FrameEnd = false;
var ipf = GateArray.interruptsPerFrame;
GateArray.interruptsPerFrame = 0;