docu.txt

(20 KB) Pobierz
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 t...
Zgłoś jeśli naruszono regulamin