Paul is quite right. Port 201 joystick read routines work by issuing an
OUT to port 0x201, and then sit in a tight loop performing IN's on this
port, looking for each axis' bit value to change. Simplistic port 201
routines just count the number of INs it takes for each axis to change. A
slightly more sophisticated port 201 joystick reader will also disable
interrupts during the read. Servicing interrupts during the read can lead
to jumpy reads, so disabling interrupts is essential if you want your reads
to be accurate. Up until the Rendition version of IndyCar Racing, Papyrus'
joystick reader "counted the INs", and disabled interrupts.
Unfortunately, the "counting the INs" method works poorly when there are
bus mastering devices active in the system. Such devices (I bet you can
guess one) can stall the processor, leading to intermittently lower "IN"
counts than would be appropriate, and thus jumpy joystick reads. There's
nothing we can do about a bus mastering card stealing cycles away from the
CPU, so if we "count the INs" we'll have dicey reads.
"Counting the INs" can also work rather poorly when the serial port is
active if you haven't disabled interrupts, since the serial port interrupts
will intermittently skew the IN count lower than it should be. You can
disable interrupts during the joystick read, but this can cause loss of
incoming data, and poor outgoing throughput on the serial port. Unless, of
course, you put two-and-two together, and service the serial port directly
while you have interrupts disabled. In the good old DOS days our joystick
read routine did exactly that. It would disable interrupts, and it would
service the serial port(s) in its loop. This gave us lossless incoming and
kick-ass outgoing serial port throughput (_without_ a 16550 UART!), and
accurate joystick reads.
Unfortunately, this doesn't work unless you run the game by rebooting the
machine into exclusive DOS mode (Windows "virtualizes" our request to
disable interrupts - by not disabling them.) If we wanted to allow our
NASCAR Racing 2 customers to play two- or multi-player games through a
serial port while in Windows, and we wanted reasonably smooth joystick
reads, we couldn't use the "counting the INs" method.
So we abandoned "counting the INs" in favor of a more accurate method of
measuring the passage of time. My guess is that these VxD's don't "reset
the bits when an appropriate decay time has been reached", but, instead,
reset the bits when some number of INs have been performed. So all the
jumpiness we eliminated, these VxD's put right back in.
Randy