October 25, 2011

When it comes to advanced applications like Games, GUI apps or any graphical application. Mouse is the utmost necessity of a programmer. It’s a powerful tool since in such situations it’s both frustrating and time consuming to rely on keyboard as you do in parallel programming because it‘s sequential. Therefore a good knowledge of mouse programming is warranted for all playful and knowledgeable purposes and to all top-notch DOS programmers.

Mouse Programming can be a very long topic especially when beginner understanding is involved but everything becomes easy with practice.

THEORY

All input devices generate interrupts mouse is no exception to this rule. It also has got a chip inside it which generates interrupt 33h. Later mouse driver converts mouse activity in understandable data for operating system. In DOS (TURBO C) interrupt’s are easily accessible and programmable then to program a whole driver hence they will be used. Since we use interrupts to make mouse functions a basic understanding of interrupts and CPU registers is assumed.

Over cyberspace most articles are silent on Event mode they all use polling which is neither used professionally nor by advanced applications developed on mouse. But PART2 will show you a live example of implementing Event programming for mouse.

REQUEST MODE

Before starting off a quick review of interrupt’s going to be used in mouse programming.

There are exactly 24 service defined in 33h but only required ones are shown.

TABLE OF MOUSE FUNCTIONS

SERVICE

ARGUMENTS

RETURN VALUES

WORKING

00h

AX =00h

AX = FFFFh or 0000h

If AX is FFFFh mouse driver installed otherwise not installed. Mouse driver is reset after call, but not displayed on screen.

01h

AX = 01h

none

Shows mouse cursor on screen.

02h

AX = 02h

None

Hides mouse cursor.

03h

AX = 03h

CX = (X) position

DX = (Y) position

BX = button status

---BX---

8

7

6

5

4

3

2

1

0

If 0 bit is set ­– left button pressed.

If 1 bit is set – right button pressed.

If 2 bit is set – middle button pressed.

04h

AX = 04h

CX =(X)position

DX=(X)position

none

Sets mouse position

07h

AX = 07h

CX =min (X)

DX =max (X)

none

Restricts mouse horizontally between minimum X and maximum X.

08h

AX = 08h

CX = min (Y)

DX = max (Y)

none

Restricts mouse vertically between minimum Y and maximum Y.

09h

AX = 09h

BX =horz hotspot

CX = vert hotspot

ES:DX = pointer to screen and cursor mask

none

Sets Graphical cursor

Screen mask -AND’ed to screen and cursor mask is XOR’ed.

Bytes 0 – 7 form screen mask.

Bytes 8 – F form the cursor bitmap.

0Ch

AX = 0Ch

ES:DX = far pointer to interrupt routine.

CX = interrupt mask.

none

…

4

3

2

1

0

Bit 0 = mouse move

Bit 1 = left button pressed

Bit 2 = left button released

Bit 3 = right button pressed

Bit 4 = right button released

… = unused

For speed and learning purposes it’s better to write all coding in assembly though you may find easy int86 style over cyberspace. Let’s write a GUI app with the use of these interrupts. As expected it’s a large code mainly due to BGI though it’s very basic.

The global variables hold mouse’s current state as per the need of different functions. ‘mX’ and ‘mY’ hold mouse’s X and Y coordinate respectively followed by ‘lPress ’ and ‘rPress ’ set only when left or right mouse button is pressed.

The BUTTON structure fully describes a button on screen. From its initial X and Y cord’s to its maximum length and height followed by BUTTON’s Label and it’s color. You will see how easy polling becomes with this structure.

MOUSE FUNCTIONS

Few assembly instructions. The letter in italic are operands for these instructions.

SetMouse()- Remember you need to initialize mouse driver and set it to its initial state before using any kind of interrupt’s to access mouse’s data. If you don’t results can be WEIRD!!! As the table states 00h initializes mouse driver on its presence but it’s too FANCY to check mouse or even its driver’s presence hence no condition check to FFFFh is given function is followed by showing mouse using 01h. You better break this function into 2.

HideMouse()- Often you will need to hide mouse. Assuming you playing a video on screen you will need to hide mouse and may be at some illegal place depending on your application’s purpose. Table states 02h for this purpose.

SlaveMouse() - A FANCY function with little use in person’s “signature” through mouse in some advanced applications. Table states two consecutive functions 07h and 08h for its usage. It’s quite easy to decode.

ChangeCursor()- A useful utility indeed. You can set your own cursor. A mouse array is declared globally which is so written according to function’s need.

Declaring RIGHT array-

The integers are decoded here

SCREEN MASK 0-15 CURSOR MASK 15-31(starting and ending indexes)

Screen mask – It is ANDed with screen that means every 0 results in black color and 1 in what the screen is currently having under the mask. Put simply if you don’t want screen mask to disturb screen write that bit 1 and the thing you want to display should be 0. It is normally held under your cursor mask so it is not visible if you totally overlap it with cursor mask, black pixels will be seen otherwise.

Cursor mask – It is the mask XORed with screen that simply means put 0 where you want to display what exactly being displayed under cursor mask and place where you want to display your cursor should be kept 1.

Hotspot is the location inside your screen mask which you want to act like a tracker, here 3 as X and 4 as Y coordinate are used.

GetStatus()- Table states 03h function to get mouse status. Its definition may seem tricky.

Here is what and how it does.

First it retrieved the information using 03h. Next it set Global vars mX and mY to their respective usages. The way it retrieves lPress and rPress is saves bx then shifts it right so you get the right key status in LSB then copy it to rPress next retrieve original bx then AND it with 1, in that way every bit except LSB is zeroed result is simply moved in lPress.

FEW WORDS ON GUI

The model used to create a button according to this code is quite simple.

1.Create an array of BUTTON objects. Fill them with required details.

2.Call addButton()to add these buttons to screen.

3.Enter an infinite loop and call Checkbutton().It will return the index of button clicked, -1 otherwise.

The creation of BUTTON structure eases the way of GUI. Traditionally wherever mouse programming is involved dependency exists that means you cannot use any 1 of GUI detection functions in some other project simply due to fixed scope and lack of wide thoughts. The code breaks this barrier.

PROBLEMS WITH CODE

As you might notice code can be slow and flickering may result this is strictly not acceptable in professional apps. The root cause of this problem is that BGI is too slow. If you are familiar with mode 13h programming better implement this model over BGI.

Well that was fun to do and learn. Hope you enjoyed.

Part 2 will be dedicated to event mode mouse programming.Don’t forget to ask queries.. :)