Implement cycle-based timing for VGA.


svn path=/trunk/; revision=68095
This commit is contained in:
Aleksandar Andrejevic 2015-06-09 19:22:52 +00:00
parent d4365a1beb
commit f3c5b91037
4 changed files with 58 additions and 30 deletions

View file

@ -36,26 +36,28 @@
/* VARIABLES ******************************************************************/
static LIST_ENTRY Timers;
static ULONGLONG Cycles = 0ULL;
static ULONGLONG CurrentIps = 20000000ULL; // 20 MIPS is a good estimate
static LARGE_INTEGER StartPerfCount, Frequency;
// static ULONG StartTickCount;
static LARGE_INTEGER Counter;
static ULONG CurrentTickCount;
#ifdef IPS_DISPLAY
static ULONGLONG LastCycles = 0ULL;
static PHARDWARE_TIMER IpsTimer;
static ULONGLONG Cycles = 0ULL;
#endif
/* PRIVATE FUNCTIONS **********************************************************/
#ifdef IPS_DISPLAY
static VOID FASTCALL IpsDisplayCallback(ULONGLONG ElapsedTime)
static VOID FASTCALL IpsCallback(ULONGLONG ElapsedTime)
{
DPRINT1("NTVDM: %I64u Instructions Per Second\n", Cycles / ElapsedTime);
Cycles = 0ULL;
}
CurrentIps = (Cycles - LastCycles) / ElapsedTime;
#ifdef IPS_DISPLAY
DPRINT1("NTVDM: %I64u Instructions Per Second\n", CurrentIps);
#endif
LastCycles = Cycles;
}
/* PUBLIC FUNCTIONS ***********************************************************/
VOID ClockUpdate(VOID)
@ -76,10 +78,7 @@ VOID ClockUpdate(VOID)
for (i = 0; VdmRunning && CpuRunning && (i < STEPS_PER_CYCLE); i++)
{
CpuStep();
#ifdef IPS_DISPLAY
++Cycles;
#endif
}
for (Entry = Timers.Flink; Entry != &Timers; Entry = Entry->Flink)
@ -199,6 +198,16 @@ VOID DestroyHardwareTimer(PHARDWARE_TIMER Timer)
}
}
ULONGLONG GetCycleCount(VOID)
{
return Cycles;
}
ULONGLONG GetCycleSpeed(VOID)
{
return CurrentIps;
}
BOOLEAN ClockInitialize(VOID)
{
InitializeListHead(&Timers);
@ -215,16 +224,12 @@ BOOLEAN ClockInitialize(VOID)
/* Find the starting tick count */
// StartTickCount = GetTickCount();
#ifdef IPS_DISPLAY
IpsTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED, HZ_TO_NS(1), IpsDisplayCallback);
IpsTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED, HZ_TO_NS(1), IpsCallback);
if (IpsTimer == NULL)
{
wprintf(L"FATAL: Cannot create IPS display timer.\n");
wprintf(L"FATAL: Cannot create IPS timer.\n");
return FALSE;
}
#endif
return TRUE;
}

View file

@ -44,6 +44,9 @@ VOID DisableHardwareTimer(PHARDWARE_TIMER Timer);
VOID SetHardwareTimerDelay(PHARDWARE_TIMER Timer, ULONGLONG NewDelay);
VOID DestroyHardwareTimer(PHARDWARE_TIMER Timer);
ULONGLONG GetCycleCount(VOID);
ULONGLONG GetCycleSpeed(VOID);
VOID ClockUpdate(VOID);
BOOLEAN ClockInitialize(VOID);

View file

@ -282,8 +282,8 @@ static BYTE VgaDacRegisters[VGA_PALETTE_SIZE];
// static VGA_REGISTERS VgaRegisters;
static BOOLEAN InVerticalRetrace = FALSE;
static BOOLEAN InHorizontalRetrace = FALSE;
static ULONGLONG VerticalRetraceCycle = 0ULL;
static ULONGLONG HorizontalRetraceCycle = 0ULL;
static BOOLEAN NeedsUpdate = FALSE;
static BOOLEAN ModeChanged = FALSE;
@ -1413,8 +1413,31 @@ static BYTE WINAPI VgaReadPort(USHORT Port)
case VGA_INSTAT1_READ_COLOR:
{
BYTE Result = 0;
BOOLEAN Vsync = InVerticalRetrace;
BOOLEAN Hsync = InHorizontalRetrace;
BOOLEAN Vsync, Hsync;
ULONGLONG Cycles = GetCycleCount();
ULONG CyclesPerMicrosecond = (ULONG)((GetCycleSpeed() + 500000ULL) / 1000000ULL);
ULONG Dots = (VgaSeqRegisters[VGA_SEQ_CLOCK_REG] & 1) ? 9 : 8;
ULONG Clock = ((VgaMiscRegister >> 2) & 1) ? 28 : 25;
ULONG HorizTotalDots = ((ULONG)VgaCrtcRegisters[VGA_CRTC_HORZ_TOTAL_REG] + 5) * Dots;
ULONG VblankStart, VblankEnd, HblankStart, HblankEnd;
ULONG HblankDuration, VblankDuration;
/* Calculate the vertical blanking duration in cycles */
VblankStart = VgaCrtcRegisters[VGA_CRTC_START_VERT_BLANKING_REG] & 0x7F;
VblankEnd = VgaCrtcRegisters[VGA_CRTC_END_VERT_BLANKING_REG] & 0x7F;
if (VblankEnd < VblankStart) VblankEnd |= 0x80;
VblankDuration = ((VblankEnd - VblankStart) * HorizTotalDots
* CyclesPerMicrosecond + (Clock >> 1)) / Clock;
/* Calculate the horizontal blanking duration in cycles */
HblankStart = VgaCrtcRegisters[VGA_CRTC_START_HORZ_BLANKING_REG] & 0x1F;
HblankEnd = VgaCrtcRegisters[VGA_CRTC_END_HORZ_BLANKING_REG] & 0x1F;
if (HblankEnd < HblankStart) HblankEnd |= 0x20;
HblankDuration = ((HblankEnd - HblankStart) * Dots
* CyclesPerMicrosecond + (Clock >> 1)) / Clock;
Vsync = (Cycles - VerticalRetraceCycle) < (ULONGLONG)VblankDuration;
Hsync = (Cycles - HorizontalRetraceCycle) < (ULONGLONG)HblankDuration;
/* Reset the AC latch */
VgaAcLatch = FALSE;
@ -1429,9 +1452,6 @@ static BYTE WINAPI VgaReadPort(USHORT Port)
/* Set an additional flag if there was a vertical retrace */
if (Vsync) Result |= VGA_STAT_VRETRACE;
/* Clear the flags */
InHorizontalRetrace = InVerticalRetrace = FALSE;
return Result;
}
@ -1787,8 +1807,8 @@ static VOID FASTCALL VgaVerticalRetrace(ULONGLONG ElapsedTime)
UNREFERENCED_PARAMETER(ElapsedTime);
/* Set the vertical retrace flag */
InVerticalRetrace = TRUE;
/* Set the vertical retrace cycle */
VerticalRetraceCycle = GetCycleCount();
/* If nothing has changed, just return */
// if (!ModeChanged && !CursorChanged && !PaletteChanged && !NeedsUpdate)
@ -1859,8 +1879,8 @@ static VOID FASTCALL VgaHorizontalRetrace(ULONGLONG ElapsedTime)
{
UNREFERENCED_PARAMETER(ElapsedTime);
/* Set the flag */
InHorizontalRetrace = TRUE;
/* Set the cycle */
HorizontalRetraceCycle = GetCycleCount();
}
/* PUBLIC FUNCTIONS ***********************************************************/

View file

@ -161,7 +161,7 @@ enum
VGA_CRTC_OFFSET_REG,
VGA_CRTC_UNDERLINE_REG,
VGA_CRTC_START_VERT_BLANKING_REG,
VGA_CRTC_END_VERT_BLANKING,
VGA_CRTC_END_VERT_BLANKING_REG,
VGA_CRTC_MODE_CONTROL_REG,
VGA_CRTC_LINE_COMPARE_REG,
VGA_CRTC_MAX_REG