(You need Visual Studio and 2 mouses)
Introduction
(This code is just a layer implemented into another code: https://github.com/djpnewton/busdog).
This program adds the function of mouse smoothing to your mouse, if you don't know what is mouse smoothing, it's basically a delay between your mouse physical moves and the mouse coordinates (camera in game).
It's used to prevent jitter mouse movement thus add camera movement realism.
Mouse acceleration - PCGamingWiki
To use it:
- First thing first, you need to install the USB sniffer driver to be able to read HID packet of the mouse
- Download it to https://github.com/djpnewton/busdog#downloads
- Run the program and install the driver when it's asked
- Grab devcon there https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/devcon then put it into the Release folder
- Compile the code and run it
- Select your mouse according to its VID/PID values (Identify a VID PID for a USB Device - InterWorks)

- (Smooth Value slider modify the variable MouseSmoothingValue/InterpSpeed)
- Connect a second mouse to your PC (else Windows will not display mouse cursor), but don't use this 2nd mouse, use your main mouse connected to the VID/PID you chosen
- Enjoy the smoothed mouse
- To use it for a game, you need to disable Raw Mouse Input in the option of the game if the game allow it, else you cannot use it
- To close the program, unselect the Device you selected earlier then just Alt-F4 the app (Alt+Tab can help)
Background
This program idea came from a find I made when I played Star Citizen, Mouse Smoothing.

Using the Code
The mouse smoothing is based on the interpolation equation below:
Point InterpTo(Point Current, Point Target, float InterpSpeed)
{
var DeltaMove = new Point()
{
X = (Int32)((Target.X - Current.X) * InterpSpeed),
Y = (Int32)((Target.Y - Current.Y) * InterpSpeed),
};
Target.X = Current.X + DeltaMove.X;
Target.Y = Current.Y + DeltaMove.Y;
return Target;
}
And here's the code where mouse driver simulation is implemented:
void RecievedFilterTraces(object sender, FilterTraceArrivedEventArgs e)
{
Native.MouseOffset.X = 0;
Native.MouseOffset.Y = 0;
foreach (FilterTrace filterTrace in e.Traces.ToArray())
{
if (filterTrace.Buffer[0] != 0x80)
{
if (filterTrace.Buffer[3] == 0x00)
{
Native.MouseOffset.X += filterTrace.Buffer[2];
}
else if (filterTrace.Buffer[3] == 0xFF)
{
Native.MouseOffset.X -= 0x100 - filterTrace.Buffer[2];
}
if (filterTrace.Buffer[5] == 0x00)
{
Native.MouseOffset.Y += filterTrace.Buffer[4];
}
else if (filterTrace.Buffer[5] == 0xFF)
{
Native.MouseOffset.Y -= 0x100 - filterTrace.Buffer[4];
}
if (GetBit(filterTrace.Buffer[0], 0) == 1)
{
if (MouseButton[0] == 0)
{
WinAPI.mouse_event(MOUSEEVENTF_LEFTDOWN, Native.MouseOffset.X,
Native.MouseOffset.Y, 0, 0);
}
MouseButton[0] = 1;
}
else if (MouseButton[0] == 1)
{
WinAPI.mouse_event(MOUSEEVENTF_LEFTUP, Native.MouseOffset.X,
Native.MouseOffset.Y, 0, 0);
MouseButton[0] = 0;
}
if (GetBit(filterTrace.Buffer[0], 1) == 1)
{
if (MouseButton[0] == 0)
{
WinAPI.mouse_event(MOUSEEVENTF_RIGHTDOWN, Native.MouseOffset.X,
Native.MouseOffset.Y, 0, 0);
}
MouseButton[1] = 1;
}
else if (MouseButton[1] == 1)
{
WinAPI.mouse_event(MOUSEEVENTF_RIGHTUP, Native.MouseOffset.X,
Native.MouseOffset.Y, 0, 0);
MouseButton[1] = 0;
}
if (GetBit(filterTrace.Buffer[0], 2) == 1)
{
if (MouseButton[0] == 0)
{
WinAPI.mouse_event(MOUSEEVENTF_MIDDLEDOWN, Native.MouseOffset.X,
Native.MouseOffset.Y, 0, 0);
}
MouseButton[2] = 1;
}
else if (MouseButton[2] == 1)
{
WinAPI.mouse_event(MOUSEEVENTF_MIDDLEUP, Native.MouseOffset.X,
Native.MouseOffset.Y, 0, 0);
MouseButton[2] = 0;
}
if (GetBit(filterTrace.Buffer[0], 3) == 1)
{
if (MouseButton[0] == 0)
{
WinAPI.mouse_event(MOUSEEVENTF_XDOWN, Native.MouseOffset.X,
Native.MouseOffset.Y, 0x0001, 0);
}
MouseButton[3] = 1;
}
else if (MouseButton[3] == 1)
{
WinAPI.mouse_event(MOUSEEVENTF_XUP, Native.MouseOffset.X,
Native.MouseOffset.Y, 0x0001, 0);
MouseButton[3] = 0;
}
if (GetBit(filterTrace.Buffer[0], 4) == 1)
{
if (MouseButton[0] == 0)
{
WinAPI.mouse_event(MOUSEEVENTF_XDOWN, Native.MouseOffset.X,
Native.MouseOffset.Y, 0x0002, 0);
}
MouseButton[4] = 1;
}
else if (MouseButton[4] == 1)
{
WinAPI.mouse_event(MOUSEEVENTF_XUP, Native.MouseOffset.X,
Native.MouseOffset.Y, 0x0002, 0);
MouseButton[4] = 0;
}
if (filterTrace.Buffer[6] == 0x01)
{
WinAPI.mouse_event(MOUSEEVENTF_WHEEL, 0, 0, 120, 0);
}
else if (filterTrace.Buffer[6] == 0xFF)
{
WinAPI.mouse_event(MOUSEEVENTF_WHEEL, 0, 0, -120, 0);
}
}
}
Byte GetBit(Byte b, Int32 bitNumber)
{
BitArray ba = new BitArray(new Byte[] { b });
return Convert.ToByte(ba.Get(bitNumber));
}
}
filterTrace.Buffer
contains the HID packets of the mouse and the if()
chain is used to parse the packets and do actions according to what I receive.
The rest of the code is just the code of BusDog
that I didn't write, so I cannot explain well to you how it works.
But here's the main code of that program:
void TraceBufRead()
{
var devIO = new DeviceIOCTL(busdogPath, true);
while (true)
{
UInt32 bytesReturned;
devIO.DeviceIoControl(IOCTL_BUSDOG_GET_BUFFER, IntPtr.Zero, 0,
outBuffer, outBufferSize, out bytesReturned);
if (MouseOffset == MousePitchYaw)
{
while (true)
{
if (devIO.WaitForOverlappedIo(500, out bytesReturned))
{
break;
}
}
}
FilterTraceArrived(this, new FilterTraceArrivedEventArgs(GetTraceList(outBuffer, outBufferSize, bytesReturned)));
MousePitchYaw = InterpTo(MouseOffset, MousePitchYaw, MouseSmoothingValue);
Cursor.Position = new Point(MousePitchYaw.X + Cursor.Position.X,
MousePitchYaw.Y + Cursor.Position.Y);
Thread.Sleep(10);
}
}
FilterTraceArrived
function is where the loop gather mouse coordinate through HID packets.
if (MouseOffset == MousePitchYaw)
line is where the loop waits for mouse movement.
Points of Interest
Mathematic equations are interesting if we can found an application
Conclusion
Mouse smoothing adds a new perspective when playing video games, a new way to play.
History
- 30th September, 2019: Initial version
- 29th November, 2021: Update, made the tuto easier and the code as well
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.