reactos/subsystems/ntvdm/clock.c
Hermès Bélusca-Maïto 105aff1c51 [NTVDM]
- Define and export VDDSimulate16 and host_simulate.
- Move the big emulation loop from ntvdm.c to clock.c, and the console input pump thread from ps2.c to ntvdm.c.
  Indeed:
  * Moving the emulation loop out of the main initialization function will be helpful if one wants to modify how emulation is done,
  * The console input pump thread deals also with console UI bits that have nothing to do with keyboard/mouse/ps-2. Instead, the pump thread will dispatch keyboard and mouse events to the ps/2 controller.
- Implement a custom menu in the console's system menu to be able to parametrize ROS VDM (work-in-progress); at the moment only a menu item to show/hide mouse pointer, and another one allowing us to quit properly the VDM are implemented. The menu code was taken from the GUI frontend in winsrv.dll. Only english and french translations available at the moment.

svn path=/branches/ntvdm/; revision=61902
2014-02-01 16:32:20 +00:00

174 lines
4.3 KiB
C

/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: clock.c
* PURPOSE: Clock for VDM
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES *******************************************************************/
#define NDEBUG
#include "emulator.h"
// #include "clock.h"
#include "hardware/cmos.h"
#include "hardware/ps2.h"
#include "hardware/timer.h"
#include "hardware/vga.h"
/* DEFINES ********************************************************************/
/*
* Activate IPS_DISPLAY if you want to display the
* number of instructions per second, as well as
* the computed number of ticks for the PIT.
*/
// #define IPS_DISPLAY
/*
* Activate WORKING_TIMER when the PIT timing problem is fixed.
*/
// #define WORKING_TIMER
/* Processor speed */
#define STEPS_PER_CYCLE 256
#define KBD_INT_CYCLES 16
/* VARIABLES ******************************************************************/
LARGE_INTEGER StartPerfCount, Frequency;
LARGE_INTEGER LastTimerTick, LastRtcTick, Counter;
LONGLONG TimerTicks;
DWORD StartTickCount, CurrentTickCount;
DWORD LastClockUpdate;
DWORD LastVerticalRefresh;
INT KeyboardIntCounter = 0;
#ifdef IPS_DISPLAY
DWORD LastCyclePrintout;
DWORD Cycles = 0;
#endif
/* PUBLIC FUNCTIONS ***********************************************************/
VOID ClockUpdate(VOID)
{
UINT i;
#ifdef WORKING_TIMER
DWORD PitResolution = PitGetResolution();
#endif
DWORD RtcFrequency = RtcGetTicksPerSecond();
/* Get the current number of ticks */
CurrentTickCount = GetTickCount();
#ifdef WORKING_TIMER
if ((PitResolution <= 1000) && (RtcFrequency <= 1000))
{
/* Calculate the approximate performance counter value instead */
Counter.QuadPart = StartPerfCount.QuadPart
+ (CurrentTickCount - StartTickCount)
* (Frequency.QuadPart / 1000);
}
else
#endif
{
/* Get the current performance counter value */
QueryPerformanceCounter(&Counter);
}
/* Get the number of PIT ticks that have passed */
TimerTicks = ((Counter.QuadPart - LastTimerTick.QuadPart)
* PIT_BASE_FREQUENCY) / Frequency.QuadPart;
/* Update the PIT */
if (TimerTicks > 0)
{
PitClock(TimerTicks);
LastTimerTick = Counter;
}
/* Check for RTC update */
if ((CurrentTickCount - LastClockUpdate) >= 1000)
{
RtcTimeUpdate();
LastClockUpdate = CurrentTickCount;
}
/* Check for RTC periodic tick */
if ((Counter.QuadPart - LastRtcTick.QuadPart)
>= (Frequency.QuadPart / (LONGLONG)RtcFrequency))
{
RtcPeriodicTick();
LastRtcTick = Counter;
}
/* Check for vertical retrace */
if ((CurrentTickCount - LastVerticalRefresh) >= 15)
{
VgaRefreshDisplay();
LastVerticalRefresh = CurrentTickCount;
}
if (++KeyboardIntCounter == KBD_INT_CYCLES)
{
GenerateKeyboardInterrupts();
KeyboardIntCounter = 0;
}
/* Horizontal retrace occurs as fast as possible */
VgaHorizontalRetrace();
/* Continue CPU emulation */
// EmulatorSimulate();
for (i = 0; (i < STEPS_PER_CYCLE) && VdmRunning; i++)
{
EmulatorStep();
#ifdef IPS_DISPLAY
Cycles++;
#endif
}
#ifdef IPS_DISPLAY
if ((CurrentTickCount - LastCyclePrintout) >= 1000)
{
DPRINT1("NTVDM: %lu Instructions Per Second; TimerTicks = %I64d\n", Cycles, TimerTicks);
LastCyclePrintout = CurrentTickCount;
Cycles = 0;
}
#endif
}
BOOLEAN ClockInitialize(VOID)
{
/* Initialize the performance counter (needed for hardware timers) */
if (!QueryPerformanceFrequency(&Frequency))
{
wprintf(L"FATAL: Performance counter not available\n");
return FALSE;
}
/* Find the starting performance and tick count */
StartTickCount = GetTickCount();
QueryPerformanceCounter(&StartPerfCount);
/* Set the different last counts to the starting count */
LastClockUpdate = LastVerticalRefresh =
#ifdef IPS_DISPLAY
LastCyclePrintout =
#endif
StartTickCount;
/* Set the last timer ticks to the current time */
LastTimerTick = LastRtcTick = StartPerfCount;
return TRUE;
}