mirror of
https://github.com/reactos/reactos.git
synced 2025-07-04 13:41:24 +00:00
[NTVDM]
Implement cycle-based timing for VGA. svn path=/trunk/; revision=68095
This commit is contained in:
parent
d4365a1beb
commit
f3c5b91037
4 changed files with 58 additions and 30 deletions
|
@ -36,26 +36,28 @@
|
||||||
/* VARIABLES ******************************************************************/
|
/* VARIABLES ******************************************************************/
|
||||||
|
|
||||||
static LIST_ENTRY Timers;
|
static LIST_ENTRY Timers;
|
||||||
|
static ULONGLONG Cycles = 0ULL;
|
||||||
|
static ULONGLONG CurrentIps = 20000000ULL; // 20 MIPS is a good estimate
|
||||||
static LARGE_INTEGER StartPerfCount, Frequency;
|
static LARGE_INTEGER StartPerfCount, Frequency;
|
||||||
// static ULONG StartTickCount;
|
// static ULONG StartTickCount;
|
||||||
static LARGE_INTEGER Counter;
|
static LARGE_INTEGER Counter;
|
||||||
static ULONG CurrentTickCount;
|
static ULONG CurrentTickCount;
|
||||||
|
static ULONGLONG LastCycles = 0ULL;
|
||||||
#ifdef IPS_DISPLAY
|
|
||||||
static PHARDWARE_TIMER IpsTimer;
|
static PHARDWARE_TIMER IpsTimer;
|
||||||
static ULONGLONG Cycles = 0ULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
#ifdef IPS_DISPLAY
|
static VOID FASTCALL IpsCallback(ULONGLONG ElapsedTime)
|
||||||
static VOID FASTCALL IpsDisplayCallback(ULONGLONG ElapsedTime)
|
|
||||||
{
|
{
|
||||||
DPRINT1("NTVDM: %I64u Instructions Per Second\n", Cycles / ElapsedTime);
|
CurrentIps = (Cycles - LastCycles) / ElapsedTime;
|
||||||
Cycles = 0ULL;
|
|
||||||
}
|
#ifdef IPS_DISPLAY
|
||||||
|
DPRINT1("NTVDM: %I64u Instructions Per Second\n", CurrentIps);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
LastCycles = Cycles;
|
||||||
|
}
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
|
|
||||||
VOID ClockUpdate(VOID)
|
VOID ClockUpdate(VOID)
|
||||||
|
@ -76,10 +78,7 @@ VOID ClockUpdate(VOID)
|
||||||
for (i = 0; VdmRunning && CpuRunning && (i < STEPS_PER_CYCLE); i++)
|
for (i = 0; VdmRunning && CpuRunning && (i < STEPS_PER_CYCLE); i++)
|
||||||
{
|
{
|
||||||
CpuStep();
|
CpuStep();
|
||||||
|
|
||||||
#ifdef IPS_DISPLAY
|
|
||||||
++Cycles;
|
++Cycles;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Entry = Timers.Flink; Entry != &Timers; Entry = Entry->Flink)
|
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)
|
BOOLEAN ClockInitialize(VOID)
|
||||||
{
|
{
|
||||||
InitializeListHead(&Timers);
|
InitializeListHead(&Timers);
|
||||||
|
@ -215,16 +224,12 @@ BOOLEAN ClockInitialize(VOID)
|
||||||
/* Find the starting tick count */
|
/* Find the starting tick count */
|
||||||
// StartTickCount = GetTickCount();
|
// StartTickCount = GetTickCount();
|
||||||
|
|
||||||
#ifdef IPS_DISPLAY
|
IpsTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED, HZ_TO_NS(1), IpsCallback);
|
||||||
|
|
||||||
IpsTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED, HZ_TO_NS(1), IpsDisplayCallback);
|
|
||||||
if (IpsTimer == NULL)
|
if (IpsTimer == NULL)
|
||||||
{
|
{
|
||||||
wprintf(L"FATAL: Cannot create IPS display timer.\n");
|
wprintf(L"FATAL: Cannot create IPS timer.\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,9 @@ VOID DisableHardwareTimer(PHARDWARE_TIMER Timer);
|
||||||
VOID SetHardwareTimerDelay(PHARDWARE_TIMER Timer, ULONGLONG NewDelay);
|
VOID SetHardwareTimerDelay(PHARDWARE_TIMER Timer, ULONGLONG NewDelay);
|
||||||
VOID DestroyHardwareTimer(PHARDWARE_TIMER Timer);
|
VOID DestroyHardwareTimer(PHARDWARE_TIMER Timer);
|
||||||
|
|
||||||
|
ULONGLONG GetCycleCount(VOID);
|
||||||
|
ULONGLONG GetCycleSpeed(VOID);
|
||||||
|
|
||||||
VOID ClockUpdate(VOID);
|
VOID ClockUpdate(VOID);
|
||||||
BOOLEAN ClockInitialize(VOID);
|
BOOLEAN ClockInitialize(VOID);
|
||||||
|
|
||||||
|
|
|
@ -282,8 +282,8 @@ static BYTE VgaDacRegisters[VGA_PALETTE_SIZE];
|
||||||
|
|
||||||
// static VGA_REGISTERS VgaRegisters;
|
// static VGA_REGISTERS VgaRegisters;
|
||||||
|
|
||||||
static BOOLEAN InVerticalRetrace = FALSE;
|
static ULONGLONG VerticalRetraceCycle = 0ULL;
|
||||||
static BOOLEAN InHorizontalRetrace = FALSE;
|
static ULONGLONG HorizontalRetraceCycle = 0ULL;
|
||||||
|
|
||||||
static BOOLEAN NeedsUpdate = FALSE;
|
static BOOLEAN NeedsUpdate = FALSE;
|
||||||
static BOOLEAN ModeChanged = FALSE;
|
static BOOLEAN ModeChanged = FALSE;
|
||||||
|
@ -1413,8 +1413,31 @@ static BYTE WINAPI VgaReadPort(USHORT Port)
|
||||||
case VGA_INSTAT1_READ_COLOR:
|
case VGA_INSTAT1_READ_COLOR:
|
||||||
{
|
{
|
||||||
BYTE Result = 0;
|
BYTE Result = 0;
|
||||||
BOOLEAN Vsync = InVerticalRetrace;
|
BOOLEAN Vsync, Hsync;
|
||||||
BOOLEAN Hsync = InHorizontalRetrace;
|
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 */
|
/* Reset the AC latch */
|
||||||
VgaAcLatch = FALSE;
|
VgaAcLatch = FALSE;
|
||||||
|
@ -1429,9 +1452,6 @@ static BYTE WINAPI VgaReadPort(USHORT Port)
|
||||||
/* Set an additional flag if there was a vertical retrace */
|
/* Set an additional flag if there was a vertical retrace */
|
||||||
if (Vsync) Result |= VGA_STAT_VRETRACE;
|
if (Vsync) Result |= VGA_STAT_VRETRACE;
|
||||||
|
|
||||||
/* Clear the flags */
|
|
||||||
InHorizontalRetrace = InVerticalRetrace = FALSE;
|
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1787,8 +1807,8 @@ static VOID FASTCALL VgaVerticalRetrace(ULONGLONG ElapsedTime)
|
||||||
|
|
||||||
UNREFERENCED_PARAMETER(ElapsedTime);
|
UNREFERENCED_PARAMETER(ElapsedTime);
|
||||||
|
|
||||||
/* Set the vertical retrace flag */
|
/* Set the vertical retrace cycle */
|
||||||
InVerticalRetrace = TRUE;
|
VerticalRetraceCycle = GetCycleCount();
|
||||||
|
|
||||||
/* If nothing has changed, just return */
|
/* If nothing has changed, just return */
|
||||||
// if (!ModeChanged && !CursorChanged && !PaletteChanged && !NeedsUpdate)
|
// if (!ModeChanged && !CursorChanged && !PaletteChanged && !NeedsUpdate)
|
||||||
|
@ -1859,8 +1879,8 @@ static VOID FASTCALL VgaHorizontalRetrace(ULONGLONG ElapsedTime)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(ElapsedTime);
|
UNREFERENCED_PARAMETER(ElapsedTime);
|
||||||
|
|
||||||
/* Set the flag */
|
/* Set the cycle */
|
||||||
InHorizontalRetrace = TRUE;
|
HorizontalRetraceCycle = GetCycleCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
|
|
|
@ -161,7 +161,7 @@ enum
|
||||||
VGA_CRTC_OFFSET_REG,
|
VGA_CRTC_OFFSET_REG,
|
||||||
VGA_CRTC_UNDERLINE_REG,
|
VGA_CRTC_UNDERLINE_REG,
|
||||||
VGA_CRTC_START_VERT_BLANKING_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_MODE_CONTROL_REG,
|
||||||
VGA_CRTC_LINE_COMPARE_REG,
|
VGA_CRTC_LINE_COMPARE_REG,
|
||||||
VGA_CRTC_MAX_REG
|
VGA_CRTC_MAX_REG
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue