add directory study

This commit is contained in:
gohigh
2024-02-19 00:25:23 -05:00
parent b1306b38b1
commit f3774e2f8c
4001 changed files with 2285787 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
Instructions for putting FCS handle on CH Flightstick base
----------------------------------------------------------
Here's a quick file to explain the procedure for taking a Thrustmaster
Flight Control Stick and mounting it on a CH Flightstick base, while
keeping all FCS button and hat functions (and only losing the throttle
wheel on the CH base.)
You'll need a small phillips head screwdriver, a pair of wire-cutters,
a pair of wire-strippers, electrical tape, and a T-10 star screwdriver
(or similarly sized allen wrench)
First, remove the bottoms of both bases. Look at the internals.
You'll see that the potentiomenter layouts for both sticks are very
similar. The key to doing this whole procedure is removing the cable
from the FCS and installing it in the CH base. In the Ch, you have 3
wires that connect the pots (1 black, 1 blue, 1 tan) There is also a
yellow wire that goes to the throttle wheel pot (the blue wire also
goes to this pot as well) Ignore the throttle wheel pot as it won't
work after the procedure (it uses the same pin assignments in the plug
as the 4-way switch).
Cut the Black, blue, and tan wires that go to the cable. Cut the
wires leading up to the CH handle triggers. Cut the yellow wire leading
to the throttle wheel pot. Now, remove the cable from the base. On the
FCS, there are also three wires for the pots...a black wire, a white
wire, and a tan wire. There is also a gray wire connecting the pots
together in the FCS, but you can ignore this wire completely (the pots
in the CH are connected already by part of the blue wire) Cut the white,
tan, and black wires leading to the FCS cable. Cut the wires leading up
into the handle of the FCS, making sure to leave plenty of extra wire on
either end as you'll be connecting them right back together.
Now, remove the FCS cable from the base. Unscrew the CH stick handle
screws and remove the handle from the shaft. Notice that there is a small
pilot hole on the shaft. This is important as it allows the FCS stick
to fasten to the CH shaft. Unscrew the FCS stick screws and remove the
free half of the handle. The other half is screwed to the shaft via a
similar pilot hole. (At this point, use great care with the FCS stick...
the buttons and solder joints are extremely fragile and break easily.)
Unscrew the other half of the handle from the FCS shaft. Use the screw
to open the small pilot hole in the CH shaft...then connect the handle
to the shaft using the screw. Thread the wires from the handle back
down the CH shaft, then screw the other half of the FCS handle on to
the assembly.
Well, you're almost done!! Now, take the FCS cable and connect the pot
wires as follows...
FCS Cable Ch Base and pots
Black wire to Black wire
White wire to Tan Wire
Tan Wire to Blue Wire
Now just reconnect the FCS handle wires to the cable wires, slip the
cable stop into the space provided in the base, and button her up!!
Then just check the stick out using any program that takes advantage
of the FCS features (I use AOTP to benchtest my stick...it was a dog
with the FCS, but very sprightly with the CH stick...now it has the
best of each!)
If you have any questions or problems with this procedure, contact
me through CI$ Mail at Account Number 70761,1103. Hope it works as
well for you as it did for me. Good luck!!
********************************NOTE**************************************
I downloaded this file from Compuserve because of the problems I experienced
with the Thrustmaster Flight Control System. I have since converted my FCS to
my old CH Flightstick base and have had NO problems since doing this. The only
real problem I found was that the person that wrote this left his number only,
and not his name. This makes it very hard to contact someone to find out how
well it worked. Well you can contact me, Albert Lowe, here on the MPSBBS, or
through Compuserve at 73233,2455. If you need help. I must stress that you
shouldn't try this unless you have a good dexterity and have worked with
electrical wiring before. If you want this done, but don't think you can do it,
get someone that you think can.
Good Luck,
Albert Lowe

View File

@@ -0,0 +1,108 @@
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<20> Programming the Gravis GamePad and Analog Pro <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> Disclaimer <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
I assume no responsibility whatsoever for any effect that this file, the
information contained therein or the use thereof has on you, your sanity,
computer, spouse, children, pets or anything else related to you or your
existance. No warranty is provided nor implied with this information.
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> Programming the Gravis GamePad <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
The Gravis GamePad plugs into the standard joystick connector. It is
a pad with a 9 direction controller (including center) and four buttons.
Two of the buttons can be selected as "autofire" by a switch on the
GamePad.
_____ ||
| \____||________
| __ GRAVIS \
| / \ GamePad B |
| \__/ A C|
|______________ D |
\_____|
The chief difference between the GamePad and a regular joystick is that
the GamePad uses fixed resistances of about 0<>, 50k<30> and 100k<30>. The
resistances for each controller position are as follows:
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<20> x = 0<> <20> x = 50<35> <20> x = 100<30> <20>
<20> y = 0<> <20> y = 0<> <20> y = 0<> <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ
<20> x = 0<> <20> x = 50<35> <20> x = 100<30> <20>
<20> y = 50k<30> <20> y = 50<35> <20> y = 50<35> <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ
<20> x = 0<> <20> x = 50<35> <20> x = 100<30> <20>
<20> y = 100<30> <20> y = 100<30> <20> y = 100<30> <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
The x axis is read via the regular Joystick A X Axis, the y axis is read
via the Joystick A Y Axis.
The GamePad buttons are accessed the same way that the normal joystick
buttons are accessed:
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<EFBFBD> GamePad Button A = Joystick A, Button 1 <20>
<EFBFBD> GamePad Button B = Joystick A, Button 2 <20>
<EFBFBD> GamePad Button C (autofire A) = Joystick B, Button 2 <20>
<EFBFBD> GamePad Button D (autofire B) = Joystick B, Button 1 <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> Programming the Gravis Analog Pro <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
The Analog Pro is very similar to a regular joystick, except it has 5
buttons and a dial on the joystick, originally intended for use as a
throttle for flight simulators.
-- B & A
___
C -> \ |
||
D - || - E
_<>_||_<>_
|______|
Left Side
The Analog Pro joystick position is read the same as the regular Joystick A.
The throttle value is read the same as for the regular Joystick B X Axis
value.
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<20> Analog Pro Button A = Joystick A, Button 1 <20>
<20> Analog Pro Button B = Joystick A, Button 2 <20>
<20> Analog Pro Button C = Joystick B, Button 1 <20>
<20> Analog Pro Button D = Joystick B, Button 2 <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
The SDK is a bit vague as to how button E is read. It mentions that the
buttons D and E can be set as any of the joystick buttons, but I believe
this is done via switches on the joystick itself (not sure, I don't actually
own one).
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> References <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
All the information in this file was obtained from the PC GamePad and Analog
Pro SDK V1.1 which can be obtained via anonymous ftp:
site: wasp.eng.ufl.edu
directory: /pub/msdos/demos/programming/source
filename: joysdk11.lzh

View File

@@ -0,0 +1,252 @@
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<20> Programming the PC Joystick <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> Programming Info <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
All joystick programming is done via port 201h.
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<20> 7 <20> 6 <20> 5 <20> 4 <20> 3 <20> 2 <20> 1 <20> 0 <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<20> <20> <20> <20> <20> <20> <20> <20>
Joystick B, Button 2 <20><><EFBFBD><EFBFBD> <20> <20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD> Joystick A, X Axis
Joystick B, Button 1 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Joystick A, Y Axis
Joystick A, Button 2 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Joystick B, X Axis
Joystick A, Button 1 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Joystick B, Y Axis
Reading the status of the joystick buttons is fairly simple. Just read the
byte from the joystick port and check the status of the appropriate bit. A
clear bit (0) means the button is pressed, a set bit (1) means it is not
pressed. Note that the button's are not hardware debounced. Each time a
button is pressed it's bit may "bounce" between 0 and 1 a couple of times.
Reading the position of the stick positions is a bit more complicated. You
must first write a dummy byte (any value will do) to the joystick port. This
will set each axis bit to 1. You must then time how long the bit takes to
drop back to 0, this time is roughly proportional to the position of
the joystick axis (see Steve McGowan's discussion below).
AT computers also have a BIOS call which supports the joystick. I have come
across numerous machines which apparently did not support this call. My own
machine supports reading the joystick buttons apparently can't read the
stick position values, so I do not advise using this call for any serious
games. In any case here is info on the call:
Joystick Support BIOS Call
Int 15h
To call:
AH = 84h
DX = 00h Read switch settings
01h Read joystick position
Returns:
PC, PCjr : Carry flag set, AH = 80h
PC XT : Carry flag set, AH = 86h
All others : DX = 00h on calling
AL = Switch settings (bits 4 - 7)
Carry flag set on error
DX = 01h on calling
AX = A(X) value
BX = A(Y) value
CX = B(X) value
DX = B(Y) value
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> Hardware Pinout <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
The joystick connects to a 15 pin female plug :
__________________________
\ 8 7 6 5 4 3 2 1 /
\ 9 10 11 12 13 14 15 /
----------------------
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<20> Pin # Joystick <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ
<20> 1 +5v <20>
<20> 2 Joystick A, Button 1 <20>
<20> 3 Joystick A, X Axis <20>
<20> 4 Gnd <20>
<20> 5 Gnd <20>
<20> 6 Joystick A, Y Axis <20>
<20> 7 Joystick A, Button 2 <20>
<20> 8 +5v <20>
<20> 9 +5v <20>
<20> 10 Joystick B, Button 1 <20>
<20> 11 Joystick B, X Axis <20>
<20> 12 Gnd <20>
<20> 13 Joystick B, Y Axis <20>
<20> 14 Joystick B, Button 2 <20>
<20> 15 +5v <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> Misc notes on Joystick handling by Steve McGowan <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
With a polling loop on a 486-66 I got x/y values between 8 and 980. When
I centered the stick the value was usually a value around 330.
NOTE: a Gravis Game Pad it only put out 3 values, 8(min), 330(center),
and 980(max). Every joystick I have tried has been non-linear.
The "speed compensation" that some games require is due to the fact that
the game designer did not anticipate the range of values that could
come back on faster machines. On a 486-25 you may see max values of 360,
I saw 980, on a Pentium the max value could be well over 2000. If you
had used a unsigned byte value you probably would have been in good
shape on an AT, or 386 but you would be in big trouble with faster machines.
Because the joystick logic returns a non linear value, if you base your
scaling only on the 4 corners then the center will be off (biased towards
a corner). If you just use the center value and a single scaling factor
(i.e. of the center is at 330 then full throw should be at 660), then the
stick will saturate (660) half way to the full throw position (980).
That is why most joystick setup programs make the distinction between
hitting the 4 corners and centering the stick.
Joystick position vs. loop count
x,y--------------------
8,8| 330,8 | 980,8
| |
| | delta 330
| |
8,330| 330,330 | 980,330 (y centered)
| |
| | delta 650
| |
8,980| 330,980 | 980,980
--------------------
(x centered)
For the best effect you basically need 2 scale factors, depending on whether
you are above or below the center value. I think the curve is actually an
exponential (charging capacitor) but a straight line approximation should
do fine.
The 10% dead zone in the center is a good idea. The centering mechanism of
joysticks vary in repeatablity, they don't always come back to the same place.
I have a cheap one that (1 time in 8) does not return to the X center if I
just let it snap to center. It hangs on the high side.
I would recommend disabling interrupts while polling. An interrupt
in the middle of your polling loop will really throw off the results. And
any DMA that takes place will also give you bad values.
Joysticks are noisy, so holding the stick in a fixed position will return
values that vary +-5% easily. I added a smoothing function to my joystick
code where I throw away single values that are not continuous. It helped
a lot with the noise and the DMA.
I use protected mode and the interrupt disable() call doesn't actually work
because it only disables interrupts for the process not the processor.
The smoothing trick can help here too.
If I turn on my machine and start the polling loop immediately, it will
put out a centered value of 330,330 but after warming up for 10 minutes
the value changes to 285,285. This variance also needs to be absorbed in
your center dead zone. If after warming up the 'center' value is outside your
dead zone then the cursor will drift (to the left and/or up). Make
sure your game has a "center joystick" command to get around joystick
interfaces with lousy temperature compensation.
You must wait for all of the axis bits to settle before initiating
another read, otherwise strange results may come out. So, instead of
reading X, then Y, in two separate loops (which take twice as much time)
Read both X and Y simultaneously, polling until both bits settle. This
can be extended for two joysticks, assuming that they are both attached.
The respective X/Y bits never come true if there is no joystick attached.
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> A Simple Demo Joystick Unit <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
JOY.PAS - By Mark Feldman
e-mail address : u914097@student.canberra.edu.au
myndale@cairo.anu.edu.au
A simple Pascal Joystick Unit.
}
unit Joy;
Interface
{ Define constants for use as JoystickButton and JoystickPosition parameters }
const JoystickAButton1 = $10;
JoystickAButton2 = $20;
JoystickBButton1 = $40;
JoystickBButton2 = $80;
JoystickAAxisX = $01;
JoystickAAxisY = $02;
JoystickBAxisX = $04;
JoystickBAxisY = $08;
function JoystickButton(buttonnum : byte) : boolean;
function JoystickPosition(axisnum : byte) : word;
Implementation
const JOYSTICKPORT = $201;
{ Button returns true is button is pressed }
function JoystickButton(buttonnum : byte) : boolean;
begin
JoystickButton := (Port[JOYSTICKPORT] and buttonnum) = 0;
end;
{ Returns position value of joystick. The value returned is highly
dependent on machine speed. Changing the setting of the computer's
Turbo speed button will affect the value returned.
Returns $FFFF if the joystick is not connected
}
function JoystickPosition(axisnum : byte) : word;
var count : word;
begin
asm
mov word ptr count, 0
cli { Disable interrupts so they don't interfere with timing }
mov dx, JOYSTICKPORT { Write dummy byte to joystick port }
out dx, al
@joystickloop:
inc count { Add one to count }
cmp count, $FFFF { Check for time out }
je @done
in al, dx { Get joystick port value }
and al, axisnum { Test the appropriate bit }
jne @joystickloop
@done:
sti { Enable interrupts again }
end;
JoystickPosition := count;
end;
end.
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> References <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Title : Flights of Fantasy
Author : Christopher Lampton
Publishers : The Waite Group
ISBN : 1-878739-18-2
Title : DOS and BIOS Functions Quick Reference
Publishers : Que Corporation
ISBN : 0-88022-426-6

View File

@@ -0,0 +1,296 @@
The Keyboard Interface Tutorial
Preface:
The Keyboard on the IBM PC and compatible is connected to the PPI -
Programmable Peripheral Interface, which generally takes care of Keyboard
functions, equipment information and timer functions. The PPI is addressable
via port reads and writes, to addresses 060h thru 063h.
There are several type of keyboards available. The main difference between the
various types is the key count. Existing sizez are:
83 Key (Original PC)
84 Key (XT and clones)
101 Key (Usually on AT's and up, called Enhanced Keyboard)
In addition to those standard types, there are numerous non-standard types,
which varry from manufacturer to manufacturer. There are 102 Key keyboards,
keyboards with two F-Key sets (upper and left), keyboards with weird
hardly-used keys like 'Macro' and 'Turbo' (which DO have a scan code, though)
etcetera.
The IBM AT and up provides a better way of negotiating the keyboard, by
allowing the user to directly access and command the keyboard, as it will be
demonstrated later.
Using assembly language, there are two major ways to handle the keyboard and
keystrokes:
1. Using DOS functions:
DOS provides a useful set of functions to use in context with the keyboard.
This includes one-key-input and string input.
2. Using BIOS interrupts:
The IBM PC BIOS (Basic Input Output System) provides an interrupt to handle
the keyboard - Interrupt 016h (022d). These functions, titles KEYBOARD I/O,
are an efficient medium level way of using the keyboard
In addition to the Interrupt 016h interface, there is the Keyboard
Interrupt, Interrupt 009h. As opposed to the other interrupt, Interrupt
009h is an IRQ - Interrupt Request, which means that it is never called by
software. Only hardware, when certain conditions are met, calls IRQ
interrupts. Naturally, the user is able to invoke them himself, but that is
not commonly done.
3. Direct port access:
It is possible to access the keyboard using direct port reads and writes.
As mentioned before, this is usually done by addressing the PPI. On AT's
and up, however, it is possible to directly access the keyboard itself.
The BIOS also supplies a certain amount of information about the keyboard
within it's BDA - BIOS Data Area, aka BDS - BIOS Data Segment - which is the
segment that lies at paragraph 040h (0040h:XXXXh or 0000h:04XXh):
Address Size Contents
------- ---- --------
0:0412 1 Errors in PCjr InfraRed keyboard link
0:0417 2 Keyboard status bits. See Keyboard Flags
0:0419 1 Current (accumulating) value of Alt+numpad pseudo-key input.
Normally 0. When [Alt] is released, value is stored in kbd buf.
0:041A 2 Address of keyboard buffer head (keystroke at that addr is next)
0:041C 2 Address of keyboard buffer tail
0:041E 32 Keyboard buffer. BIOS stores keystrokes here (head and tail
point to addresses from 041Eh to 043Dh inclusive).
0:0480 2 AT PS/2 Keyboard buffer offset start address (usually 01Eh)
0:0482 2 end address (usually 03Eh)
0:0496 1 AT Keyboard flag bit 4=1 (10h) if 101-key keyboard is attached
0:0497 1 AT Keyboard flag for LED 'key lock' display
bits 0-2 are ScrollLock, NumLock, CapsLock respectively
******************************************************************************
Using DOS functions:
--------------------
DOS provides a set of 7 functions to handle the keyboard:
01h Keyboard Input
06h Console I/O
07h No Echo Unfiltered Input
08h No Echo Filtered Input
0Ah Buffered Input
0Bh Input Status
0Ch Clear Keyboard Buffer & Input
In addition to these functions, it is also possible to read a selected amount
of characters from the keyboard, using DOS's File Handle functions, as the
Keyboard, aka Standard Input, has a pre-set handle of 0000h:
DOS Fn 3Fh: Read from keyboard via Handle
------------------------------------------------------------------------------
/-----------------------------------------------------------------\
| Expects | AH | 3Fh |
\---------| BX | 0000h - Handle for Standard Input (Keyboard) |
| DS:DX | Address of buffer to receive data |
| CX | Number of bytes to read |
/---------|-------|-----------------------------------------------|
| Returns | AX | Error code if CF is set to CY |
\---------| AX | Number of bytes actually read |
\-------------------------------------------------------/
Description: CX bytes of data are read from the keyboard. The data is placed
into the caller's buffer pointed to by DS:DX.
Notes: It is handy to use this function for reading default handles
such as the Standard I/O handles, instead of the buffered input
or character-by-character input functions.
When you read from a device, AX returns the length of the line
up to and including the termination CR (ASCII 13h).
******************************************************************************
Using BIOS Interrupts:
----------------------
As mentioned before, there are two ways to use interrupts to access the
keyboard.
The first is Interrupt 016h - Keyboard I/O.
INT 16h: Keyboard Services
------------------------------------------------------------------------------
This is the application-level interface to the keyboard. Keystrokes are
actually processed asynchronously in the background. As each keystroke is
received from the keyboard, it is processed by INT 09h and placed into a
circular queue.
The second is Interrupt 009h - Keyboard Interrupt, IRQ 1
INT 09h: Keyboard Interrupt
------------------------------------------------------------------------------
This hardware-generated interrupt (IRQ 1) is executed upon each press and
release of a key. The ROM-BIOS code interprets the keystroke, storing values
into the keyboard buffer at 40:1Eh. It also handles the special cases of the
PrtSc and SysReq keys, and tracks the status of the shift and case-lock keys.
See: INT 16h .......... BIOS service to access the keys stored in the buffer
and obtain status of the certain shift keys.
Scan Codes ....... a list of the values of each possible keystroke as
it is received by INT 09h.
Extended ASCII ... for a summary of the values that BIOS stores into the
the keyboard buffer after it translates a scan code.
Keyboard Flags ... for a summary of how to obtain, test for, and modify
the bit-settings of shift and case-lock flags.
TSRs (RAM-resident programs) that have a hot-key to trigger a popup usually
intercept INT 09h and test for a certain key with a sequence such as this:
push ax
in al,60h ; Read the key
cmp al,POP_KEY ; Is this the hot key?
je do_pop ; Yes, trigger the popup
; No, drop through to original driver
pop ax
jmp cs:[int9_vect] ; Just hop out to original int handler
do_pop: ;------ the following housekeeping is needed to satisfy the hdwr int
in al,61h ; Get value of keyboard control lines
mov ah,al ; Save it
or al,80h ; Set the "enable kbd" bit
out 61h,al ; And write it out the control port
xchg ah,al ; Fetch the original control port value
out 61h,al ; And write it back
mov al,20h ; Send End-Of-Interrupt signal
out 20h,al ; to the 8259 Interrupt Controller
;------ other code handles other tests and finally the popup code
******************************************************************************
Direct port access:
-------------------
The keyboard is addressable in two manners.
The first, available on all IBM PCs of all types, is by addressing the PPI -
Programmable Peripheral Interface.
Port Description
---- -----------
060h PC/XT PPI port A. Read keyboard scan code:
IN al,60h ; Fetche most recent scan code. See INT 09h and Scan Code
AT keyboard data register. See AT Keyboard
061h PC/XT PPI (Programmable Peripheral Interface) port B.
7 6 5 4 3 2 1 0
| | | | | | | |
| | | | | | | \-> 0: Timer 2 gate (speaker) --/--> OR 03h=speaker ON
| | | | | | \---> 1: Timer 2 data ---------/ AND 0FCh=speaker OFF
| | | | | \-----> 2: Always 0
| | | | \-------> 3: 1=Read high switches; 0=read low switches(see 62h)
| | | \---------> 4: 0=Enable RAM parity checking; 1=disable
| | \-----------> 5: 0=Enable I/O channel check
| \-------------> 6: 0=Hold keyboard clock low
\---------------> 7: 0=Enable keyboard; 1=disable keyboard
------------------------------------------------------------------------------
The second, available only on IBM PC/ATs and up, is by directly commanding the
keyboard itself. -= This is for the AT keyboard only. =-
Port Description
---- -----------
064h AT keyboard command register. This port communicates with the 8042
which runs an on-chip control program for the keyboard. It accepts
command codes and data bytes.
The keyboard of the AT (and its Intel 8042 microcomputer interface) is
programmable and a lot more interesting than the old-style PC keyboards.
Using the information below, you can set the key repeat speed and play
games with the "lock" key LED display.
Note: This is not a comprehensive coverage of the details of keyboard and
8042 operation, but it should provide some food for thought.
Port 60h is for writing data and is maintained for compatibility with
earlier models. If the examples using port 64h don't work, try using 60h.
Port 64h is for writing commands and data and for reading keyboard status.
Before sending a command to the keyboard, the BIOS tests its status
(IN al,64h) and makes sure a key isn't being pressed or the internal buffer
isn't full, etc. There's a small risk if you just go ahead and send the
command:
mov al,cmd_code
out 64h,al
For a two-part command such as setting the typeamatic rate, it's wise to
delay a little while between OUTs:
mov al,cmd_code
out 64h,al
mov cx,2000h ;arbitrary <20> 10ms+
delay: loop delay
mov al,data_value
out 64h,al
Cmd Description
--- -----------
0FFh Reset the keyboard and start internal diagnostics
0FEh Resend the last transmission
0FDh-0F7h (NOP)
0F6h Set keyboard to defaults and continue scanning
0F5h Set keyboard to defaults and disable keyboard scanning
0F4h Enable the keyboard. Kybd sends 'ACK', clears buffer, and starts scanning
0F3h Set typeamatic rate and delay. First send 0F3h, then send data byte:
-7-6-5-4-3-2-1-0-
|0|dly|rept rate|
-----------------
| | | \---------> bits 0-4 set the repeat rate (see below)
| \-------------> bits 5-6 set initial delay before first repeat:
| 00=250ms; 01=500ms; 10=750ms; 11=1000ms
\---------------> bit 7 is always 0
Value Rate Value Rate
This chart is a partial guide for the repeat 0 = 30.0 0Ah = 10.0
rate (bits 0-4). You can interpolate for 1 = 26.7 0Dh = 9.2
values not shown, but let's face it, you're 2 = 24.0 10h = 7.5
only interested in the fastest rates. 4 = 20.0 14h = 5.0
8 = 15.0 1Fh = 2.0
The keyboard is initially set to begin repeating after 1/2-second and
repeat at a rate of 10 repeats per second. This is much too slow. A
data byte of 01h sets the delay to 1/4-second with 26 repeats per second.
0F2h-0EFh (NOP)
0EEh Echo. Diagnostics aid. Simply sends 0EEh right back.
0EDh Turn LED 'lock key' lights on or off. First send 0EDh, then send byte:
-7-6-5-4-3-2-1-0-
| not used|c|n|s|
-----------|-|-|-
| | \-> ScrollLock light 01h=turn on
| \---> NumLock light 02h=turn on
\-----> CapsLock light 04h=turn on
The bit positions 0-3 correspond to bits 4-6 of the keyboard flags
variable in the BIOS Data area. You should make an effort to keep the
flags in sync with the lights. For instance, if you do a big favor for
the user and set his ten-key pad into NumLock mode (by setting bit 5 of
0:0417h) then be sure to turn on the corresponding LED (eg, bit 1).

View File

@@ -0,0 +1,286 @@
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<20> Programming the Microsoft Mouse <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> Disclaimer <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
I assume no responsibility whatsoever for any effect that this file, the
information contained therein or the use thereof has on you, your sanity,
computer, spouse, children, pets or anything else related to you or your
existance. No warranty is provided nor implied with this information.
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> Introduction <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
A complete list of mouse function calls can be found in the file GMOUSE.TXT,
the file contains calls for both Microsoft (2 button) and Genius (3 button)
modes.
Calling these functions from within a Pascal program is a fairly simple
matter. This procedure would get the mouse position and button states:
const MOUSEINTR = $33;
procedure GetMousePos(var x, y : word; var button1, button2 : boolean);
var regs : registers;
begin
regs.ax := 3;
Intr(MOUSEINTR, regs);
x := regs.cx;
y := regs.dx;
button1 := (regs.bx and 1) <> 0;
button2 := (regs.bx and 2) <> 0;
end;
The mouse position is returned in variables x and y, the button states are
returned in variable button1 and button2 (true = button is pressed).
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> Writing Custom Handlers <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Most mouse drivers do not support SVGA modes, so you must write custom
handlers if you want mouse support for these modes.
Rather than writing an entire mouse driver, you can write a simple handler
routine to take care of the graphics and tell the mouse driver to call it
whenever the mouse does anything. This function is descibed in the GMOUSE.DOC
file, but this demo Pascal program shows the general idea. It sets mode 13h,
resets the mouse and waits for a key to be pressed. Whenever you do anything
to the mouse (moving it or pressing a button) the handler will get called
and it will draw a pixel on the screen. The color of the pixel depends on
which buttons are being pressed.
Uses Crt, Dos;
{$F+}
{ called with bl = buttons, cx = x * 2, dx = y }
procedure Handler; far; assembler;
asm
{ This mouse "handler" just draws a pixel at the current mouse pos }
pusha
mov ax, $A000
mov es, ax
shr cx, 1
xchg dh, dl
mov di, dx
shr dx, 2
add di, dx
add di, cx
mov al, bl
inc al
stosb
popa
end;
{$F-}
begin
asm
{ Set graphics mode 13h }
mov ax, $13
int $10
{ Initialize mouse driver }
xor ax, ax
int $33
{ Install custom handler }
mov ax, SEG Handler
mov es, ax
mov dx, OFS Handler
mov ax, 12
mov cx, $1F
int $33
{ Wait for a key press }
xor ah, ah
int $16
{ Back to text mode }
mov ax, 3
int $10
end;
end.
Alternatively you may wish to write your own interrupt handler to process
mouse events as they happen. When a mouse event occurs, 3 interrupts are
generated and the bytes are availble via the COM port.
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<20> Interrupt Port <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ
<20> COM1 $0C $3F8 <20>
<20> COM2 $0B $3F8 <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
The three bytes sent are formatted as follows:
1st byte 2nd byte 3rd byte
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<20>-<2D>1<EFBFBD>?<3F>?<3F>X<EFBFBD>X<EFBFBD>Y<EFBFBD>Y<EFBFBD><59>-<2D>0<EFBFBD>X<EFBFBD>X<EFBFBD>X<EFBFBD>X<EFBFBD>X<EFBFBD>X<EFBFBD><58>-<2D>0<EFBFBD>Y<EFBFBD>Y<EFBFBD>Y<EFBFBD>Y<EFBFBD>Y<EFBFBD>Y<EFBFBD>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<20> <20> <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<20> <20> <20> <20> <20> <20>
<20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ <20>
<20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ <20> <20> <20>
<20> <20> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20><> <20> <20> <20> <20> <20> <20> <20> <20>
Left Button <20><><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Right Button <20><><EFBFBD><EFBFBD><EFBFBD> X increment Y increment
The X and Y increment values are in 2's compliment signed char format. (BTW
thanks go to Adam Seychell for posting this info to comp.os.msdos.programmer).
A simple Borland Pascal 7.0 mouse handler follows. First we declare a few
things we'll need:
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
Uses Crt, Dos;
{$F+}
const COM1INTR = $0C;
COM1PORT = $3F8;
var bytenum : word;
combytes : array[0..2] of byte;
x, y : longint;
button1, button2 : boolean;
MouseHandler : procedure;
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
The bytenum variable is used to keep track of which byte is expected next
(ie 0, 1 or 2). The combytes variable is simply an array to keep track of
bytes received so far. The mouse position will be stored in the x and y
varaibles (note that this example will not perfrom any range checking).
Button1 and button2 will be used to store the states of each of the buttons.
MouseHandler will be used to store the normal mouse driver event handler.
We'll need it to reset everything once we are finished.
Here's the actual handler:
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
procedure MyMouseHandler; Interrupt;
var dx, dy : integer;
var inbyte : byte;
begin
{ Get the port byte }
inbyte := Port[COM1PORT];
{ Make sure we are properly "synched" }
if (inbyte and 64) = 64 then bytenum := 0;
{ Store the byte and adjust bytenum }
combytes[bytenum] := inbyte;
inc(bytenum);
{ Have we received all 3 bytes? }
if bytenum = 3 then
begin
{ Yes, so process them }
dx := (combytes[0] and 3) shl 6 + combytes[1];
dy := (combytes[0] and 12) shl 4 + combytes[2];
if dx >= 128 then dx := dx - 256;
if dy >= 128 then dy := dy - 256;
x := x + dx;
y := y + dy;
button1 := (combytes[0] And 32) <> 0;
button2 := (combytes[0] And 16) <> 0;
{ And start on first byte again }
bytenum := 0;
end;
{ Acknowledge the interrupt }
Port[$20] := $20;
end;
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Once again pretty simple stuff. We just read the byte from the com1 port and
figure out if it's time to do anything yet. If bit 6 is set to 1 then we
know that it's meant to be the first byte of the 3, so we reset our
bytenum variable to zero (in a perfect world bytes would always come in 3's
and we would never need to check, but it never hurts to be careful).
When 3 bytes have been received we simple decode them according to the
diagram above and update the appropriate variables accordingly.
The 'Port[$20] := $20;' command just lets the interrupt controller know we
have processed the interrupt so it can send us the next one when it wants to.
Note that the above "handler" does nothing more than keep track of the
current mouse position and button states. If we were writing a proper mouse
driver for an SVGA game we would also have to write custom cursor routines.
I'll leave that bit to you!
To actually install our mouse driver we'll have to set up all the variables,
save the address of the current mouse handler and install our own. We'll
also need call the existing mouse driver to set up the COM1 port to make
sure it sends us the mouse bytes as it receives them. We could do this
ourselves, but why make life harder than it already is?
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
procedure InitMyDriver;
begin
{ Initialize the normal mouse handler }
asm
mov ax, 0
int $33
end;
{ Initialize some of the variables we'll be using }
bytenum := 0;
x := 0;
y := 0;
button1 := false;
button2 := false;
{ Save the current mouse handler and set up our own }
GetIntVec(COM1INTR, @MouseHandler);
SetIntVec(COM1INTR, Addr(MyMouseHandler));
end;
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
And finally when our program is finished it'll need to clean up after
itself and return control back to the normal mouse driver:
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
procedure CleanUpMyDriver;
begin
SetIntVec(COM1INTR, @MouseHandler);
end;
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
This little bit of source will test the above code. It does nothing more
than repeatedly write the mouse position and button states to the screen
until a keyboard key is pressed:
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
begin
ClrScr;
InitMyDriver;
while not keypressed do
WriteLn(x : 5, y : 5, button1 : 7, button2 : 7);
CleanUpMyDriver;
end.
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
<html>
<head>
<meta http-equiv="refresh" content="0;url=/Linux.old/sabre/os/articles">
</head>
<body lang="zh-CN">
</body>
</html>

View File

@@ -0,0 +1,86 @@
From: s152226@proffa.cc.tut.fi (Saastamoinen Vesa)
Subject: Joystikin salat
Newsgroups: sfnet.harrastus.elektroniikka
Date: 20 May 1996 18:54:59 GMT
Organization: Tampere University of Technology, Computing Centre
Joystick port .-----------------------.
\ 8 7 6 5 4 3 2 1 /
\ 9 10 11 12 13 14 15 /
~~~~~~~~~~~~~~~~~~~
Pin Function Pin Function
1 +5v 9 +5v (SB midi)
2 Joy A, Button 1 10 Joy B, Button 1 (multibutton 3)
3 Joy A, Direction X 11 Joy B, Direction X
4 Gnd 12 Gnd (SB midi)
5 Gnd 13 Joy B, Direction Y
6 Joy A, Direction Y 14 Joy B, Button 2 (multibutton 4)
7 Joy A, Button 2 15 +5v
8 +5v
Each switch grounds the respective pin. X and Y are wired via 100kohm variable
resistor to +5V.
Throttle: Joy B, Direction Y
Pedals: Joy B, Direction X
In order to achieve 2 pedals, connect 2 separate 50kohm variables in series.
50 kohm 50 kohm
GND o------|\/\/\/\|---+---|\/\/\/\|------o +5 V
/_______|_______/
|
Right up equals 50 kohm,
Right down equals 0 kohm,
Left up equals 50 kohm,
Left down equals 0 kohm,
CH Virtualpilot pro and F-16 comp.stick buttons:
A B C D Function
X Button 1
X Button 2
X Button 3
X Button 4
X X Button 5
X X Button 6
X X X X Hat 1 Up
X X X Hat 1 Down
X X X Hat 1 Right
X X Hat 1 Left
X X X Hat 2 Up
X X Hat 2 Down
X X Hat 2 Right
X X Hat 2 Left
Where:
A = switch has connection to Pin 2 trough a diode.
B = switch has connection to Pin 7 trough a diode.
C = switch has connection to Pin 10 trough a diode.
D = switch has connection to Pin 14 trough a diode.
Example: ``Hat 1 Left'' is "A" + "B"
S1 ___ D1
GND o------o o--+----|<|----o Pin 2 (Button 1)
| D2
+----|<|----o Pin 7 (Button 2)
|
V You can use the above for other "Hat 1" buttons
~ as well, by placing a diode here.
Diodes D1,D2: anything you have, e.g. 1N 4002 (for heavy-duty use ;)
[ Ms-Dos 6.22 + OS/2 3.0 = ]
[ Vesa Saastamoinen Varoitus: Koneeni on osittain ]
[ email s152226@cc.tut.fi Mikrosoftin saastuttama ]

View File

@@ -0,0 +1,234 @@
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<20> Programming the Keyboard <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> Disclaimer <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
I assume no responsibility whatsoever for any effect that this file, the
information contained therein or the use thereof has on you, your sanity,
computer, spouse, children, pets or anything else related to you or your
existance. No warranty is provided nor implied with this information.
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> Overview <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
The operation of the keyboard is really quite simple. Every time a key
is pressed or released an interrupt 9 is generated, and reading the value
from port 60h tells you what happened.
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> Decoding the Keyboard Byte <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
So let's say you've installed an interrupt handler to handle all keyboard
events and when an interrupt is generated your handler reads the byte from
port 60h. What now?
Well..each key on the keyboard has an associated scan code which is contained
in the lower 7 bits of the byte. The most significant bit (ie bit 7) tells
you what was actually done, 0 = key was just pressed, 1 = key was just
released. If someone had just pressed the ESC key for instance, the port will
show a value of 1 (1 is the ESC key's scan code). If they hold their finger
on the button the keyboard will keep generating interrupt 9's and each
time the port will still show a value of 1. When the person releases the key
a final interrupt will be generated and the port will return 129 (1 + 128,
since the high bit will be set indicating the person has released the key).
Well...it's almost this simple. Some keys are "extended" keys. When an
extended key is pressed an interrupt is generated and the keyboard port
will return a value of 224 (E0h). This means that an extended key was pressed
and it's *extended* scan code will be available during the *next* interrupt.
Note that the left control key has a scan code of 29, while the *right*
control key has an *extended* scan code of 29. The same applies to the alt
keys and the arrow keys (keypad arrows vs the other ones).
It would be nice if all keys were created equal and we could just throw away
the 224 extended bytes and handle all the other bytes normally. Unfortunately
there are two buttons which on my machine at least (and others I have tested)
do some really weird stuff:
PrtScn
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Pressing this button will send *2* extended characters to the handler, 42
and 55, so the actual byte sequence will be 224, 42, 224, 55. (Also note
that the left shift key has a regular scan code of 42, so there goes our
idea of just throwing 224's away). Only the extended 55's are sent during
auto-repeat. When the key is released, the two are sent again with the high
bits set (224, 170, 224, and 183). If any of the shift or control keys are
being held down when the PrtScn button is pressed then only the (224, 55) is
sent when the key is pressed and only the (224, 183) is sent when it's
released. If the alt key is being held down (System Request) then the key
behaves like an ordinary key with scan code 84. The practical upshot of all
this is that the handlers you write to handle normal keys and extended keys
will work fine with all the different PrtScn combinations (although a program
would have to check normal key 84 *AND* extended key 55 in order to determine
if the key is currently being pressed).
Pause/Break
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Welcome to hell. If you press this key while either of the the control keys
are being held down, it will behave like extended key 70, at all other times
it will send the following bytes: (225, 29, 69, 225, 157, 197). Holding the
key down does not result in autorepeat. Taking your finger off the key does
not send any extra bytes, they appear to be sent after the "key down" bytes
when you first press the key. Notice that 225 isn't 224, so our normal
extended character handler will not take care of this. My personal theory is
that while a scan code of 224 (E0h) means there is 1 more character
following, a scan code of 225 (E1h) means there are *2* more following. I've
seen a number of keyboard handler libraries and they all seem to overlook
this key. So why not be the first kid on your block to have a keyboard
handler which properly supports the Pause/Break key? CHECK IT OUT!!
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> Writing a Handler <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Writing a keyboard handler is fairly straightforward. This section will
show how to do it in Pascal (you C and asm programmers would probably already
know this stuff anyway).
First we'll declare a few things we'll need:
const KEYBOARDINTR = 9;
KEYBOARDPORT = $60;
var BIOSKeyboardHandler : procedure;
CallBIOSHandler : boolean;
The CallBIOSHandler variable will be initialised by the calling program. If
we also want the BIOS handler to process all keystrokes then this variable
must be set to true.
Next we need to store the value of the current handler and set up own our
own one. We'll use a procedure called KeyboardHandler to handle the actual
interrupt.
CallBIOSHandler := false; { ...or set it to true if you want. }
GetIntVec(KEYBOARDINTR, @BIOSKeyboardHandler);
SetIntVec(KEYBOARDINTR, Addr(KeyboardHandler));
Ok, so everything is now set up and our handler will now be able to process
all keyboard events. The actual interrupt handler could look like this:
{$F+}
procedure KeyboardHandler(Flags, CS, IP, AX, BX, CX, DX,
SI, DI, DS, ES, BP: Word);
interrupt;
var key : byte;
begin
key := Port[KEYBOARDPORT];
{ PROCESS THE KEYSTROKE HERE }
if CallBIOSHandler then
{ Call the BIOS keyboard handler if the calling program wants us to }
begin
asm pushf end;
BIOSKeyboardHandler;
end
{ Otherwise just acknowledge the interrupt }
else Port[$20] := $20;
end;
{$F-}
When the program is finished we can set the old keyboard handler again:
SetIntVec(KEYBOARDINTR, @BIOSKeyboardHandler);
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> A Word of Warning <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
When I was writing a simple handler to test the info in this file I did
something REALLY stoopid which I would like to share with the world. I
thought that my program was stuffing the keyboard up because when I exited
the program my editor (Borland Pascal 7.0) would act as though the control
button was being held down (I'm sure some of you have already started
laughing by now). I had to press it after each time I ran the program
just to sort it out. After spending a few hours looking all over the place
for info on what could possibly be wrong I realised what I was doing. I was
pressing CTRL-F9 to compile the program which would also immediately make it
run and I was releasing the control key when my program was running, ie the
regular BIOS handler was not getting the control key's "key up" command and
still thought it was being held down when my program returned control to
it. Moron.....
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD> Scan Codes <20>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
The following is a list of all the regular key scan codes in numerical
order:
Scan Scan
Code Key Code Key
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
1 ESC 44 Z
2 1 45 X
3 2 46 C
4 3 47 V
5 4 48 B
6 5 49 N
7 6 50 M
8 7 51 , <
9 8 52 . >
10 9 53 / ?
11 0 54 RIGHT SHIFT
12 - _ 55 * (KEYPAD)
13 = + 56 LEFT ALT
14 BACKSPACE 57 SPACEBAR
15 TAB 58 CAPSLOCK
16 Q 59 F1
17 W 60 F2
18 E 61 F3
19 R 62 F4
20 T 63 F5
21 Y 64 F6
22 U 65 F7
23 I 66 F8
24 O 67 F9
25 P 68 F10
26 [ { 69 NUMLOCK (KEYPAD)
27 ] } 70 SCROLL LOCK
28 ENTER (RETURN) 71 7 HOME (KEYPAD)
29 LEFT CONTROL 72 8 UP (KEYPAD)
30 A 73 9 PGUP (KEYPAD)
31 S 74 - (KEYPAD)
32 D 75 4 LEFT (KEYPAD)
33 F 76 5 (KEYPAD)
34 G 77 6 RIGHT (KEYPAD)
35 H 78 + (KEYPAD)
36 J 79 1 END (KEYPAD)
37 K 80 2 DOWN (KEYPAD)
38 L 81 3 PGDN (KEYPAD)
39 ; : 82 0 INSERT (KEYPAD)
40 ' " 83 . DEL (KEYPAD)
41 ` ~ 87 F11
42 LEFT SHIFT 88 F12
The following is a list of all the extended key scan codes in numerical
order:
Scan Scan
Code Key Code Key
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
28 ENTER (KEYPAD) 75 LEFT (NOT KEYPAD)
29 RIGHT CONTROL 77 RIGHT (NOT KEYPAD)
42 PRINT SCREEN (SEE TEXT) 79 END (NOT KEYPAD)
53 / (KEYPAD) 80 DOWN (NOT KEYPAD)
55 PRINT SCREEN (SEE TEXT) 81 PAGE DOWN (NOT KEYPAD)
56 RIGHT ALT 82 INSERT (NOT KEYPAD)
71 HOME (NOT KEYPAD) 83 DELETE (NOT KEYPAD)
72 UP (NOT KEYPAD) 111 MACRO
73 PAGE UP (NOT KEYPAD)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,587 @@
Programming the Microsoft Mouse
-------------------------------
"A Mouse! What A Great Idea!!"
-W. Disney
Written for the PC-GPE by bri (accbpf@vaxc.hofstra.edu)
and Mark Feldman (pcgpe@geocities.com)
Disclaimer
----------
We assume no responsibility whatsoever for any effect that this file, the
information contained therein or the use thereof has on you, your sanity,
computer, spouse, children, pets or anything else related to you or your
existance. No warranty is provided nor implied with this information.
Introduction
------------
Programming the mouse is one of the easiest tasks you'll ever have to
undertake. Mouse drivers hook themselves into interrupt 33h, so you
can just call driver-functions the same way you would BIOS functions.
Basics
------
The first step is to initialize the mouse driver. You do this by setting
the ax register to 0 and calling interrupt 33h. This will return a
non-zero number in ax if the driver is installed(which usually means if
the mouse is installed. From here on in, anything I say about the mouse
actually refers to the driver).
To display the mouse cursor on the screen, set ax to 1 before calling int 33h.
In text-mode you should get what appears to be a block-like text cursor, and
in any graphics mode you should get the arrow by default(although we'll see
how to change this later). The driver detects what mode you're in and draws
the appropriate cursor.
To hide the mouse cursor, you set the ax register to 2 and call the interrupt.
Showing and hiding the mouse cursor is something you'll probably have to do
often when you draw images to the screen. Believe you me, having a mouse move
across something you're drawing can really wreck you're display. To get around
this, hide the mouse cursor, draw what's necessary, and re-display the mouse
cursor.
Please note, mouse drivers often keep a 'display counter' that reads 0
if the cursor is displayed and less then 0 if its hidden. Consecutive
calls to hide the mouse cursor will decrement the counter and make it
more and more negative-in which case it will take more calls to display
the mouse cursor to get the counter to 0. Once the counter is 0, calls
to display the mouse cursor have no effect on the counter. To read the
state of the counter, you can call function 2Ah, and the counter is
returned in the ax register. I'll touch on function 2Ah a bit more later.
Last but not least, we should be able to figure out if any buttons are
pressed, if so which ones, and where the mouse is. This is easy, just
set ax to 3 and call int 33h-the horizontal coordinate is returned
in the cx register, the vertical coordinate in the dx register and
bx has the button status. In bx, each bit reads 1 if a corresponding
button is pressed-for example bit 0 is 1 if the left button is pressed,
bit 1 is 1 if the right button is pressed, and bit 2 is 1 if the
center button is pressed.
As for the coordinates-be careful, as a lot of mouse drivers use a "virtual
screen" of 640x200 pixels-which mean if you're screen resolution isn't this-
you'll have to do some converting.
SETTING THE CURSOR SHAPE
------------------------
When you use your mouse in a graphics mode, by default, you're stuck
with the shape of the mouse cursor as an arrow. This is fine most of the
time, but it can get boring after a while. Don't fret!!! You can alter the
shape to accomodate your needs!
The graphics mode cursor image is a 16-by-16 pixel area on the screen
that is defined by a 64 byte buffer passed to int 33h, function 9. The first
32 bytes contain the cursor mask-the appearance of the cursor on the screen.
The second 32 bytes is the screen mask-it defines the appearance of the
screen image under the cursor. In this 64 byte buffer, each bit corresponds
to 1 pixel, i.e. the first two bytes in both of the masks corresponds to the
16 pixels that make up the top row of the cursor.
When you're designing the cursor mask, each bit is 1 if it is displayed,
and 0 if it is not. On the screen mask, bits that are 1 are transparent.
The mouse driver takes the screen mask, and the cursor mask and shoves
them together, coming up with the following:
Screen Mask Bit is Cursor Mask Bit is Resulting Screen Bit is
------------------ ------------------ -----------------------
0 0 0
0 1 1
1 0 Bit is Not Changed
1 1 Bit is Inverted
To set the shape you call Function 9h with ES holding the segment of your
buffer containing the masks, and DX containing the offset of the buffer
containing the cursor mask.
One other important thing to note: your cursor has a hot spot=the point
on your mouse cursor that is where the cursor is actually pointing.
Usually this is 1, 1(that is 1 pixel from the top of the cursor and
1 from the right). But when you change the image of your mouse cursor
you might need to change the hot spot. You can do this by setting CX
and DX of Function 9 to the horizontal and vertical offset of the hot
spot.
ODDS AND ENDS
-------------
Well, there are a few odds and ends here that you might find useful.
You can set limits on where you want to allow the mouse cursor to roam.
Function 7 & 8(AX= 7 & AX = 8) set the horizontal and vertical limits
of the mouse cursor respectively. In both cases you input cx as the minimum
coordinate in pixels, and dx as the maximum coordinate in pixels.
You can take the mouse and move it to a certain position on the screen
from inside your program. That's function 4(ax=4). You specify the
horizontal coordinate in CX, and the vertical coordinate in DX. If you
specify a coordinate outside a range you've set using functions 7 & 8,
the mouse driver will most likely put the cursor at the very edge of
that boundary.
Lastly, you can set the amount of distance you're actual mouse moves
to get the cursor on the screen to move. Mouse movement is measured
in mickeys(I'm not joking here!) where each mickey is approximately
1/200 of an inch. To adjust this use function 0Fh. CX should contain
the number of horizontal mickeys, and dx the number of vertical ones.
The numbers in CX and DX actually refer to the amount of mickeys needed
to move the mouse cursor a total of 8 pixels. By default, CX is 8, while
DX is 16. You can set a range of 1(hyper-active energetic mouse) to
32,767(unbelievably sluggish and lazy).
SLAM DUNKS AND LOW CEILINGS
----------------------------
(With special thanks to Feldman the Great for this section)
Yes, like the subject header, something else that has never mixed very well
together was mouse and SVGA programming. The reason, of course is that your
mouse driver is what takes care of the updating of the image of the mouse
cursor in graphics mode.
You see, in the beginning, SVGA was created. This was widely regarded
as a bad idea.
Sure it looked cool, and there were more pretty colors than you could shake
a kaleidoscope at, but there was no standard. (This was before VESA, and sadly
even today many mouse drivers don't use VESA) This left all SVGA chip
makers to deviously make chips however they wanted, depending on what
kind of mood they were in, and what they had had for lunch. As most
SVGA chip designers rarely ate the same thing at lunchtime, you wound up
with a googleplex full of SVGA cards that all were 110% incompatible
with each other.
Remember what I said about your mouse driver handling your mouse cursor.
Now mouse drivers had to know how to handle every single SVGA card, so
they could draw the cursors correctly in SVGA mode. Mouse driver
maufacturers got around this problem in a rather novel way: they ignored
SVGA.
Because of this, most mouse drivers throw up their hands in disgust when
confronted with the ugly head of SVGA and simply provide you with no mouse
cursor at all. Likewise, if you're programming for Mode X, you're likely to
run into the same trouble. You CAN get around this, however. How? you ask
with baited breath. Simply install your own mouse handler(I'm using the word
'simply' rather loosely here). What this will do, is cause the mouse driver
to call one of your functions-and then you're responsible for updating the
graphics cursor image on the screen.
Basically, you call Function 0Ch. CX contains the event mask: on what
conditions the mouse driver will call your function. The mask is listed
below:
Bit If set
0 Mouse Cursor Movement
1 Left Button Pressed
2 Left Button Released
3 Right Button Pressed
4 Right Button Released
5 Center Button Pressed
6 Center Button Released
The ES register holds the segment of your mouse code that the driver
should call, and DX holds the offset. (As an aside, I'd recommend
doing the mouse handler itself in assembly, as getting it to work
in C or Pascal is an uphill struggle at best).
When the mouse driver calls your function, AX will contain the event
flag that you set earlier. BX will contain the button status: 0 if
the left button is pressed, 1 if the right button is pressed, and 2
if the center button is pressed. CX and DX contain the horizontal and
vertical position of the mouse cursor respectively.
To disable an installed handler, simply call function 0Ch with an
event mask of 0, or call Function 0h.
Well that about wraps it up...if you have any questions at all,
please feel free to contact me (bri) at accbpf@vaxc.hofstra.edu and I'll
do my best to answer them.
Quick Reference Guide to Interrupt 33h
--------------------------------------
FUNCTION: AX = 0h
Description: Determines whether a mouse is available and if it is
initializes the mouse driver.
Returns : AX = Non-Zero (If Mouse is installed, 0 if not)
BX = Number of Mouse Buttons
FUNCTION: AX = 1h
Description: Increments the mouse cursor display counter.
Returns : Nothing
FUNCTION: AX = 2h
Description: Decrements the mouse cursor display counter.
Returns : Nothing
FUNCTION: AX = 3h
Description: Returns the current mouse position and button status.
Returns : BX = Buttons status:
Bit 0: Left Button
Bit 1: Right Button
Bit 2: Center Button
CX = Horizontal Coordinate
DX = Vertical Coordinate
FUNCTION: AX = 4h
Description: Moves the mouse cursor to a certain position on the screen.
Call With : CX = Horizontal Coordinate
DX = Vertical Coordinate
Returns : Nothing
FUNCTION: AX = 5h
Description: Reports on the status and numbers of presses for a
button.
Call with : BX = Button to Check
0 = Left Button
1 = Right Button
2 = Center Button
Returns : AX = Button Status
Bit 0 = Left Button
Bit 1 = Right Button
Bit 2 = Center Button
BX = Button Press Counter
CX = Horizontal Coordinate of Last Button Press
DX = Vertical Coordinate of Last Button Press
FUNCTION: AX = 6h
Description: Gets the button release information.
Call With : BX = Button to Query
0 = Left Button
1 = Right Button
2 = Center Button
Returns : AX = Button Status(1 if pressed)
Bit 0 = Left Button
Bit 1 = Right Button
Bit 2 = Center Button
BX = Button Release counter
CX = Horizontal Coordinate of last button release
DX = Vertical Coordinate of last button release
FUNCTION: AX = 7h
Description: Sets the horizontal limits for the mouse cursor.
Calls With : CX = Minimum horizontal mouse coordinate.
DX = Maximum horizontal mouse coordinate.
FUNCTION: AX = 8h
Description: Sets the vertical limits for the mouse cursor.
Call With : CX = Minimum vertical mouse coordinate.
DX = Maximum vertical mouse coordinate.
Returns : Nothing
FUNCTION: AX = 9h
Description: Defines the shape of the graphics mode cursor.
Call With : BX = Hoorizontal hot spot offset
CX = Vertical hot spot offset
ES = Segment of buffer containing cursor mask
DX = Offset of buffer containing cusror mask
Returns : Nothing
FUNCTION: AX = 0Ah
Description: Definesthe shape of the text mode cursor
Call With : BX = Cursor Type
0 = Software Cursor
1 = Hardware cursor
if BX = 0 then
CX = Screen Mask value
DX = Cursor Mask Value
else
CX = Starting Scan Line For Cursor
DX = Ending Scan Line For Cursor
FUNCTION: AX = 0Bh
Description: Returns the net mouse movement since the last call
to this function(or since the mouse was initialized).
Returns : CX = Horizontal mouse movement(in Mickeys)
DX = Vertical mouse movement(in Mickeys)
FUNCTION: AX = 0Ch
Description: Sets the user defined mouse handler.
Call With : CX = Event Mask
Bit If set
0 Mouse Cursor Movement
1 Left Button Pressed
2 Left Button Released
3 Right Button Pressed
4 Right Button Released
5 Center Button Pressed
6 Center Button Released
ES = Segment of your mouse handler code
DX = Offset of your mouse handler code
Returns : AX = Event Mask
BX = Button Status(1 if pressed)
Bit 0 = Left Button
Bit 1 = Right Button
Bit 2 = Center Button
CX = Horizontal Coordinate
DX = Vertical Coordinate
FUNCTION: AX = 2Ah
Description: Returns display counter state, and current hot spot
Returns : BX = Horizontal offset of hot spot
CX = Vertical offset of hot spot
A complete list of mouse function calls can be found in the file GMOUSE.TXT,
the file contains calls for both Microsoft (2 button) and Genius (3 button)
modes.
Writing Custom Handlers
-----------------------
Most mouse drivers do not support SVGA modes, so you must write custom
handlers if you want mouse support for these modes.
Rather than writing an entire mouse driver, you can write a simple handler
routine to take care of the graphics and tell the mouse driver to call it
whenever the mouse does anything. This function is descibed in the GMOUSE.DOC
file, but this demo Pascal program shows the general idea. It sets mode 13h,
resets the mouse and waits for a key to be pressed. Whenever you do anything
to the mouse (moving it or pressing a button) the handler will get called
and it will draw a pixel on the screen. The color of the pixel depends on
which buttons are being pressed.
Uses Crt, Dos;
{$F+}
{ called with bl = buttons, cx = x * 2, dx = y }
procedure Handler; far; assembler;
asm
{ This mouse "handler" just draws a pixel at the current mouse pos }
pusha
push es ; pusha doesn't save es
mov ax, $A000
mov es, ax
shr cx, 1
xchg dh, dl
mov di, dx
shr dx, 2
add di, dx
add di, cx
mov al, bl
inc al
stosb
pop es
popa
end;
{$F-}
begin
asm
{ Set graphics mode 13h }
mov ax, $13
int $10
{ Initialize mouse driver }
xor ax, ax
int $33
{ Install custom handler }
mov ax, SEG Handler
mov es, ax
mov dx, OFS Handler
mov ax, 12
mov cx, $1F
int $33
{ Wait for a key press }
xor ah, ah
int $16
{ Back to text mode }
mov ax, 3
int $10
end;
end.
Alternatively you may wish to write your own interrupt handler to process
mouse events as they happen. When a mouse event occurs, 3 interrupts are
generated and the bytes are available via the COM port.
----------------------------
| Interrupt Port |
----------------------------
| COM1 $0C $3F8 |
| COM2 $0B $3F8 |
----------------------------
The three bytes sent are formatted as follows:
1st byte 2nd byte 3rd byte
----------------- --------------- ---------------
|-|1|?|?|X|X|Y|Y| - |0|X|X|X|X|X|X| |0|Y|Y|Y|Y|Y|Y|
----------------- --------------- ---------------
| | \ / \ / | |
| | | | | |
| | | ------------- ---------- |
| | ---------- | \ \ |
| | \_\_ _ _ _ _ _ _ \_\_ _ _ _ _ _ _
| | |_|_|_|_|_|_|_|_| |_|_|_|_|_|_|_|_|
| | X increment Y increment
Left Button -- |
Right Button ----
The X and Y increment values are in 2's compliment signed char format. (BTW
thanks go to Adam Seychell for posting this info to comp.os.msdos.programmer).
A simple Borland Pascal 7.0 mouse handler follows. First we declare a few
things we'll need:
----------------------------------------------------------------------
Uses Crt, Dos;
{$F+}
const COM1INTR = $0C;
COM1PORT = $3F8;
var bytenum : word;
combytes : array[0..2] of byte;
x, y : longint;
button1, button2 : boolean;
MouseHandler : procedure;
----------------------------------------------------------------------
The bytenum variable is used to keep track of which byte is expected next
(ie 0, 1 or 2). The combytes variable is simply an array to keep track of
bytes received so far. The mouse position will be stored in the x and y
variables (note that this example will not perfrom any range checking).
button1 and button2 will be used to store the states of each of the buttons.
MouseHandler will be used to store the normal mouse driver event handler.
We'll also need it to reset everything once we are finished.
Here's the actual handler:
----------------------------------------------------------------------
procedure MyMouseHandler; Interrupt;
var dx, dy : integer;
var inbyte : byte;
begin
{ Get the port byte }
inbyte := Port[COM1PORT];
{ Make sure we are properly "synched" }
if (inbyte and 64) = 64 then bytenum := 0;
{ Store the byte and adjust bytenum }
combytes[bytenum] := inbyte;
inc(bytenum);
{ Have we received all 3 bytes? }
if bytenum = 3 then
begin
{ Yes, so process them }
dx := (combytes[0] and 3) shl 6 + combytes[1];
dy := (combytes[0] and 12) shl 4 + combytes[2];
if dx >= 128 then dx := dx - 256;
if dy >= 128 then dy := dy - 256;
x := x + dx;
y := y + dy;
button1 := (combytes[0] And 32) <> 0;
button2 := (combytes[0] And 16) <> 0;
{ And start on first byte again }
bytenum := 0;
end;
{ Acknowledge the interrupt }
Port[$20] := $20;
end;
----------------------------------------------------------------------
Once again pretty simple stuff. We just read the byte from the com1 port and
figure out if it's time to do anything yet. If bit 6 is set to 1 then we
know that it's meant to be the first byte of the 3, so we reset our
bytenum variable to zero (in a perfect world bytes would always come in 3's
and we would never need to check, but it never hurts to be careful).
When 3 bytes have been received we simple decode them according to the
diagram above and update the appropriate variables accordingly.
The 'Port[$20] := $20;' command just lets the interrupt controller know we
have processed the interrupt so it can send us the next one when it wants to.
Note that the above "handler" does nothing more than keep track of the
current mouse position and button states. If we were writing a proper mouse
driver for an SVGA game we would also have to write custom cursor routines.
I'll leave that bit to you!
To actually install our mouse driver we'll have to set up all the variables,
save the address of the current mouse handler and install our own. We'll
also need call the existing mouse driver to set up the COM1 port to make
sure it sends us the mouse bytes as it receives them. We could do this
ourselves, but why make life harder than it already is?
----------------------------------------------------------------------
procedure InitMyDriver;
begin
{ Initialize the normal mouse handler }
asm
mov ax, 0
int $33
end;
{ Initialize some of the variables we'll be using }
bytenum := 0;
x := 0;
y := 0;
button1 := false;
button2 := false;
{ Save the current mouse handler and set up our own }
GetIntVec(COM1INTR, @MouseHandler);
SetIntVec(COM1INTR, Addr(MyMouseHandler));
end;
----------------------------------------------------------------------
And finally when our program is finished it'll need to clean up after
itself and return control back to the normal mouse driver:
----------------------------------------------------------------------
procedure CleanUpMyDriver;
begin
SetIntVec(COM1INTR, @MouseHandler);
end;
----------------------------------------------------------------------
This little bit of source will test the above code. It does nothing more
than repeatedly write the mouse position and button states to the screen
until a keyboard key is pressed:
----------------------------------------------------------------------
begin
ClrScr;
InitMyDriver;
while not keypressed do
WriteLn(x : 5, y : 5, button1 : 7, button2 : 7);
CleanUpMyDriver;
end.
----------------------------------------------------------------------

View File

@@ -0,0 +1,81 @@
From: Tomi Engdahl <then@snakemail.hut.fi>
Date: Fri, 29 Apr 1994 13:28:37 +0200 (EET DST)
Serial mouse
Voltage levels:
Mouse takes standard RS-232C output signals (+-12V) as its input signals.
Those outputs are in +12V when mouse is operated. Mouse takes some current
>from each of the RS-232C port output lines it is connected (about 10mA).
Mouse send data to computer in levels that RS-232C receiver chip in the
computer can uderstand as RS-232C input levels. Mouse outputs are normally
something like +-5V, 0..5V or sometimes +-12V. Mouse electronics
normally use +5V voltage.
Microsoft serial mouse
Pins used:
TD, RTS and DTR are used only as power source for the mouse.
RD is used to receive data from mouse.
Serial data parameters: 1200bps, 7 databits, 1 stop-bit
Data packet format:
Data packet is 3 byte packet. It is send to the computer every time
mouse state changes (mouse moves or keys are pressed/released).
D7 D6 D5 D4 D3 D2 D1 D0
1. X 1 LB RB Y7 Y6 X7 X6
2. X 0 X5 X4 X3 X2 X1 X0
3. X 0 Y5 Y4 Y3 Y2 Y1 Y0
The byte marked with 1. is send first, then the others. The bit D6
in the first byte is used for syncronizing the software to mouse
packets if it goes out of sync.
LB is the state of the left button (0 means pressed down)
RB is the state of the right button (0 means pressed down)
X7-X0 movement in X direction since last packet (signed byte)
Y7-Y0 movement in Y direction since last packet (signed byte)
Mouse systems mouse
Serial data parameters: 1200bps, 8 databits, 1 stop-bit
The data is sent in 5 byte packets in following format:
D7 D6 D5 D4 D3 D2 D1 D0
1. 1 0 0 0 0 LB CB RB
2. X7 X6 X5 X4 X3 X2 X1 X0
3. Y7 Y6 Y5 Y4 Y3 Y4 Y1 Y0
4.
5.
LB is left button state (0=pressed, 1=released)
CB is center button state (0=pressed, 1=released)
RB is right button state (0=pressed, 1=released)
X7-X0 movement in X direction since last packet in signed byte
format (-128..+127), positive direction right
Y7-Y0 movement in Y direction since last packet in signed byte
format (-128..+127), positive direction up
The last two bytes in the packet (bytes 4 and 5) contains
information about movement data send in last packet. I have not
found exact information about those bytes. I have not also found
any use for such a information (maybe it is for syncronization
or something like that).
--
Tomi.Engdahl@hut.fi Helsinki University of Technology
G=Tomi S=Engdahl O=hut ADMD=fumail C=fi Department of Computer Science
# This text is provided "as is" without any express or implied warranty #

View File

@@ -0,0 +1,29 @@
From: Lennart Steinke <steinke@zeus.adv-boeblingen.de>
Subject: Two mice, one pc
Newsgroups: rec.games.programmer
Date: Thu, 18 Jul 1996 10:14:53 -0500
Hi!
Sometime ago, I tried to use two mice at the
the same PC. It worked, and I used it for a
tron game, and a simple Air Hockey simulation
(two player only).
Here's what I've done to use those two mice:
0) Install mouse handler (com1)
1) Save the address of the current hander
2) Point the irq to "no handler installed"
3) Install a mouse handler for com2
4) Save it's address
To get the mouseinformation, just swap the
isr addresses, then use the standard mouse
functions.
Lenny
--
Lennart Steinke (steinke@adv-boeblingen.de)