Index: C:/rosbuild/subsystems/ntvdm/bios/bios32/moubios32.c
===================================================================
--- C:/rosbuild/subsystems/ntvdm/bios/bios32/moubios32.c	(revision 66215)
+++ C:/rosbuild/subsystems/ntvdm/bios/bios32/moubios32.c	(working copy)
@@ -28,13 +28,9 @@
 // Mouse IRQ 12
 static VOID WINAPI BiosMouseIrq(LPWORD Stack)
 {
-    // HACK!! Call directly the MOUSE.COM driver instead of going
+    // HACK!! Call directly the emulated MOUSE hardware instead of going
     // through the regular interfaces!!
-    extern COORD DosNewPosition;
-    extern WORD  DosButtonState;
-    DosMouseUpdatePosition(&DosNewPosition);
-    DosMouseUpdateButtons(DosButtonState);
-
+    MouseSendPacket();
     PicIRQComplete(Stack);
 }
 
Index: C:/rosbuild/subsystems/ntvdm/clock.c
===================================================================
--- C:/rosbuild/subsystems/ntvdm/clock.c	(revision 66215)
+++ C:/rosbuild/subsystems/ntvdm/clock.c	(working copy)
@@ -17,7 +17,6 @@
 // #include "clock.h"
 
 #include "hardware/cmos.h"
-#include "hardware/ps2.h"
 #include "hardware/pit.h"
 #include "hardware/video/vga.h"
 
@@ -54,13 +53,164 @@
 static DWORD LastClockUpdate;
 static DWORD LastVerticalRefresh;
 
-static DWORD LastIrq1Tick = 0, LastIrq12Tick = 0;
-
 #ifdef IPS_DISPLAY
     static DWORD LastCyclePrintout;
     static ULONGLONG Cycles = 0;
 #endif
 
+
+/* static DWORD LastIrq1Tick = 0, LastIrq12Tick = 0; */
+
+/* Hardware Clocks */
+
+typedef void (*HwClock)(VOID); // Hardware Clock Prototipe;
+
+
+typedef struct _HARDWARE_CLOCKS
+{
+    CHAR *Label;
+    USHORT Id;
+    USHORT Cycles;
+    DWORD LastTick;
+    HwClock TimerFunction;
+    BOOLEAN IsPaused;
+    struct _HARDWARE_CLOCKS *NextTimer;
+} HARDWARE_CLOCKS, *PHARDWARE_CLOCKS;
+
+static PHARDWARE_CLOCKS HardwareClockList = NULL; // linked List of timers
+
+PHARDWARE_CLOCKS FindInHardwareList(USHORT ClockID)
+{
+    PHARDWARE_CLOCKS Temp;
+    if (HardwareClockList == NULL)
+        return NULL;
+    else
+    {
+        if (HardwareClockList->Id == ClockID)
+            return HardwareClockList;
+    }
+    Temp = HardwareClockList->NextTimer;
+    while (Temp != NULL)
+    {
+        if (Temp->Id == ClockID)
+            return Temp;
+        Temp = Temp->NextTimer;
+    }
+    return NULL;
+}
+
+PHARDWARE_CLOCKS  LastInHardwareList()
+{
+    PHARDWARE_CLOCKS Temp;
+    if (HardwareClockList == NULL)
+        return NULL;
+    Temp = HardwareClockList;
+    while (Temp->NextTimer != NULL)
+    {
+        Temp = Temp->NextTimer;
+    }
+    return Temp;
+}
+
+USHORT RegisterHardwareClock(char *Label, USHORT Cycles, HwClock TimerFunction)
+{
+    PHARDWARE_CLOCKS Last = LastInHardwareList();
+    USHORT HId = 0; 
+    if (Last == NULL)
+    {
+        HardwareClockList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HARDWARE_CLOCKS));
+        HardwareClockList->Label = Label;
+        HId = 1;
+        HardwareClockList->Id = HId;
+        HardwareClockList->LastTick = CurrentTickCount;
+        HardwareClockList->Cycles = Cycles;
+        HardwareClockList->TimerFunction = TimerFunction;
+        HardwareClockList->IsPaused = 0;
+        HardwareClockList->NextTimer = NULL;
+        return 1;
+    }
+    else
+    {
+        Last->NextTimer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HARDWARE_CLOCKS));
+        HId = Last->Id +1;
+        Last = Last->NextTimer;
+        Last->Label = Label;
+        Last->Id = HId;
+        Last->LastTick = CurrentTickCount;
+        Last->Cycles = Cycles;
+        Last->TimerFunction = TimerFunction;
+        Last->IsPaused = 0;
+        Last->NextTimer = NULL;
+    }
+    return HId;
+}
+
+void UnRegisterHardwareClock(USHORT ClockID)
+{
+    PHARDWARE_CLOCKS Current;
+    PHARDWARE_CLOCKS Temp;
+    if (HardwareClockList == NULL)
+        return;
+    else
+    {
+        if (HardwareClockList->Id == ClockID)
+        {  
+            Temp = HardwareClockList;
+            HardwareClockList = Temp->NextTimer;
+            HeapFree(GetProcessHeap(), 0, Temp);
+            return;
+        }
+    }
+    Current = HardwareClockList;
+    while (Current->NextTimer != NULL){
+        Temp = Current->NextTimer;
+        if (Temp->Id == ClockID)
+        {
+            Current->NextTimer = Temp->NextTimer;
+            HeapFree(GetProcessHeap(), 0, Temp);
+            return;
+        }
+        Current = Current->NextTimer;
+    }
+}
+
+void PauseHardwareClock(USHORT ClockID,BOOLEAN IsPaused)
+{
+    PHARDWARE_CLOCKS Temp = FindInHardwareList(ClockID);
+    if (Temp != NULL)
+        Temp->IsPaused = IsPaused;
+}
+
+void HardwareClocksUpdate()
+{
+    PHARDWARE_CLOCKS Current= HardwareClockList;
+    while (Current != NULL)
+    {
+        if ((CurrentTickCount - Current->LastTick) >= Current->Cycles)
+        {
+            Current->TimerFunction();
+            Current->LastTick = CurrentTickCount;
+            //DPRINT1("Hardware Tick for %s\n",Current->Label);
+        }
+        Current = Current->NextTimer;
+    }
+}
+
+void HardwareClocksDispose()
+{
+    PHARDWARE_CLOCKS Current = HardwareClockList;
+    PHARDWARE_CLOCKS Temp;
+    if (Current != NULL)
+    {
+        while (Current->NextTimer != NULL){
+            Temp = Current->NextTimer;
+            Current->NextTimer = Temp->NextTimer;
+            HeapFree(GetProcessHeap(), 0, Temp);
+        }
+        HeapFree(GetProcessHeap(), 0, HardwareClockList);
+    }
+}
+
 /* PUBLIC FUNCTIONS ***********************************************************/
 
 VOID ClockUpdate(VOID)
@@ -135,6 +285,11 @@
         LastVerticalRefresh = CurrentTickCount;
     }
 
+    /* Horizontal retrace occurs as fast as possible */
+    VgaHorizontalRetrace();
+    
+    HardwareClocksUpdate();
+    /*
     if ((CurrentTickCount - LastIrq1Tick) >= IRQ1_CYCLES)
     {
         GenerateIrq1();
@@ -146,10 +301,8 @@
         GenerateIrq12();
         LastIrq12Tick = CurrentTickCount;
     }
-
-    /* Horizontal retrace occurs as fast as possible */
-    VgaHorizontalRetrace();
-
+    */
+    
     /* Continue CPU emulation */
     for (i = 0; VdmRunning && CpuRunning && (i < STEPS_PER_CYCLE); i++)
     {
@@ -197,3 +350,7 @@
 
     return TRUE;
 }
+
+void ClockDispose(VOID){
+    HardwareClocksDispose();
+}
Index: C:/rosbuild/subsystems/ntvdm/clock.h
===================================================================
--- C:/rosbuild/subsystems/ntvdm/clock.h	(revision 66215)
+++ C:/rosbuild/subsystems/ntvdm/clock.h	(working copy)
@@ -14,7 +14,17 @@
 
 VOID ClockUpdate(VOID);
 BOOLEAN ClockInitialize(VOID);
+VOID ClockDispose(VOID);
 
+/* Hardware Clocks Emulation */
+
+
+typedef VOID (*HwClock)(VOID); // Hardware Clock Prototipe;
+
+USHORT RegisterHardwareClock(char *Label, USHORT Cycles, HwClock TimerFunction);
+VOID UnRegisterHardwareClock(USHORT ClockID);
+VOID PauseHardwareClock(USHORT ClockID, BOOLEAN IsPaused);
+
 #endif // _CLOCK_H_
 
 /* EOF */
Index: C:/rosbuild/subsystems/ntvdm/dos/dem.c
===================================================================
--- C:/rosbuild/subsystems/ntvdm/dos/dem.c	(revision 66215)
+++ C:/rosbuild/subsystems/ntvdm/dos/dem.c	(working copy)
@@ -423,7 +423,7 @@
     RegisterBop(BOP_START_DOS, NULL);
 
     /* Load the mouse driver */
-    // DosMouseInitialize();
+    DosMouseInitialize();
 
 #ifndef STANDALONE
 
Index: C:/rosbuild/subsystems/ntvdm/dos/mouse32.c
===================================================================
--- C:/rosbuild/subsystems/ntvdm/dos/mouse32.c	(revision 66215)
+++ C:/rosbuild/subsystems/ntvdm/dos/mouse32.c	(working copy)
@@ -19,17 +19,25 @@
 
 #include "io.h"
 #include "dos32krnl/dos.h"
+#include "hardware/video/vga.h"
 
 /* PRIVATE VARIABLES **********************************************************/
 
-static BOOLEAN DriverEnabled = TRUE;
+static BOOLEAN DriverEnabled = FALSE;
 static MOUSE_DRIVER_STATE DriverState;
-
 /**/
 COORD DosNewPosition;
 WORD  DosButtonState;
 /**/
 
+/* Windows Related Variables */
+SHORT WidthPixels;
+SHORT HeightPixels;
+SHORT WindowFactorX;
+SHORT WindowFactorY;
+BOOLEAN IsWindowProportional = TRUE;
+
+
 /* PRIVATE FUNCTIONS **********************************************************/
 
 static VOID PaintMouseCursor(VOID)
@@ -41,8 +49,8 @@
 
         EmulatorReadMemory(&EmulatorContext,
                            VideoAddress
-                           + (DriverState.Position.Y * Bda->ScreenColumns
-                           + DriverState.Position.X) * sizeof(WORD),
+                           + (DriverState.Position.Y/8 * Bda->ScreenColumns
+                           + DriverState.Position.X/8) * sizeof(WORD),
                            (LPVOID)&Character,
                            sizeof(WORD));
 
@@ -52,8 +60,8 @@
 
         EmulatorWriteMemory(&EmulatorContext,
                             VideoAddress
-                            + (DriverState.Position.Y * Bda->ScreenColumns
-                            + DriverState.Position.X) * sizeof(WORD),
+                            + (DriverState.Position.Y/8 * Bda->ScreenColumns
+                            + DriverState.Position.X/8) * sizeof(WORD),
                             (LPVOID)&Character,
                             sizeof(WORD));
     }
@@ -72,8 +80,8 @@
 
         EmulatorWriteMemory(&EmulatorContext,
                             VideoAddress
-                            + (DriverState.Position.Y * Bda->ScreenColumns
-                            + DriverState.Position.X) * sizeof(WORD),
+                            + (DriverState.Position.Y/8 * Bda->ScreenColumns
+                            + DriverState.Position.X/8) * sizeof(WORD),
                             (LPVOID)&DriverState.Character,
                             sizeof(WORD));
     }
@@ -110,8 +118,9 @@
         setBX(DriverState.ButtonState);
         setCX(DriverState.Position.X);
         setDX(DriverState.Position.Y);
-        setSI(DriverState.MickeysPerCellHoriz);
-        setDI(DriverState.MickeysPerCellVert);
+        setSI(DriverState.HorizCount);
+        setDI(DriverState.VertCount);
+        
 
         DPRINT("Calling Handler0 %04X:%04X with CallMask 0x%04X\n",
                HIWORD(DriverState.Handler0.Callback),
@@ -152,8 +161,8 @@
             setBX(DriverState.ButtonState);
             setCX(DriverState.Position.X);
             setDX(DriverState.Position.Y);
-            setSI(DriverState.MickeysPerCellHoriz);
-            setDI(DriverState.MickeysPerCellVert);
+            setSI(DriverState.HorizCount);
+            setDI(DriverState.VertCount);
 
             DPRINT1("Calling Handler[%d] %04X:%04X with CallMask 0x%04X\n",
                     i,
@@ -174,77 +183,181 @@
     }
 }
 
-static VOID WINAPI DosMouseService(LPWORD Stack)
+
+VOID UseProportionalMotion(BOOLEAN Flag)
 {
-    switch (getAX())
+    IsWindowProportional = Flag;
+}
+
+static VOID CalcolateProportionalFactor()
+{
+    //WindowFactorX =  (((MaxX-MinX) * MickyCellX)*100)/(WindowWidth * MouseResolution) 
+    WindowFactorX = (((DriverState.MaxX - DriverState.MinX) * DriverState.MickeysPerCellHoriz)*100)/(WidthPixels * DriverState.MouseResolution);
+    WindowFactorY = (((DriverState.MaxY - DriverState.MinY) * DriverState.MickeysPerCellVert)*100)/(HeightPixels * DriverState.MouseResolution);
+    //DPRINT1("CalcPropFactorX %04d = (((%04d - %04d)*%04d)*100)/(%04d*%04d)\n",WindowFactorX,DriverState.MaxX,DriverState.MinX,DriverState.MickeysPerCellHoriz,WidthPixels,DriverState.MouseResolution); 
+    //DPRINT1("CalcPropFactorY %04d = (((%04d - %04d)*%04d)*100)/(%04d*%04d)\n",WindowFactorY,DriverState.MaxY,DriverState.MinY,DriverState.MickeysPerCellVert,HeightPixels,DriverState.MouseResolution); 
+}
+
+SHORT PropMickeyX(SHORT MickeyIn)
+{
+    if (IsWindowProportional)
     {
-        /* Reset Driver */
-        case 0x00:
-        {
-            SHORT i;
+        return (MickeyIn*WindowFactorX)/100;
+    }
+    return MickeyIn;
+}
 
-            DriverEnabled = TRUE;
-            DriverState.ShowCount = 0;
-            DriverState.ButtonState = 0;
+SHORT PropMickeyY(SHORT MickeyIn)
+{
+    if (IsWindowProportional)
+    {
+        return (MickeyIn*WindowFactorY)/100;
+    }
+    return MickeyIn;
+}
 
-            /* Set the default text cursor */
-            DriverState.TextCursor.ScreenMask = 0xFFFF; /* Display everything */
-            DriverState.TextCursor.CursorMask = 0xFF00; /* ... but with inverted attributes */
 
-            /* Set the default graphics cursor */
-            DriverState.GraphicsCursor.HotSpot.X = 3;
-            DriverState.GraphicsCursor.HotSpot.Y = 1;
+static VOID InitializeMouseRange(VOID)
+{
+    /* Initialize Mouse Range */
+    DriverState.ScreenResolution = VgaGetDisplayResolution();
+    DriverState.MinX = DriverState.MinY = 0;
+    DriverState.VideoMode = Bda->VideoMode;
+    if (DriverState.VideoMode <= 0x03)
+    {
+        DriverState.ScreenResolution.X*=8;
+        DriverState.ScreenResolution.Y*=8;
+    }
+    DriverState.MaxX = DriverState.ScreenResolution.X -1;
+    DriverState.MaxY = DriverState.ScreenResolution.Y -1;
+    
+    /* DPRINT1("InitializeMouseRange VideoMode:0x%04X Width:%04d Height:%04d\n",Bda->VideoMode,DriverState.MaxX,DriverState.MaxY);	*/
+}
 
-            DriverState.GraphicsCursor.ScreenMask[0] = 0xC3FF;  // 1100001111111111
-            DriverState.GraphicsCursor.ScreenMask[1] = 0xC0FF;  // 1100000011111111
-            DriverState.GraphicsCursor.ScreenMask[2] = 0xC07F;  // 1100000001111111
-            DriverState.GraphicsCursor.ScreenMask[3] = 0xC01F;  // 1100000000011111
-            DriverState.GraphicsCursor.ScreenMask[4] = 0xC00F;  // 1100000000001111
-            DriverState.GraphicsCursor.ScreenMask[5] = 0xC007;  // 1100000000000111
-            DriverState.GraphicsCursor.ScreenMask[6] = 0xC003;  // 1100000000000011
-            DriverState.GraphicsCursor.ScreenMask[7] = 0xC007;  // 1100000000000111
-            DriverState.GraphicsCursor.ScreenMask[8] = 0xC01F;  // 1100000000011111
-            DriverState.GraphicsCursor.ScreenMask[9] = 0xC01F;  // 1100000000011111
-            DriverState.GraphicsCursor.ScreenMask[10] = 0xC00F; // 1100000000001111
-            DriverState.GraphicsCursor.ScreenMask[11] = 0xC60F; // 1100011000001111
-            DriverState.GraphicsCursor.ScreenMask[12] = 0xFF07; // 1111111100000111
-            DriverState.GraphicsCursor.ScreenMask[13] = 0xFF07; // 1111111100000111
-            DriverState.GraphicsCursor.ScreenMask[14] = 0xFF87; // 1111111110000111
-            DriverState.GraphicsCursor.ScreenMask[15] = 0xFFCF; // 1111111111001111
+static VOID GetWindowResolution(VOID)
+{
+    HWND hWnd;
+    HDC hDC;
 
-            DriverState.GraphicsCursor.CursorMask[0] = 0x0000;  // 0000000000000000
-            DriverState.GraphicsCursor.CursorMask[1] = 0x1C00;  // 0001110000000000
-            DriverState.GraphicsCursor.CursorMask[2] = 0x1F00;  // 0001111100000000
-            DriverState.GraphicsCursor.CursorMask[3] = 0x1F80;  // 0001111110000000
-            DriverState.GraphicsCursor.CursorMask[4] = 0x1FE0;  // 0001111111100000
-            DriverState.GraphicsCursor.CursorMask[5] = 0x1FF0;  // 0001111111110000
-            DriverState.GraphicsCursor.CursorMask[6] = 0x1FF8;  // 0001111111111000
-            DriverState.GraphicsCursor.CursorMask[7] = 0x1FE0;  // 0001111111100000
-            DriverState.GraphicsCursor.CursorMask[8] = 0x1FC0;  // 0001111111000000
-            DriverState.GraphicsCursor.CursorMask[9] = 0x1FC0;  // 0001111111000000
-            DriverState.GraphicsCursor.CursorMask[10] = 0x19E0; // 0001100111100000
-            DriverState.GraphicsCursor.CursorMask[11] = 0x00E0; // 0000000011100000
-            DriverState.GraphicsCursor.CursorMask[12] = 0x0070; // 0000000001110000
-            DriverState.GraphicsCursor.CursorMask[13] = 0x0070; // 0000000001110000
-            DriverState.GraphicsCursor.CursorMask[14] = 0x0030; // 0000000000110000
-            DriverState.GraphicsCursor.CursorMask[15] = 0x0000; // 0000000000000000
+    /* Get the console window */
+    hWnd = GetConsoleWindow();
+    if (hWnd == NULL) return ;
 
-            /* Initialize the counters */
-            DriverState.HorizCount = DriverState.VertCount = 0;
+    /* Get the console window's device context */
+    hDC = GetWindowDC(hWnd);
+    if (hDC == NULL) return ;
 
-            for (i = 0; i < NUM_MOUSE_BUTTONS; i++)
-            {
-                DriverState.PressCount[i] = DriverState.ReleaseCount[i] = 0;
-            }
+    /* Get the parameters */
+    WidthPixels  = (SHORT)GetDeviceCaps(hDC, HORZRES);
+    HeightPixels = (SHORT)GetDeviceCaps(hDC, VERTRES);
+    /* Release the device context */
+    ReleaseDC(hWnd, hDC);
+}
 
-            /* Initialize the resolution */
-            DriverState.MickeysPerCellHoriz = 8;
-            DriverState.MickeysPerCellVert = 16;
+static VOID DosCursorSetPosition(SHORT X, SHORT Y)
+{
+    POINT Point;
 
-            /* Return mouse information */
+    /* Set Internal Position*/
+    DriverState.Position.X = X;
+    DriverState.Position.Y = Y;
+    /* Reset the counters */
+    DriverState.HorizCount = DriverState.VertCount = 0;
+    /* Calculete position of real pointer */
+    Point.x = X*WidthPixels/DriverState.MaxX;
+    Point.y = Y*HeightPixels/DriverState.MaxY;
+    ClientToScreen(GetConsoleWindow(), &Point);
+    SetCursorPos(Point.x, Point.y);
+    DPRINT1("DosCursorSetPosition X:%04d Y:%04d -> X:%04d Y:%04d\n",X,Y,Point.x,Point.y); 
+}
+
+static VOID DosMouseReset(VOID)
+{
+    SHORT i;
+    DriverState.ShowCount = 0;
+    DriverState.ButtonState = 0;
+
+    /* Set the default text cursor */
+    DriverState.TextCursor.ScreenMask = 0xFFFF; /* Display everything */
+    DriverState.TextCursor.CursorMask = 0xFF00; /* ... but with inverted attributes */
+
+    /* Set the default graphics cursor */
+    DriverState.GraphicsCursor.HotSpot.X = 3;
+    DriverState.GraphicsCursor.HotSpot.Y = 1;
+
+    DriverState.GraphicsCursor.ScreenMask[0] = 0xC3FF;  // 1100001111111111
+    DriverState.GraphicsCursor.ScreenMask[1] = 0xC0FF;  // 1100000011111111
+    DriverState.GraphicsCursor.ScreenMask[2] = 0xC07F;  // 1100000001111111
+    DriverState.GraphicsCursor.ScreenMask[3] = 0xC01F;  // 1100000000011111
+    DriverState.GraphicsCursor.ScreenMask[4] = 0xC00F;  // 1100000000001111
+    DriverState.GraphicsCursor.ScreenMask[5] = 0xC007;  // 1100000000000111
+    DriverState.GraphicsCursor.ScreenMask[6] = 0xC003;  // 1100000000000011
+    DriverState.GraphicsCursor.ScreenMask[7] = 0xC007;  // 1100000000000111
+    DriverState.GraphicsCursor.ScreenMask[8] = 0xC01F;  // 1100000000011111
+    DriverState.GraphicsCursor.ScreenMask[9] = 0xC01F;  // 1100000000011111
+    DriverState.GraphicsCursor.ScreenMask[10] = 0xC00F; // 1100000000001111
+    DriverState.GraphicsCursor.ScreenMask[11] = 0xC60F; // 1100011000001111
+    DriverState.GraphicsCursor.ScreenMask[12] = 0xFF07; // 1111111100000111
+    DriverState.GraphicsCursor.ScreenMask[13] = 0xFF07; // 1111111100000111
+    DriverState.GraphicsCursor.ScreenMask[14] = 0xFF87; // 1111111110000111
+    DriverState.GraphicsCursor.ScreenMask[15] = 0xFFCF; // 1111111111001111
+
+    DriverState.GraphicsCursor.CursorMask[0] = 0x0000;  // 0000000000000000
+    DriverState.GraphicsCursor.CursorMask[1] = 0x1C00;  // 0001110000000000
+    DriverState.GraphicsCursor.CursorMask[2] = 0x1F00;  // 0001111100000000
+    DriverState.GraphicsCursor.CursorMask[3] = 0x1F80;  // 0001111110000000
+    DriverState.GraphicsCursor.CursorMask[4] = 0x1FE0;  // 0001111111100000
+    DriverState.GraphicsCursor.CursorMask[5] = 0x1FF0;  // 0001111111110000
+    DriverState.GraphicsCursor.CursorMask[6] = 0x1FF8;  // 0001111111111000
+    DriverState.GraphicsCursor.CursorMask[7] = 0x1FE0;  // 0001111111100000
+    DriverState.GraphicsCursor.CursorMask[8] = 0x1FC0;  // 0001111111000000
+    DriverState.GraphicsCursor.CursorMask[9] = 0x1FC0;  // 0001111111000000
+    DriverState.GraphicsCursor.CursorMask[10] = 0x19E0; // 0001100111100000
+    DriverState.GraphicsCursor.CursorMask[11] = 0x00E0; // 0000000011100000
+    DriverState.GraphicsCursor.CursorMask[12] = 0x0070; // 0000000001110000
+    DriverState.GraphicsCursor.CursorMask[13] = 0x0070; // 0000000001110000
+    DriverState.GraphicsCursor.CursorMask[14] = 0x0030; // 0000000000110000
+    DriverState.GraphicsCursor.CursorMask[15] = 0x0000; // 0000000000000000
+
+    /* Initialize the counters */
+    DriverState.HorizCount = DriverState.VertCount = 0;
+
+    for (i = 0; i < NUM_MOUSE_BUTTONS; i++)
+    {
+        DriverState.PressCount[i] = DriverState.ReleaseCount[i] = 0;
+    }
+
+    /* Initialize the resolution */
+    DriverState.MickeysPerCellHoriz = 8;
+    DriverState.MickeysPerCellVert = 16;
+    /* Initialize Mouse Resolution */
+    DriverState.MouseResolution = 4;
+    /* Initialize Double Speed Threshold */
+    DriverState.DoubleSpeedThreshold = 64;
+    /* Set Mouse Constraint Area */
+    InitializeMouseRange();
+    /* Get Window Size */
+    GetWindowResolution();
+    /* Calcolete Proportional Factor */
+    CalcolateProportionalFactor();
+    /* Center Mouse cursor */
+    DosCursorSetPosition(DriverState.ScreenResolution.X / 2, DriverState.ScreenResolution.Y /2);
+    /* Return mouse information */
+    DriverEnabled = TRUE;
+}
+
+
+static VOID WINAPI DosMouseService(LPWORD Stack)
+{/*int logevent=1; */
+    switch (getAX())
+    {
+            
+        /* Reset Driver */
+        case 0x00:
+        {
+            DosMouseReset();
             setAX(0xFFFF);  // Hardware & driver installed
             setBX(NUM_MOUSE_BUTTONS);
-
             break;
         }
 
@@ -278,14 +391,7 @@
         /* Position Mouse Cursor */
         case 0x04:
         {
-            POINT Point;
-
-            Point.x = getCX();
-            Point.y = getDX();
-
-            ClientToScreen(GetConsoleWindow(), &Point);
-            SetCursorPos(Point.x, Point.y);
-
+            DosCursorSetPosition(getCX(),getDX());
             break;
         }
 
@@ -322,6 +428,32 @@
 
         }
 
+        /* Set  Horizontal Range */
+        case 0x07:
+        {
+            DriverState.MinX = getCX();
+            DriverState.MaxX = getDX();
+            if (DriverState.MinX>DriverState.MaxX){
+                DriverState.MinX = getDX();
+                DriverState.MaxX = getCX();
+            }
+            CalcolateProportionalFactor();
+            break;
+        }
+
+        /* Set  Vertical Range */
+        case 0x08:
+        {
+            DriverState.MinY = getCX();
+            DriverState.MaxY = getDX();
+            if (DriverState.MinY>DriverState.MaxY){
+                DriverState.MinY = getDX();
+                DriverState.MaxY = getCX();
+            }
+            CalcolateProportionalFactor();
+            break;
+        }
+
         /* Define Graphics Cursor */
         case 0x09:
         {
@@ -397,9 +529,17 @@
         {
             DriverState.MickeysPerCellHoriz = getCX();
             DriverState.MickeysPerCellVert  = getDX();
+            CalcolateProportionalFactor();
             break;
         }
-
+       
+        /* Set Double Speed Threshold */
+        case 0x13:
+        {
+            DriverState.DoubleSpeedThreshold = getDX();
+            break;
+        }
+        
         /* Exchange Interrupt Subroutines, compatible MS MOUSE v3.0+ (see function 0x0C) */
         case 0x14:
         {
@@ -604,27 +744,53 @@
             DPRINT1("BIOS Function INT 33h, AX = 0x%04X NOT IMPLEMENTED\n", getAX());
         }
     }
+    /*if (logevent) DPRINT1("Exiting DosMouseService AX:0x%04X BX:0x%04X CX:0x%04X DX:0x%04X  \n", getAX(), getBX(), getCX(), getDX());*/
 }
 
+SHORT GetDoubled(SHORT Value)
+{
+    if ((Value >= DriverState.DoubleSpeedThreshold ) || ((DriverState.DoubleSpeedThreshold*-1) >= Value))
+    {          
+        return Value * 2;
+    }
+    else
+    {
+        return Value;
+    }
+}
+
+
 /* PUBLIC FUNCTIONS ***********************************************************/
 
 VOID DosMouseUpdatePosition(PCOORD NewPosition)
 {
-    SHORT DeltaX = NewPosition->X - DriverState.Position.X;
-    SHORT DeltaY = NewPosition->Y - DriverState.Position.Y;
-
     if (!DriverEnabled) return;
+    //DPRINT1("DosMouseUpdatePosition Horizontal:0x%04d Vertical:0x%04d \n",NewPosition->X,NewPosition->Y);
+    DriverState.HorizCount += PropMickeyX(GetDoubled(NewPosition->X));
+    DriverState.VertCount  += PropMickeyY(GetDoubled(NewPosition->Y));
+    if (NewPosition->X || NewPosition->Y)
+    {
+        if (DriverState.ShowCount > 0)
+            EraseMouseCursor();
+        DriverState.Position.X += PropMickeyX(GetDoubled(NewPosition->X))/DriverState.MickeysPerCellHoriz;
+        DriverState.Position.Y += PropMickeyY(GetDoubled(NewPosition->Y))/DriverState.MickeysPerCellVert;
 
-    DriverState.HorizCount += (DeltaX * (SHORT)DriverState.MickeysPerCellHoriz) / 8;
-    DriverState.VertCount  += (DeltaY * (SHORT)DriverState.MickeysPerCellVert ) / 8;
+        /* Limit position to defined range */
+        if (DriverState.Position.X < DriverState.MinX)
+            DriverState.Position.X= DriverState.MinX;
+        if (DriverState.Position.X > DriverState.MaxX)
+            DriverState.Position.X = DriverState.MaxX;
+        if (DriverState.Position.Y < DriverState.MinY)
+            DriverState.Position.Y = DriverState.MinY;
+        if (DriverState.Position.Y > DriverState.MaxY)
+            DriverState.Position.Y = DriverState.MaxY;
 
-    if (DriverState.ShowCount > 0) EraseMouseCursor();
-    DriverState.Position = *NewPosition;
-    if (DriverState.ShowCount > 0) PaintMouseCursor();
-
-    /* Call the mouse handlers */
-    // if (DeltaX || DeltaY)
-    CallMouseUserHandlers(0x0001); // We use MS MOUSE v1.0+ format
+        if (DriverState.ShowCount > 0)
+            PaintMouseCursor();
+        /* Call the mouse handlers */
+        CallMouseUserHandlers(0x0001); // We use MS MOUSE v1.0+ format
+        //DPRINT1("DosMouseUpdatePosition PositionX:0x%06d PositionY:0x%06d \n", DriverState.Position.X, DriverState.Position.Y);
+    }
 }
 
 VOID DosMouseUpdateButtons(WORD ButtonState)
@@ -667,10 +833,9 @@
 {
     /* Clear the state */
     RtlZeroMemory(&DriverState, sizeof(DriverState));
-
     /* Initialize the interrupt handler */
     RegisterDosInt32(DOS_MOUSE_INTERRUPT, DosMouseService);
-
+    DosMouseReset();
     return TRUE;
 }
 
Index: C:/rosbuild/subsystems/ntvdm/dos/mouse32.h
===================================================================
--- C:/rosbuild/subsystems/ntvdm/dos/mouse32.h	(revision 66215)
+++ C:/rosbuild/subsystems/ntvdm/dos/mouse32.h	(working copy)
@@ -49,6 +49,14 @@
     SHORT VertCount;
     WORD MickeysPerCellHoriz;
     WORD MickeysPerCellVert;
+    WORD MinX;
+    WORD MinY;
+    WORD MaxX;
+    WORD MaxY;
+    SHORT DoubleSpeedThreshold;
+    SHORT MouseResolution;
+    COORD ScreenResolution;
+    BYTE VideoMode;
 
     /*
      * User Subroutine Handlers called on mouse events
@@ -75,6 +83,8 @@
 VOID DosMouseUpdatePosition(PCOORD NewPosition);
 VOID DosMouseUpdateButtons(WORD ButtonStatus);
 
+VOID DosMouseUseProportionalMotion(BOOLEAN Flag);
+
 BOOLEAN DosMouseInitialize(VOID);
 VOID DosMouseCleanup(VOID);
 
Index: C:/rosbuild/subsystems/ntvdm/hardware/mouse.c
===================================================================
--- C:/rosbuild/subsystems/ntvdm/hardware/mouse.c	(revision 66215)
+++ C:/rosbuild/subsystems/ntvdm/hardware/mouse.c	(working copy)
@@ -11,6 +11,7 @@
 #define NDEBUG
 
 #include "mouse.h"
+#include "dos\mouse32.h"
 #include "ps2.h"
 // #include "pic.h"
 
@@ -17,10 +18,8 @@
 /* PRIVATE VARIABLES **********************************************************/
 
 static MOUSE_MODE Mode, PreviousMode;
-static COORD Position;
-static ULONG WidthMm, HeightMm, WidthPixels, HeightPixels;
 static ULONG SampleRate;
-static ULONG Resolution;
+static SHORT Resolution;
 static BOOLEAN Scaling;
 static BOOLEAN Reporting;
 static BYTE MouseId;
@@ -27,10 +26,18 @@
 static ULONG ButtonState;
 static SHORT HorzCounter;
 static SHORT VertCounter;
-static CHAR ScrollCounter;
-
+static SHORT ScrollCounter;
+static MOUSE_PACKET MousePacket;
 static BYTE PS2Port = 1;
 
+//Emulation Variables
+static PCOORD Position; // windows use absolute position 
+static PCOORD RelativePosition;
+static HANDLE HMouseMutex;
+const wchar_t* MOUSEMUTEX = L"Mouse Mutex";
+static BOOLEAN  IsStateChanged=0;
+ 
+
 /* PRIVATE FUNCTIONS **********************************************************/
 
 static VOID MouseResetConfig(VOID)
@@ -42,10 +49,18 @@
     Reporting = FALSE;
 }
 
+static VOID MouseEmulationResetConfig(VOID)
+{
+     // should release this
+    Position = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COORD));
+    RelativePosition = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COORD));
+}
+
 static VOID MouseResetCounters(VOID)
 {
     /* Reset all flags and counters */
     ButtonState = HorzCounter = VertCounter = ScrollCounter = 0;
+    IsStateChanged=0;
 }
 
 static VOID MouseReset(VOID)
@@ -63,9 +78,9 @@
     PS2QueuePush(PS2Port, MouseId);
 }
 
-#if 0
 static VOID MouseGetPacket(PMOUSE_PACKET Packet)
 {
+
     /* Clear the packet */
     RtlZeroMemory(Packet, sizeof(*Packet));
 
@@ -83,7 +98,7 @@
     /* Check for vertical overflows */
     if ((VertCounter < MOUSE_MIN) || (VertCounter > MOUSE_MAX))
     {
-        if (VertCounter > MOUSE_MIN) VertCounter = MOUSE_MIN;
+        if (VertCounter > MOUSE_MAX) VertCounter = MOUSE_MAX;
         if (VertCounter < MOUSE_MIN) VertCounter = MOUSE_MIN;
 
         Packet->Flags |= MOUSE_Y_OVERFLOW;
@@ -107,33 +122,107 @@
     if (MouseId >= 3)
     {
         /* Set the scroll counter */
-        Packet->Extra |= (UCHAR)ScrollCounter & 0x0F;
+        Packet->Extra |= ScrollCounter & 0x0F;
     }
 
     /* Store the counters in the packet */
     Packet->HorzCounter = LOBYTE(HorzCounter);
     Packet->VertCounter = LOBYTE(VertCounter);
+}
 
-    /* Reset the counters */
-    MouseResetCounters();
+/* scaling according to http://www.computer-engineering.org/ps2mouse/ */
+
+SHORT Scale(SHORT Value)
+{
+    if (Scaling && (Mode == MOUSE_STREAMING_MODE))
+    {
+        switch (Value)
+        {   
+            case -4: 
+                return -6;
+            case -3: 
+                return -3;
+            case -2: 
+                return -1;
+            case -1: 
+                 return -1;
+            case 0: 
+                return 0;
+            case 1: 
+                return 1;
+            case 2: 
+                return 1;
+            case 3: 
+                return 3;
+            case 4: 
+                return 6;
+            default: 
+                return 2 * Value; 
+        }
+    }
+    return Value;
 }
-#endif
 
 /*static*/ VOID MouseUpdatePosition(PCOORD NewPosition)
 {
     /* Update the counters */
-    HorzCounter += ((NewPosition->X - Position.X) * WidthMm  * Resolution) / WidthPixels;
-    VertCounter += ((NewPosition->Y - Position.Y) * HeightMm * Resolution) / HeightPixels;
+    HorzCounter += Scale(NewPosition->X) * Resolution;
+    VertCounter += Scale(NewPosition->Y) * Resolution;
+}
 
-    /* Update the position */
-    Position = *NewPosition;
+static PCOORD EmulateRelativePosition()
+{
+    /* Calculate a Relative position in Mickey */
+    POINT p;
+    GetCursorPos(&p);
+    RelativePosition->X = (p.x - Position->X); // *2  work better in most applications
+    RelativePosition->Y = (p.y - Position->Y); // *2  work better in most applications
+    Position->X=p.x;
+    Position->Y=p.y;
+    return RelativePosition;
 }
 
+
 /*static*/ VOID MouseUpdateButtons(ULONG NewButtonState)
 {
     ButtonState = NewButtonState;
 }
 
+VOID MouseSendPacket(VOID) 
+{
+    COORD MousePosition;
+    if (IsStateChanged)
+    {
+        WaitForSingleObject(HMouseMutex,INFINITE);
+        MouseGetPacket(&MousePacket);
+        /* HACK  Bypass PS/2 and call the driver with raw data
+            PS2QueuePush(PS2Port, MousePacket.Flags);
+            PS2QueuePush(PS2Port, MousePacket.HorzCounter);
+            PS2QueuePush(PS2Port, MousePacket.VertCounter);
+            PS2QueuePush(PS2Port, MousePacket.Extra);
+            */
+        MousePosition.X = HorzCounter;
+        MousePosition.Y = VertCounter;
+        DosMouseUpdatePosition(&MousePosition);
+        DosMouseUpdateButtons(ButtonState);
+        MouseResetCounters();
+        ReleaseMutex(HMouseMutex);
+    }
+}
+
+
+static VOID MouseResendPacket(VOID)
+{
+    /*  Bypass PS/2
+    PS2QueuePush(PS2Port, MousePacket.Flags);
+    PS2QueuePush(PS2Port, MousePacket.HorzCounter);
+    PS2QueuePush(PS2Port, MousePacket.VertCounter);
+    PS2QueuePush(PS2Port, MousePacket.Extra);
+      */
+    return;
+}
+
+
 /*static*/ VOID MouseScroll(LONG Direction)
 {
     ScrollCounter += Direction;
@@ -141,11 +230,12 @@
 
 /*static*/ COORD MouseGetPosition(VOID)
 {
-    return Position;
+    return *Position;
 }
 
 static VOID WINAPI MouseCommand(LPVOID Param, BYTE Command)
-{
+{  
+    WaitForSingleObject(HMouseMutex,INFINITE);
     switch (Command)
     {
         /* Set 1:1 Scaling */
@@ -283,8 +373,7 @@
         /* Resend */
         case 0xFE:
         {
-            // TODO: NOT IMPLEMENTED
-            UNIMPLEMENTED;
+            MouseResendPacket();
             break;
         }
 
@@ -301,52 +390,31 @@
             PS2QueuePush(PS2Port, MOUSE_ERROR);
         }
     }
+    ReleaseMutex(HMouseMutex);
 }
 
 /* PUBLIC FUNCTIONS ***********************************************************/
 
+// FIXME: We need raw data in mickey not in pixel or Cell!
 VOID MouseEventHandler(PMOUSE_EVENT_RECORD MouseEvent)
 {
-extern COORD DosNewPosition;
-extern WORD  DosButtonState;
-
-    // FIXME: Sync our private data
-    MouseUpdatePosition(&MouseEvent->dwMousePosition);
+    WaitForSingleObject(HMouseMutex,INFINITE);
+    /* We should calcolate a relative position for now
+       MouseUpdatePosition(&MouseEvent->dwMousePosition); */
+    MouseUpdatePosition(EmulateRelativePosition());
     MouseUpdateButtons(MouseEvent->dwButtonState);
-
-    // HACK: Bypass PS/2 and instead, notify the MOUSE.COM driver directly
-    DosNewPosition = MouseEvent->dwMousePosition;
-    DosButtonState = LOWORD(MouseEvent->dwButtonState);
-
-    // PS2QueuePush(PS2Port, Data);
+    IsStateChanged=1;
+    ReleaseMutex(HMouseMutex);
 }
 
 BOOLEAN MouseInit(BYTE PS2Connector)
 {
-    HWND hWnd;
-    HDC hDC;
-
-    /* Get the console window */
-    hWnd = GetConsoleWindow();
-    if (hWnd == NULL) return FALSE;
-
-    /* Get the console window's device context */
-    hDC = GetWindowDC(hWnd);
-    if (hDC == NULL) return FALSE;
-
-    /* Get the parameters */
-    WidthMm      = (ULONG)GetDeviceCaps(hDC, HORZSIZE);
-    HeightMm     = (ULONG)GetDeviceCaps(hDC, VERTSIZE);
-    WidthPixels  = (ULONG)GetDeviceCaps(hDC, HORZRES);
-    HeightPixels = (ULONG)GetDeviceCaps(hDC, VERTRES);
-
-    /* Release the device context */
-    ReleaseDC(hWnd, hDC);
-
+    MouseEmulationResetConfig();
     /* Finish to plug the mouse to the specified PS/2 port */
     PS2Port = PS2Connector;
     PS2SetDeviceCmdProc(PS2Port, NULL, MouseCommand);
 
     MouseReset();
+    HMouseMutex = CreateMutex(NULL, FALSE, MOUSEMUTEX);
     return TRUE;
 }
Index: C:/rosbuild/subsystems/ntvdm/hardware/mouse.h
===================================================================
--- C:/rosbuild/subsystems/ntvdm/hardware/mouse.h	(revision 66215)
+++ C:/rosbuild/subsystems/ntvdm/hardware/mouse.h	(working copy)
@@ -70,5 +70,6 @@
 
 VOID MouseEventHandler(PMOUSE_EVENT_RECORD MouseEvent);
 BOOLEAN MouseInit(BYTE PS2Connector);
+VOID MouseSendPacket(VOID);
 
 #endif // _MOUSE_H_
Index: C:/rosbuild/subsystems/ntvdm/hardware/ps2.c
===================================================================
--- C:/rosbuild/subsystems/ntvdm/hardware/ps2.c	(revision 66215)
+++ C:/rosbuild/subsystems/ntvdm/hardware/ps2.c	(working copy)
@@ -12,6 +12,7 @@
 #define NDEBUG
 
 #include "emulator.h"
+#include "clock.h"
 #include "io.h"
 #include "ps2.h"
 #include "pic.h"
@@ -49,6 +50,10 @@
 // static BYTE InputBuffer  = 0x00; // PS/2 Input  Buffer
 static BYTE OutputBuffer = 0x00; // PS/2 Output Buffer
 
+
+static USHORT HardwareTimer1 = 0;
+static USHORT HardwareTimer12 = 0;
+
 /* PRIVATE FUNCTIONS **********************************************************/
 
 static VOID PS2SendCommand(PPS2_PORT Port, BYTE Command)
@@ -379,16 +384,21 @@
         /* Generate an IRQ 1 if there is data ready in the output queue */
         if (PS2PortQueueRead(0)) PicInterruptRequest(1);
     }
+    /*DPRINT1("IRQ1\n");*/
 }
 
 VOID GenerateIrq12(VOID)
 {
-    /* Generate an interrupt if interrupts for the second PS/2 port are enabled */
-    if (ControllerConfig & 0x02)
-    {
-        /* Generate an IRQ 12 if there is data ready in the output queue */
-        if (PS2PortQueueRead(1)) PicInterruptRequest(12);
-    }
+    /* Hack Generate Always IRQ 12 until mouse-ps comunication is fixed */
+    /*Generate an interrupt if interrupts for the second PS/2 port are enabled */
+   //if (ControllerConfig & 0x02)
+   //{
+   /* Generate an IRQ 12 if there is data ready in the output queue */
+   //    if (PS2PortQueueRead(1)) PicInterruptRequest(12);
+   //}
+    
+   PicInterruptRequest(12);
+   /*DPRINT1("IRQ12\n");*/
 }
 
 BOOLEAN PS2Initialize(VOID)
@@ -409,12 +419,15 @@
     /* Register the I/O Ports */
     RegisterIoPort(PS2_CONTROL_PORT, PS2ReadPort, PS2WritePort);
     RegisterIoPort(PS2_DATA_PORT   , PS2ReadPort, PS2WritePort);
-
+    HardwareTimer1 = RegisterHardwareClock("IRQ1", 16, &GenerateIrq1);
+    HardwareTimer12 = RegisterHardwareClock("IRQ12", 16, &GenerateIrq12);
     return TRUE;
 }
 
 VOID PS2Cleanup(VOID)
 {
+    UnRegisterHardwareClock(HardwareTimer1);
+    UnRegisterHardwareClock(HardwareTimer12);
     CloseHandle(Ports[1].QueueMutex);
     CloseHandle(Ports[0].QueueMutex);
 }
