Solved

Mouse interrupts in DOS?

Posted on 1998-11-22
7
408 Views
Last Modified: 2011-09-20
I need to develop a C++ graphics programme that will work in dos and draw simple graphics like circle and rectangle at the point where the user clicks the mouse. Can anyone help me?
0
Comment
Question by:pr12
  • 4
  • 2
7 Comments
 

Author Comment

by:pr12
ID: 1178424
Edited text of question
0
 
LVL 6

Expert Comment

by:thresher_shark
ID: 1178425
First, here is a header file for mouse operations in DOS:

/*
   This provides functions for polling the mouse.  The main routine,
   mouse, has this description.

   To do various functions (input) [output] set 'a' to
    0 - test if loaded [reg.ax = $ffff]
    1 - show cursor
    2 - hide cursor
    3 - get position [b buttons, c x, d y]
    4 - set position (c x,d y)
    5 - press button   (b buttons, c x, d y) [b count]
    6 - release button (b buttons, c x, d y) [b count]
    7 - set x range  (c min, d max)
    8 - set y range  (c min, d max)
    10- text cursor  (b 0=soft 1=hard, c ?, d ?)
    15- mickeys      (c xscale, d yscale?)
*/

#define MOUSEINT 0x33
#include <dos.h>
#include <cursors.h>

int mouse (int, int *, int *, int *);  // Main Mouse Function.
int init_mouse (void);                 // Starts mouse, check if loaded.
int show_mouse (void);                 // Shows the cursor.
int hide_mouse (void);                 // Hides the cursor.
int get_mouse (int *, int *);          // Get x, y. Return # buttons PRESSED
int set_mouse (int, int);              // Puts the mouse somewhere.
void change_mouse (unsigned int far *, int, int);

int mouse (int ax, int *bx, int *cx, int *dx)
{ static union REGS regs;
  regs.x.ax = ax;   // Set registers to the values given.
  regs.x.bx = *bx;
  regs.x.cx = *cx;
  regs.x.dx = *dx;
  int86 (MOUSEINT, &regs, &regs); // Do it.

  // Return Status:
  *bx = regs.x.bx;
  *cx = regs.x.cx;
  *dx = regs.x.dx;
  return regs.x.ax;
}

int init_mouse (void)
{ int x = 0;
  return mouse (0, &x, &x, &x);
}

int show_mouse (void)
{ int b = 0;
  return mouse (1, &b, &b, &b);
}

int hide_mouse (void)
{ int b = 0;
  return mouse (2, &b, &b, &b);
}

int get_mouse (int *x, int *y)
{ int b = 0;
  mouse (3, &b, x, y);
  return b;
}

int set_mouse (int x, int y)
{ int b = 0;
  return mouse (4, &b, &x, &y);
}

////////////////////////////////////////////////////
// CHANGEMOUSE                                    //
// Changes the shape of the mouse cursor          //
// Input: pointer to new shape, hot x, hot y      //
////////////////////////////////////////////////////
// Separate because this needs access to the      //
// segment registers                              //
////////////////////////////////////////////////////
void change_mouse (unsigned int far *shape, int hotx, int hoty)
{ union REGS regs;
      struct SREGS sregs;

      regs.x.ax = 0x09; // mouse function 9, change mouse
      regs.x.bx = hotx; // x hot spot
      regs.x.cx = hoty; // y hot spot
      regs.x.dx = FP_OFF (shape); // address of shape (mask/data)
      sregs.es = FP_SEG (shape);
  int86x (0x33, &regs, &regs, &sregs); // execute BIOS call
}

Second, do you already have functions for graphics operations or would you like me to give you a header file for that too?

If you have any questions regarding the use of the header file, please feel free to ask.  Thanks!
0
 
LVL 6

Expert Comment

by:thresher_shark
ID: 1178426
Note that some of the functions in the header will vary depending on the compiler you are using.  What compiler are you using?
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Accepted Solution

by:
Noteran earned 200 total points
ID: 1178427
            PROGRAMMER'S  REFERENCE  FOR  GENIUS  MOUSE  DRIVER

*** 1 : BRIEF DESCRIPTION

The Genius Mouse Driver enables you to use mouse hardware to move an on-screen
cursor and control its movement through a software program.  Various functions
allow you to determine cursor placement, cursor shape, and button status.

In order for you to interface your Genius Mouse with an application program, the
following information on the Genius Driver has been provided.

*** 2 : GRAPHICS AND TEXT CURSORS

GMOUSE Driver supports a hardware text cursor,  a software  text   cursor, and
a graphics cursor. A hardware text cursor is a blinking cursor which moves from
one character to another on-screen. This blinking cursor may take the form of a
block or underscore. A software text cursor makes use of display attributes to
change the visual appearance of a character on-screen.  Movement is from
character to character. A graphics cursor is a shape that moves over on-screen
images.

You can choose any of these three cursors to use on-screen, however, only one
cursor can be displayed at a given time.  Also, within your application program,
you can switch back and forth between cursors.


Display the Graphics Cursor

The cursor appears on-screen or disappears from the screen through the calling
program.  This cursor consists of a block of pixels.  As this block moves
on-screen and affects the pixels beneath it, the cursor shape and background are
created. This interaction is defined by two 16-by-16 bit arrays;
one is the screen mask and the other is the cursor mask. The screen mask
determines what part of the cursor pixel is to be the shape, and what part  is
is to be the background. The cursor mask determines which pixels contribute to
the color of the cursor. Whenever changes are made to the screen which lie
directly  beneath the cursor, the cursor should be concealed so that old values
are not restored to the screen.

Please note that with a high resolution mode, you have a 16-by-16 pixel block;
with a medium resolution (four color) mode, you have a 8-by-16 pixel block; with
a medium resolution (sixteen color) mode, you have a 4-by-16 pixel block.

Refer to function 9.

To create the cursor, the software uses data from the computer's screen memory
which defines the color of each pixel on-screen.  Operations are performed that
affect individual screen bits.  Software ANDs the screen mask defining the
pixels under the cursor and XORs the cursor mask with the result of the AND
operation.

Note the results when:






                                 page 1


Screen Mask Bit is      Cursor Mask Bit is      Resulting Screen Bit is
------------------      ------------------      -----------------------
        0                        0                         0
        0                        1                         1
        1                        0                     unchanged
        1                        1                      inverted

With each mouse function, a reference to the graphics cursor location is in
reference to a point on-screen directly beneath the cursor.  This point that the
mouse software uses to determine the cursor coordinates is known as the cursor's
hot spot.
Generally, the upper_left hand corner of the cursor block is designated as the
coordinates for the cursor default value. ((0,0) are the upper_left hand corner
coordinates.)

Software Text Cursor

You can use this text cursor when your computer is in one of the text modes.  By
changing the character attributes beneath the cursor, the appearance of the
character is influenced on-screen.  This effect on the text cursor can be
defined by two 16-bit mask values. These bits can be described as follows:
bit 15 sets the blinking (1) or non-blinking (0) character ; bit 12 - 14 set the
background (1); bits 8 - 10 set the foreground color; and bits 0 - 7 set the
character code. These values in the screen mask and the cursor mask
determine the character's new attributes when the cursor is covering the
character.  The screen mask decides which of the character's attributes are
maintained. The cursor mask decides in what manner the attributes are altered
to produce the cursor.

In creating this cursor, the software works from data which defines each
character on the screen.  The software first ANDs the screen mask and the screen
data bit for the character beneath the cursor.  Next, the software XORs the
cursor mask and the result of the AND operation.

When a function refers to the text cursor location, it gives the coordinates of
the character beneath the cursor.

Refer  to function 10.

Hardware Text Cursor

This cursor is also available when the computer is in one of the text modes.
This cursor is the one seen on-screen when the computer is powered on.  It
consists of 8 pixels wide and 8 to 14 pixels tall.  Software allows you to use
this cursor for your needs. Scan lines determine a cursor's appearance
on-screen. A scan line consists of a horizontal set of pixels.
If a line is on, there will be flashing on the screen. If a line is off, there
is no effect. Scan lines are numbered from 0 to 7, or 0 to 11 depending on the
type of display used. 0 indicates the top scan line.

Refer to function 10.

*** 2.1 : Mouse Buttons





                                 page 2


Mouse functions can give the status of the mouse buttons and the number of times
a certain button has been pressed and released.  The button status is given as
an integer. If a bit is set to 1 the button is down; if a bit is set to 0, the
button is up.
      Bit 0 - Left Button Status
      Bit 1 - Right Button Status
      Bit 2 - Middle Button Status
Each time a mouse button is pressed, a counter records the number of presses and
releases.  The software sets the counter to zero once it has been read or after
a reset.

*** 2.2 : Unit of Distance - Mouse Motion

The motion of the mouse can be expressed in a unit of distance (mouse motion)
and is approximately 1/200 of an inch.

With mouse movement, mouse software determines a horizontal and vertical mouse
motion count.  This count is used by the software to move a cursor a certain
number of pixels on-screen.  Software defines mouse motion sensitivity (the
number of mouse motions needed to move the cursor 8 pixels on-screen) and this
sensitivity determines the rate at which the cursor moves on-screen.

Refer to function 15.

*** 2.3 : Internal Cursor Flag

Mouse software supports an internal flag.  This flag determines when the cursor
should appear on-screen.  If the flag equals 0, the cursor appears on-screen; if
the flag is any other number, the cursor disappears from the screen.

You can call functions 1 and 2 a number of times, however, if you call function
2, you must call function 1 later.  This is necessary to restore the flag's
previous value.

Refer to functions 1 and 2.

*** 3 : CALLING FROM ASSEMBLY LANGUAGE PROGRAMS

To make mouse function calls:

Load the appropriate registers (AX, BX, CX, DX) with the parameter values.
These correspond to G1%, G2%, G3%, and G4% as shown in the BASIC example to
follow.  Then execute software interrupt 51 (33H).  The values given by the
mouse functions will be installed in the registers.

Example:

   ; * set cursor to location (150,100)
   Mov AX,4    ;(function call 4)
   Mov CX,150  ;(set horizontal to 150)
   Mov DX,100  ;(set vertical to 100)
   Int 51(33H) ;(interrupt to mouse)

It is important to note that before using INT 33H, one should verify the
presence of the mouse driver.  Executing an INT 33H will cause uncertain results
if the mouse driver is not loaded.  Assume a mouse driver is present when INT
33H vector is non-zero and the vector does not point to an IRET instruction.

                                 page 3


Note:  When making a mouse call in Assembly Language, expect somewhat of a
different value for the fourth parameter (when compared with calls using a BASIC
program) involving functions 9, 12, and 16.

*** 4 : CALLING FROM BASIC LANGUAGE PROGRAM

To make  mouse function calls:

  Set a pair of integer variables in your program for the offset and the segment
  of the mouse driver entry point.

  In order to obtain the offset and segment values, the following statements
  must be inserted into your program before any calls to mouse functions:

10 DEF SEG = 0
15 ' GET GMOUSE ENTRY POINT
20 GMSEG   = PEEK( 51*4 + 2 ) + 256 * PEEK( 51*4 + 3 )   ' GET SEGMENT ENTRY
30 GMOUSE  = 2 + PEEK( 51*4 ) + 256 * PEEK( 51*4 + 1 )   ' GET OFFSET  ENTRY
40 DEF SEG = GMSEG           ' SET SEGMENT REGISTER AS THE SEGMENT OF GMOUSE

To enter the mouse driver, use the CALL statement:

  CALL GMOUSE (G1%, G2%, G3%, G4%)

GMOUSE contains the entry offset of the mouse driver.  G1%, G2%, G3%, and G4%
are the integer variables given in the call.  These four must be specified in
the CALL statement even if a value is not assigned.  When a value is assigned,
it must be an integer, that is, a whole number.

Example:

50  ' Find the Activated Mode of Genius Mouse
60  G1% = 0 : G2% = 0
70  CALL GMOUSE ( G1%, G2%, G3%, G4% )
80  IF G2% AND 2 THEN PRINT "Genius Mouse ( 2_Button Mode ) Enable"
90  IF G2% AND 3 THEN PRINT "Genius Mouse ( 3_Button Mode ) Enable"
100 IF NOT G1%   THEN PRINT "Can't Find Genius Mouse"

*** 5 : MOUSE FUNCTIONS

These functions listed apply to the Genius Mouse.  Further descriptions of each
mouse function will be given in the following pages.

Functions                                         Function Number
-----------------------------------------------------------------
Reset Genius Mouse Driver                                 0
Enable Cursor Display                                     1
Disable Cursor Display                                    2
Read Cursor Location & Button State of Genius Mouse       3
Set Cursor Location of Genius Mouse                       4
Read Button Press State of Genius Mouse                   5
Read Button Release State of Genius Mouse                 6
Define Horizontal (X) Range of Cursor Location            7
Define Vertical (Y) Range of Cursor Location              8
Define Graphics Mode Cursor Style                         9
Define Text Mode Cursor Style                            10
Read Genius Mouse Motion Number                          11

                                 page 4


Define Event Handler Entry Location                      12
Enable Light Pen Emulation Function                      13
Disable Light Pen Emulation Function                     14
Define Sensitivity (Mouse Motion/Pixel) of Genius Mouse  15
Disable Cursor Display in Special Range                  16
Define Double-Speed Threshold                            19
Swap Event Handler Entry Location                        20
Get Mouse Driver State Storage Size                      21
Save Mouse Driver state                                  22
Restore Mouse Driver state                               23
Set CRT Page Number                                      29
Read CRT Page Number                                     30

EGA functions are described in Section *** 7.

*** 6 : DESCRIPTION OF THE MOUSE FUNCTIONS

You'll notice that with the following mouse function descriptions, the
parameters needed to make the calls and the expected outcome (return) for each
is indicated. Also,  any special conditions regarding any of the mouse functions
have been included.  Further, an example of a program has been provided in order
for you to understand how to make the call.

The input and return values are presented for 8086 registers and for BASIC in
the following pages.

It is important to note that each mouse function call needs four parameters.
The Genius Mouse software does not verify any input values, and therefore, if
any incorrect values are given, uncertain results will occur.

Function 0: Reset Genius Mouse Driver

Function 0 gives the current status of the mouse hardware plus the current
status of the mouse software.  The calling program is able to determine the
presence of a mouse driver and/or a serial port.

This function resets the mouse driver to the following default status as
indicated:

Variable                                Value
------------------------------------------------------------------------------
internal cursor flag                    -1 (cursor concealed)
graphics  cursor shape                  horizontal oval
text cursor                             reverse video
user-defined call mask                  all zeroes
light pen emulation mode                enabled
vertical mouse motion/pixel ratio       16 to 8
horizontal mouse motion/pixel ratio     8 to 8
vertical min/max cursor coordinates     0/current display mode y values minus 1
horizontal min/max cursor coordinates   0/current display mode x values minus 1

8086 Register
Input:  AX = 0
Return: AX = mouse state (-1: installed, 0: not installed)
        BX = number of buttons (2 button mode, 3 button mode)



                                 page 5


BASIC
Input:  G1% = 0
Return: G1% = mouse state (-1: installed, 0: not installed)
        G2% = number of buttons (2 button mode, 3 button mode)

Example:  Used initially to determine if the GMOUSE driver is present and to
          reset GMOUSE.

50  ' Find the Actived Mode of Genius Mouse
60  G1% = 0 : G2% = 0
70  CALL GMOUSE ( G1%, G2%, G3%, G4% )
80  IF G2% AND 2 THEN PRINT "Genius Mouse ( 2_Button Mode ) Enable"
90  IF G2% AND 3 THEN PRINT "Genius Mouse ( 3_Button Mode ) Enable"
100 IF NOT G1%   THEN PRINT "Can't Find Genius Mouse"

Function 1: Enable Cursor Display

Function 1 increments the internal cursor flag counter.  If the counter is zero,
the cursor is enabled and appears on-screen.

The default value is -1 which indicates a concealed cursor.  Function 1 must be
called to display the cursor.  In case the internal cursor flag is already zero,
a call to this function produces no effect.

8086 Register
Input:  AX = 1
Return: none

BASIC
Input:  G1% = 1
Return: none

Example:

110  ' Enable Genius Mouse's Cursor
120  G1% = 1
130 CALL GMOUSE ( G1%, G2%, G3%, G4% )

Function 2: Disable Cursor Display

Function 2 disables the cursor by removing it from the screen and decrementing
the internal cursor flag.  Even though the cursor cannot be seen, it still
tracks any motion made with the mouse.

You should use this function before changing any portion of the screen
containing the cursor.  You will avoid the problem of the cursor affecting
screen data.

Keep in mind that whenever your program calls function 2, it must later call
function 1 to return the internal cursor flag to its default value.  In
addition, if your program changes the screen mode, function 2 is called
automatically. Therefore, the cursor's movement is enabled the next time it is
displayed.

Call function 2 at the end of a program in order to conceal the cursor.  This
ensures that nothing remains on-screen.


                                 page 6


8086 Register
Input:  AX = 2
Return: none

BASIC
Input:  G1% = 2
Return: none

Example:

110  ' Disable Genius Mouse's Cursor
120  G1% = 2
130 CALL GMOUSE ( G1%, G2%, G3%, G4% )

Function 3: Read Cursor Location & Button State of Genius Mouse

Function 3 gives the status of mouse buttons, plus cursor location.

Button status consists of a single integer value:
  Bit 0 = left button (2 button mode, 3 button mode)
  Bit 1 = right button (2 button mode, 3 button mode)
  Bit 2 = middle button (3 button mode)

The bit is 1 when the button is pressed.  The bit is 0 when the button is
released.

8086 Register
Input:  AX = 3
Return: BX = button status
        CX = horizontal cursor coordinate
        DX = vertical cursor coordinate

BASIC
Input:  G1% = 3
Return: G2% = button status
        G3% = horizontal cursor coordinate
        G4% = vertical cursor coordinate

Example:

110  ' Read Genius Mouse Location & Button State
120  G1% = 3
130 CALL GMOUSE ( G1%, G2%, G3%, G4% )
140 PRINT "Genius Mouse Location : X_Coord=" G3% " Y_Coord=" G4%
150 IF G2% AND 1 THEN PRINT "Left Button"
160 IF G2% AND 2 THEN PRINT "Right Button"
170 IF G2% AND 4 THEN PRINT "Middle Button"
180 PRINT "Pressed"

Function 4: Set Cursor Location of Genius Mouse

Function 4 sets the current cursor location.  Values must be within the
coordinate ranges for the virtual screen and, if necessary, are rounded to the
nearest values allowed for the current screen mode.




                                 page 7


  Screen     Display        Virtual         Cell        Bits/Pixel
   Mode      Adapter       Screen (XxY)     Size      Graphics Mode
---------  ------------  ---------------  --------   ----------------
    0      C, E, 3270     640 x 200        16 x 8          -
    1      C, E, 3270     640 x 200        16 x 8          -
    2      C, E, 3270     640 x 200         8 x 8          -
    3      C, E, 3270     640 x 200         8 x 8          -
    4      C, E, 3270     640 x 200         2 x 1          2
    5      C, E, 3270     640 x 200         2 x 1          2
    6      C, E, 3270     640 x 200         1 x 1          1
    7      M, E, 3270     640 x 200         8 x 8          -
    D      E              640 x 200        16 x 8          2
    E      E              640 x 200         1 x 1          1
    F      E              640 x 350         1 x 1          1
    10     E              640 x 350         1 x 1          1
    30     3270           720 x 350         1 x 1          1
           H              720 x 348         1 x 1          1

Display Adapter:
  M = IBM Monochrome Display/Printer Adapter
  C = IBM Color/Graphics Adapter
  E = IBM Enhanced Graphics Adapter
3270 = IBM All Points Addressable Graphics Adapter (3270 PC)
  H = Hercules Monochrome Graphics Card

8086 Register
Input:  AX = 4
        CX = new horizontal cursor coordinate
        DX = new vertical cursor coordinate
Return: none

BASIC
Input:  G1% = 4
        G3% = new horizontal cursor coordinate
        G4% = new vertical cursor coordinate
Return: none

Example:

110  ' Set Cursor Location at the Upper_Left Corner of Screen
120 G1% = 4
130 G3% = 0 : G4% = 0
140 CALL GMOUSE ( G1%, G2%, G3%, G4% )

Function 5: Read Button Press State of Genius Mouse

Function 5 provides status on the specified button, gives the number of button
presses since the last call, and produces the location of the cursor at last
button press.

Button status consists of a single integer value.  Again, as in function 3:
             Bit 0 = left button (2 button mode, 3 button mode)
             Bit 1 = right button (2 button mode, 3 button mode)
             Bit 2 = middle button (3 button mode)

The bit is 1 when the button is pressed.  The bit is 0 when the button is
released.

                                 page 8


The number of button presses will always fall in the range of 0 to 32767.  There
is no indicator for overflow.  Following this function call, the count is reset
to zero.

8086 Register
Input:  AX = 5
        BX = button status (left = 0, right = 1, middle = 2)
Return: AX = button status
        BX = number of button presses
        CX = horizontal cursor coordinate at last press
        DX = vertical cursor coordinate at last press

BASIC
Input:  G1% = 5
        G2% = button status (left = 0, right = 1, middle = 2)
Return: G1% = button status
        G2% = number of button presses
        G3% = horizontal cursor coordinate at last press
        G4% = vertical cursor coordinate at last press

Example:

110 ' Read the Left Button Press State of Genius Mouse
120 G1% = 5 : G2% = 2
130 CALL GMOUSE ( G1%, G2%, G3%, G4% )
140 IF G1% AND 2 THEN PRINT "The Middle Button Pressed at X_loc=" G3%

Function 6: Read Button Release State of Genius Mouse

Function 6 provides status on the specified button, gives the number of button
releases since the last call, and provides the location of the cursor at the
last button release.

Button status consists of a single integer value.  Again, as in function 3:
             Bit 0 = left button (2 button mode, 3 button mode)
             Bit 1 = right button (2 button mode, 3 button mode)
             Bit 2 = middle button (3 button mode)

The bit is 1 when the button is pressed.  The bit is 0 when the button is
released.

The number of button releases will always fall in the range of 0 to 32767.
There is no indicator for overflow.  Following this function call, the count is
reset to zero.

8086 Register
Input:  AX = 6
        BX = button status (left = 0, right = 1, middle = 2)
Return: AX = button status
        BX = number of button releases
        CX = horizontal cursor coordinate at last release
        DX = vertical cursor coordinate at last release

BASIC
Input:  G1% = 6
        G2% = button status (left = 0, right = 1, middle = 2)


                                 page 9


Return: G1% = button status
        G2% = number of button releases
        G3% = horizontal cursor coordinate at last release
        G4% = vertical cursor coordinate at last release

Example:

110 ' Read the Left Button Release State of Genius Mouse
120 G1% = 6 : G2% = 2
130 CALL GMOUSE ( G1%, G2%, G3%, G4% )
140 IF NOT G1% OR &HFFFB THEN PRINT "The Middle Button Released at X_loc=" G3%

Function 7: Define Horizontal (X) Range of Cursor Location

Function 7 defines the horizontal range of the cursor on-screen.  As a result,
cursor movement is limited to this specified area.  If a cursor happens to be
outside of this area when a call is made, the cursor is moved to just inside the
area.

8086 Register
Input:  AX = 7
        CX = minimum horizontal cursor coordinate
        DX = maximum horizontal cursor coordinate
Return: none

BASIC
Input:  G1% = 7
        G3% = minimum horizontal cursor coordinate
        G4% = maximum horizontal cursor coordinate
Return: none

Example:

110 ' Enable Cursor in Horizontal Range between 100 to 200
120 G1% = 7
130 G2% = 100 : G3% = 200
140 CALL GMOUSE ( G1%, G2%, G3%, G4% )

Function 8: Define Vertical (Y) Range of Cursor Location

Function 8 defines the vertical range of the cursor on-screen.  As a result,
cursor movement is limited to this specified area.  If a cursor happens to be
outside of this area when a call is made, the cursor is moved to just inside the
area.

8086 Register
Input:  AX = 8
        CX = minimum vertical cursor coordinate
        DX = maximum vertical cursor coordinate
Return: none

BASIC
Input:  G1% = 8
        G3% = minimum vertical cursor coordinate
        G4% = maximum vertical cursor coordinate
Return: none


                                 page 10


Example:

110 ' Enable Cursor in Vertical Range between 100 to 200
120 G1% = 8
130 G2% = 100 : G3% = 200
140 CALL GMOUSE ( G1%, G2%, G3%, G4% )

Function 9: Define Graphics Mode Cursor Style

Function 9 defines the style of the cursor in terms of color, shape, and center
for the graphics.  As mentioned before, this cursor is a 16-by-16 pixel block
and is defined by two 16-bit arrays (the screen mask bit and the cursor mask
bit). Cursor coordinates for the hot spot must be in the range of -16 to +16.
8086 Register
Input:  AX = 9
        BX = horizontal cursor hot spot
        CX = vertical cursor hot spot
        DX = pointer to screen and cursor mask
Return: none

BASIC
Input:  G1% = 9
        G2% = horizontal cursor hot spot
        G3% = vertical cursor hot spot
        G4% = pointer to screen and cursor mask
Return: none

Example:

10  ' Define the screen mask
20  '
30    cursor (0,0)  = &HFFFF       '1111111111111111
40    cursor (1,0)  = &HFFFF       '1111111111111111
50    cursor (2,0)  = &HFFFF       '1111111111111111
60    cursor (3,0)  = &HFFFF       '1111111111111111
70    cursor (4,0)  = &HFFFF       '1111111111111111
80    cursor (5,0)  = &HF00F       '1111000000001111
90    cursor (6,0)  = &H0000       '0000000000000000
100   cursor (7,0)  = &H0000       '0000000000000000
110   cursor (8,0)  = &H0000       '0000000000000000
120   cursor (9,0)  = &H0000       '0000000000000000
130   cursor (10,0) = &HF00F       '1111000000001111
140   cursor (11,0) = &HFFFF       '1111111111111111
150   cursor (12,0) = &HFFFF       '1111111111111111
160   cursor (13,0) = &HFFFF       '1111111111111111
170   cursor (14,0) = &HFFFF       '1111111111111111
180   cursor (15,0) = &HFFFF       '1111111111111111
190 '
200 ' Define the cursor mask
210 '








                                 page 11


220   cursor (0,1)  = &H0000       '0000000000000000
230   cursor (1,1)  = &H0000       '0000000000000000
240   cursor (2,1)  = &H0000       '0000000000000000
250   cursor (3,1)  = &H0000       '0000000000000000
260   cursor (4,1)  = &H0000       '0000000000000000
270   cursor (5,1)  = &H0000       '0000000000000000
280   cursor (6,1)  = &H07E0       '0000011111100000
290   cursor (7,1)  = &H7FFE       '0111111111111110
300   cursor (8,1)  = &H7FFE       '0111111111111110
310   cursor (9,1)  = &H07E0       '0000011111100000
320   cursor (10,1) = &H0000       '0000000000000000
330   cursor (11,1) = &H0000       '0000000000000000
340   cursor (12,1) = &H0000       '0000000000000000
350   cursor (13,1) = &H0000       '0000000000000000
360   cursor (14,1) = &H0000       '0000000000000000
370   cursor (15,1) = &H0000       '0000000000000000
380 '
390 ' Set the cursor style and hot spot number of Genius Mouse
400 '
410 '
420   G1% = 9
430   G2% = 6 ' horizontal hot spot
440   G3% = 5 ' vertical hot spot
450   CALL GMOUSE ( G1%, G2%, G3%, cursor (0,0))

Function 10: Define Text Mode Cursor Style

Function 10 chooses the hardware or the software text cursor.

For example, if BX (G2%) is 1, the hardware cursor is selected and the hardware
is set up with the first and last scan lines which define the cursor.
(Values for CX (G3%) and DX (G4%) range from 0 to 7 for the color display and 0
to 11 for the monochrome display.)

If BX (G2%) is 0, the software cursor is selected; and CX (G3%) and DX (G4%)
must specify the screen and cursor masks.  (These masks give the attributes and
character code of the cursor, and their values are dependent on the type of
display in use.)

8086 Register
Input:  AX = 10
        BX = select cursor (0: software text, 1: hardware text)
        CX = screen mask value/scan line start
        DX = cursor mask value/scan line stop
Return: none

BASIC
Input:  G1% = 10
        G2% = select cursor (0: software text, 1: hardware text)
        G3% = screen mask value/scan line start
        G4% = cursor mask value/scan line stop
Return: none

Example:




                                 page 12


110 ' Enable an Inverting Cursor
120 G1% = 10
130 G2% = 0
140 G3% = &HFFFF  :  G4% = &H7700
150 CALL GMOUSE ( G1%, G2%, G3%, G4% )

Function 11: Read Genius Mouse Motion Number

Function 11 gives the mouse motion number since the last call.  A positive
horizontal number indicates rightward movement (negative shows leftward
movement).  A positive vertical number indicates downward movement (negative
shows upward movement).
The number is always in the range of -32768 to 32767.  Overflow is disregarded.
Once the call is completed, the number is set to 0.

8086 Registers
Input:  AX = 11
Return: CX = horizontal number
        DX = vertical number

BASIC
Input:  G1% = 11
Return: G3% = horizontal number
        G4% = vertical number

Example:

110 ' Read Genius Mouse Motion Number
120 G1% = 11
130 CALL GMOUSE ( G1%, G2%, G3%, G4% )
140 IF G3% > 0 THEN PRINT "Genius Mouse is Moving to Right"
150 IF G4% > 0 THEN PRINT "Genius Mouse is Moving Down"

Function 12: Define Event Handler Entry Location

Function 12 defines the address entry location of an event handler routine which
is called when a certain event (defined by the call mask) occurs.  The program
is temporarily interrupted by the mouse driver. At the end of the event handler
routine  the program continues at the point it was interrupted.

The call mask is a single integer value defining the conditions which will cause
an interrupt.

A specific condition corresponds to a bit in the call mask:

Mask Bit                Condition
--------------------------------------------------
   0                    cursor location changed
   1                    left button pressed
   2                    left button released
   3                    right button pressed
   4                    right button released
   5                    middle button pressed
   6                    middle button released
   7 - 15               not used



                                 page 13


In order to call the event handler routine, set the mask bit to 1 and put the
mask in at CX (G3%).  To disable, set the mask bit to 0 and put the mask in at
CX (G3%).  Always be sure to set the call mask to 0 before the program finishes.
(Leave the system in the same state upon exit as if was upon entrance.)

8086 Register
Input:  AX = 12
        CX = call mask
        ES:DX = pointer to event handler routine
Return: none

BASIC
Input:  G1% = 12
        G3% = call mask
        G4% = pointer to event handler routine
Return: none

Example:


110 ' Active BUTTDOWN Event Handler Routine, When One or More Buttons Pressed
120 G1% = 12
130 G3% = &H002A  :  G4% = BUTTDOWN%
140 CALL GMOUSE ( G1%, G2%, G3%, G4% )

Function 13: Enable Light Pen Emulation Function

Function 13 permits the mouse to act like a light pen.  When in this mode, calls
to the pen function will give the cursor coordinates at the last pen down
location.

Note that the status of "pen down" and "pen off-screen" is controlled by the
mouse buttons:  all buttons up, pen off-screen; one button pressed, pen down.

Light pen emulation is ON after each call to function 0 (Reset Mouse Driver).

8086 Register
Input:  AX = 13
Return: none

BASIC
Input:  G1% = 13
Return: none

Example:

110 ' Enable Light Pen Emulation Function
120 G1% = 13
130 CALL GMOUSE ( G1%, G2%, G3%, G4% )

Function 14: Disable Light Pen Emulation Function

Function 14 turns off the light pen emulation mode.  When disabled, any call to
the pen function will give information only about a real light pen.

8086 Register
Input:  AX = 14

                                 page 14


Return: none

BASIC
Input:  G1% = 14
Return: none

Example:

110 ' Disable Light Pen Emulation Function
120 G1% = 14
130 CALL GMOUSE ( G1%, G2%, G3%, G4% )

Function 15: Define Sensitivity (Mouse Motion/Pixel) of Genius Mouse

Function 15 defines mouse sensitivity as determined by the mouse motion/pixel
ratio.  This is a way of setting the amount of cursor motion wanted for mouse
movement.  These ratios specify mouse motion per 8 pixels.  These values must
be in the range of 1 to 32767.  With a larger ratio, the cursor movement is
shortened for each mouse movement.

Default values:   horizontal ratio - 8  mouse motions to 8 pixels
                  vertical ratio   - 16 mouse motions to 8 pixels

Note: 1 mouse motion = 1/200 of an inch increment

8086 Register
Input:  AX = 15
        CX = horizontal mouse motion counts to pixel ratio
        DX = vertical mouse motion counts to pixel ratio
Return: none

BASIC
Input:  G1% = 15
        G3% = horizontal mouse motion counts to pixel ratio
        G4% = vertical mouse motion counts to pixel ratio
Return: none

Example:

110 ' Define Horizontal Sensitivity as 8
120 ' Define Vertical Sensitivity as 16
130 G1% = 15
140 G3% =  8
150 G4% = 16
160 CALL GMOUSE ( G1%, G2%, G3%, G4% )

Function 16: Disable Cursor Display in Special Range

Function 16 sets up a special range on-screen.  If the cursor moves to this area
or is in this area, it will be disabled.  After a call is made to this function,
it is necessary to call function 1 to enable the cursor again.

Define the special range with screen location values using four components:





                                 page 15


Components          Values
--------------------------------------------------------
    1               Left horizontal screen location
    2               Upper vertical screen location
    3               Right horizontal screen location
    4               Lower vertical screen location

8086 Register
Input:  AX = 16
        ES:DX = pointer to special range
Return: none

BASIC
Input:  G1% = 16
        G4% = pointer to special range
Return: none

Example:

110 ' Disable Cursor Display in (0,0) to (100,100) Range
120 G1% = 16
130 RANGE%(1) = 0   : RANGE%(2) = 0
140 RANGE%(3) = 100 : RANGE%(4) = 100
150 CALL GMOUSE ( G1%, G2%, G3%, RANGE%(0) )
 .
 .
 .

500 ' Enable Cursor Display Again
510 G1% = 1
520 CALL GMOUSE ( G1%, G2%, G3%, G4% )

Function 19: Define Double-Speed Threshold

Function 19 defines the threshold value (mouse motion per second) for doubling
the cursor's motion.  Should the mouse move faster than the DX (G4%) value, the
cursor motion doubles.  The default value is 64 mouse motions per second.

If you should want to disable double-speed, just set the threshold to 32767
(7FFFH) mouse motions/second.

8086 Register
Input:  AX = 19
        DX = threshold speed in mouse motions/second
Return: none

BASIC
Input:  G1% = 19
        G4% = threshold speed in mouse motions/second
Return: none

Example:

110 ' Define Double-Speed Threshold as 20 Mouse Motions/Second




                                 page 16


120 G1% = 19
130 G4% = 20
140 CALL GMOUSE ( G1%, G2%, G3%, G4% )




500 ' Disable Double-Speed Threshold Function
510 G1% = 19
520 G4% = 256 'MAX. VALUE
530 CALL GMOUSE ( G1%, G2%, G3%, G4% )

Function 20: Swap Event Handler Entry Location

Function 20 sets new values for the call mask and event handler routine
address  for mouse  hardware interrupts and return the values that were
previously specified.

For detail information to reference Function 12 description.

8086 Register
Input:  AX = 20
        CX = new call mask
        ES:DX = new pointer to event handler routine
Return: CX = old call mask
        ES:DX = old pointer to event handler routine

BASIC
Input:  G1% = 20
        G3% = call mask
        G4% = pointer to event handler routine
Return: G3% = old call mask
        G4% = old pointer to event handler routine

Example:

100 ' Swap Event Handler Entry Location
110 ' Active BUTTDOWN Event Handler Routine, When One or More Buttons Pressed
120 G1% = 20
130 G3% = &H002A  :  G4% = BUTTDOWN%
140 CALL MOUSE ( G1%, G2%, G3%, G4% )

Function 21: Get Mouse Driver State Storage Size

Function 21 returns the size of the buffer required to store the current state
of the  mouse  driver.  It is used with  functions 22  and 23 when you want to
temporarily  interrupt a program  that is using the mouse  and execute another
that also uses the mouse.

8086 Register
Input:  AX = 21

Return: BX = buffer size required for mouse driver state

BASIC
Input:  G1% = 21


                                 page 17


Return: G2% = buffer size required for mouse driver state

Example:

110 ' Get Mouse Driver State Storage Size
120 G1% = 21
130 CALL MOUSE ( G1%, G2%, G3%, G4% )
140 STATESIZE% = G2%

Function 22: Save Mouse Driver state

Function 22 saves the current mouse driver state in a buffer allocated by your
program.   It is used with  functions 21  and 23  when you want to temporarily
interrupt a program  that is using the mouse  and execute another program that
also uses the mouse.

Before your program  calls function 22, the program should call function 21 to
determine  the buffer size required  for saving the  mouse driver state,  then
allocate the appropriate amount of memory.

8086 Register
Input:  AX = 22
        ES:DX = pointer to the buffer
Return: None

BASIC
Input:  G1% = 22
        G4% = pointer to the buffer
Return: None

Example:

110 ' Save The Mouse Driver State
120 G1% = 22
130 G4% =  BUFPTR
140 ' Assume BUFPTR contains the address of the buffer
150 CALL MOUSE ( G1%, G2%, G3%, G4% )

Function 23: Restore Mouse Driver State

Function 23 restores the last  mouse driver state saved by function 22.  It is
used with functions 21 and 22 when you want to temporarily interrupt a program
that is  using the mouse  and execute another program that also uses the mouse.
To restore the mouse driver state saved by function 22, call function 23 at the
end of the interrupt program.

8086 Register
Input:  AX = 23
        ES:DX = pointer to the buffer
Return: None

BASIC
Input:  G1% = 23
        G4% = pointer to the buffer
Return: None

Example:

                                 page 18


110 ' Restore The Mouse Driver State
120 G1% = 23
130 G4% =  BUFPTR
140 ' Assume BUFPTR contains the address of the buffer
150 CALL MOUSE ( G1%, G2%, G3%, G4% )

Function 29: Set CRT Page Number

Function 29 specifies the CRT page on which the mouse cursor will be displayed.

For information on the number of CRT pages available in each display mode your
adapter supports, see the documentation that came with the graphics adapter.

8086 Register
Input:  AX = 29
        BX = CRT page for mouse cursor display
Return: none

BASIC
Input:  G1% = 29
        G2% = CRT page for mouse cursor display
Return: none

Example:

110 ; Set CRT page 2 for display mouse cursor
120 G1% = 29
130 G2% = 2
140 CALL MOUSE ( G1%, G2%, G3%, G4% )
 .
 .
 .

500 ; Enable Cursor Display Again
510 G1% = 1
520 CALL MOUSE ( G1%, G2%, G3%, G4% )

Function 30: Read CRT Page Number

Function 30 returns the number of the CRT page on which the mouse cursor is
displayed.

8086 Register
Input:  AX = 30

Return: BX = CRT page number of current cursor display

BASIC
Input:  G1% = 30

Return: G2% = CRT page number of current cursor display

Example:

110 ; Read CRT page number
120 G1% = 30
130 CALL MOUSE ( G1%, G2%, G3%, G4% )

                                 page 19


*** 7 : USING GENIUS MOUSE WITH IBM ENHANCED GRAPHICS ADAPTER

Within the Genius Mouse driver, you'll find nine EGA functions.  These functions
permit your program to write to and read from write-only registers.

The cursor in use is defined as a monochrome cursor with one bit per pixel.  The
bit masks are determined by function 9 and apply to all active planes.

In order to make an EGA function call from an Assembly-Language program, first
load the AX, BX, CX, DX, and ES registers with the values indicated for the
parameters.  Note that five values must be given for a high level language
program.  Next, execute software interrupt 16 (10h). The values that are
returned are intalled in the registers by EGA functions.

Upon start with DOS, PC BIOS will verify if the EGA BIOS exists.  When this is
verified, the PC will execute the EGA BIOS, booting up the program to write the
INT 10h entry vector to the address of the INT 42h vector.  Now, EGA BIOS
address will be written to INT 10h. Following this, you are able to call EGA
BIOS (by using INT 10h) and PC video BIOS (by using INT 42h).

There are twenty functions in EGA BIOS.  (PC BIOS has only 16.) The EGA BIOS
routines only intercept the BIOS ROM video routines (INT 10h, AH = 13h or less).

The following indicates nine EGA functions and the corresponding function
number:

Function                                             Number (HEX)
-----------------------------------------------------------------
Retrieve Single Data                                       F0
Save Single Data                                           F1
Retrieve Registers on a Specified Port                     F2
Save Registers on a Specified Port                         F3
Retrieve Several Registers Data                            F4
Save Several Registers Data                                F5
Reset All Registers as Initial Values                      F6
Set Initial Values                                         F7
Get Version Number of Genius Mouse Driver                  FA

In the above functions, the EGA I/O port number and address are as follows:

Port No.  Register Name   No. of Registers  Index No.  Address Select Register
------------------------------------------------------------------------------
 00H      CRT Controller         25           0 - 24            3x4H
 08H      Sequencer               5           0 - 4             3C4H
 10H      Graphics Controller     9           0 - 8             3CEH
 18H      Attribute Controlle    20           0 - 19            3C0H
          Singular Registers
 20H      Miscellaneous Output    1           ignored           3C2H
 28H      Feature Control         1           ignored           3xAH
 30H      Graphics 1 Position     1           ignored           3CCH
 38H      Graphics 2 Position     1           ignored           3CAH

  Note: x = B or D depending on the base I/O address;
        determined by Miscellaneous Output Register bit 1.




                                 page 20


Function F0: Retrieve Single Data

This function retrieves data from a single register.

Input:  AH = F0H
        BX = Index number
        DX = Port number
Return: BL = Retrieved data from EGA register


Example:

FUN_F0     EQU     0f0H         ; Function F0
;
GR_CONTR   EQU     010H         ; Graphics Controller
MODE_REG   EQU     005H         ; Mode Regisiter
;
GR1_PORT   EQU     030H         ; Graphics 1 Position Register
GR2_PORT   EQU     038H         ; Graphics 2 Position Register
;
VIDEO      EQU     010H         ; BIOS ROM Video Routine Entry

           ; Retrieve the Mode Register in Graphics Controller
MODE_REG   DB      00
           ;
           MOV     DX, GR_CONTR
           MOV     BX, MODE_REG
           MOV     AH, FUN_F0
           INT     VIDEO
           MOV     MODE_REG, BL


           ; Retrieve Graphics 1 Position Data
GR1_POS    DB      00
           ;
           MOV     DX, GR1_POS
           MOV     AH, FUN_F0
           INT     VIDEO
           MOV     GR1_POS, NL


Function F1: Save Single Data

This function saves data to an EGA register.  Upon finishing a call to this
function, the BH and DX values are altered.

Input:  AH = F1H
        BL = Index number (Non-single register only)
           = Data (Single register only)
        BH = Data (Non-single register only)
           = Disregard (Single register only)
        DX = Port number
Return: None


Example:


                                 page 21


FUN_F1     EQU     0f1H         ; Function F1
;
SEQUENCE   EQU     008H         ; Sequencer
MASK_REG   EQU     002H         ; Map Mask Register
;
FEAT_PORT  EQU     028H         ; Feature Control Register
;
VIDEO      EQU     010H         ; BIOS ROM Video Routine Entry

           ; Save Map Mask Register of Sequencer
MAP_MASK   EQU     03H
           ;
           MOV     DX, SEQUENCE
           MOV     BL, MASK_REG
           MOV     BH, MAP_MASK
           MOV     AH, FUN_F1
           INT     VIDEO
           MOV     MAP_MASK, BL


           ; Save Feature Control Register
FEATURE    DB      02H
           ;
           MOV     DX, FEAT_PORT
           MOV     BL, FEATURE
           MOV     AH, FUN_F1
           INT     VIDEO
           MOV     FEATURE, BL

Function F2: Retrieve Registers on a Specified Port

This function retrieves data from registers on a specific port.  Upon finishing
a call to this function, the CX value is altered.

Input:  AH = F3H
        CH = Starting index number
        CL = Number of registers
        DX = Port number
        ES:BX = Destination of returned data
Return: Returned data to destination address

Example:

FUN_F2     EQU     0f2H         ; Function F2
;
GR_CONTR   EQU     010H         ; Graphics Controller
;
VIDEO      EQU     010H         ; BIOS ROM Video Routine Entry


           ; Retrieve Four Registers Data from Graphics Controller
GRAPH_POOL DB      04   DUP (0)
           ;
           MOV     DX, DS
           MOV     ES, DX
           ;


                                 page 22


           MOV     DX, GR_CONTR
           MOV     BX, OFFSET GRAPH_POOL
           MOV     CX, 04H
           MOV     AH, FUN_F2
           INT     VIDEO

Function F3: Save Registers on a Specified Port

This function saves data from registers on a specific port.  Upon finishing a
call to this function, the BX, CX, and DX values are altered.

Input:  AH = F3H
        CH = Starting index number
        CL = Number of register
        DX = Port number
        ES:BX = Address source of incoming data
Return: None

Example:

FUN_F3     EQU     0f3H         ; Function F3
;
ATTR_CONTR EQU     018H         ; Attribute Controller
;
VIDEO      EQU     010H         ; BIOS ROM Video Routine Entry


           ; Save Four Registers Data into Attribute Controller
PALET_DATA DB      1, 2, 4, 3
           ;
           MOV     DX, DS
           MOV     ES, DX
           ;
           MOV     DX, ATTR_CONTR
           MOV     BX, OFFSET PALET_DATA
           MOV     CX, 08
           MOV     AH, FUN_F3
           INT     VIDEO

Function F4: Retrieve Several Registers Data At The Same Time

This function retrieves data from several registers at the same time.  Upon
finishing a call to this function, the CX value is altered.

Input:  AH = F4H
        CX = Number of registers (more than 1)
        ES:BX = Address of register packet (each consists of 4 bytes;
                port  address,  byte 1-2;  index number,  byte 3;
                returned data, byte 4)
Return: Returned data is saved into byte 4

Example:

FUN_F4     EQU     0f4H         ; Function F4
;
VIDEO      EQU     010H         ; BIOS ROM Video Routine Entry


                                 page 23


            ; Retrieve Follow  Registers Data
TABLE       DW     030H         ; Graphics 1 Position Register
            DB      00          ; Single Register
            DB      00          ; Retrieved Data
            ;
            DW     010H         ; Graphics Controller
            DB      05          ; Mode Register
            DB      00          ; Retrieved Data
            ;
            ;
            MOV    DX, DS
            MOV    ES, DX
            ;
            MOV    BX, OFFSET TABLE
            MOV    CX, 02
            MOV    AH, FUN_F4
            INT    VIDEO


Function F5: Save Several Registers Data At The Same Time

This function saves data from several registers at the same time.  Upon
finishing a call to this function, the CX value is altered.

Input:  AH = F5H
        CX = Number of registers (more than 1)
        ES:BX = Address of register packet (each consists of 4 bytes;
                port  number, byte 1-2;  index number,  byte 3;
                output data, byte 4)
Return: None

Example:

FUN_F5     EQU     0f5H         ; Function F5
;
VIDEO      EQU     010H         ; BIOS ROM Video Routine Entry

            ; Save Follow Registers Data
TABLE       DW      20H         ; Miscellaneous
            DB      00          ; Single Register
            DB      01          ; Data
            ;
            DW      18H         ; Attribute Controller
            DB      12H         ; Color Plane Enable
            DB      07H         ; Data
            ;
            ;
            MOV    DX, DS
            MOV    ES, DX
            ;
            MOV    BX, OFFSET TABLE
            MOV    CX, 02
            MOV    AH, FUN_F5
            INT    VIDEO




                                 page 24


Function F6: Reset All Registers as Initial Values

This function resets all values to default values for the specific registers.
Function 7 sets the default values.

Input:  AH = F6H
Return: None

Example:

FUN_F6     EQU     0f6H         ; Function F6h
;
VIDEO      EQU     010H         ; BIOS ROM Video Routine Entry

           MOV     AH, FUN_F6
           INT     VIDEO

Function F7: Set Initial Values

This function sets the initial default values.  Upon finishing a call to this
function, the BX and DX values are altered.

Input:  AH = F7H
        DX = Port number
        ES:BX = Table of output data
Return: None

Example:

FUN_F7     EQU     0f7H         ; Function F7
;
ATTR_CONTR EQU     018H         ; Attribute Controller
;
VIDEO      EQU     010H         ; BIOS ROM Video Routine Entry

           ; Setting Initial Values for the Attribute Controller
ATTR_DATA  DB      1,  2,  4,  3,  5,  6,  0,  7
           DB      0,  0,  0,  0,  0,  0,  0,  0
           DB      0,  0, 0fh, 0
           ;
           MOV     DX, DS
           MOV     ES, DX
           ;
           MOV     DX, ATTR_CONTR
           MOV     BX, OFFSET ATTR_DATA
           MOV     AH, FUN_F7
           INT     VIDEO

Function FA: Get Version Number of Genius Mouse Driver

This function will give the Genius Mouse driver version number.

Input:  AH = FAH
        BX = 00H
Return: ES:BX = Pointer to Genius Mouse driver version number.



                                 page 25

------HERE COMES GRAPHICS FAQ !!!!-----

ZDDDDDDDDDDDDDDBDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
3 Introduction 3
@DDDDDDDDDDDDDDY

Bresenham is a pretty smart cookie (note the use of the word "is", last I
heard he was still working for IBM). This file contains the algorithms he
developped for drawing lines and circles on a pixelated display system
such as the VGA.

ZDDDDDDDDDDDDDDDDBDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
3 Line Algorithm 3
@DDDDDDDDDDDDDDDDY

The basic algorithm works for lines which look like this:


      o-------                         ?
     p1       --------                 3 deltay
                      -------      p2  3
                             -------o  Y

      @DDDDDDDDDDDDDDDDDDDDDDDDDDDDY
                  deltax

where p1 = (x1,y1),
      p2 = (x2, y2),
      x and y are both increasing from p1 to p2,
      deltax = x2 - x1,
      deltay = y2 - y1 and
      deltax >= deltay.

All other types of lines can be derived from this type. I'll get to this
bit later.

First you need to perform the following intialisation:

x = x1
y = y1
d = (2 * deltay) - deltax

x is the current x location, you will add 1 to this variable after every
pixel you draw until all pixels have been drawn.
y is the current y location. The decision variable is used to determine
when to add 1 to this value. d is the decision variable which will be used
to keep a track of what to do.

Now you loop across the screen from x1 to x2 and for each loop perform the
following operations for each pixel :

PutPixel(x, y);  { Draw a pixel at the current point }
if d < 0 then
    d := d + (2 * deltay)
else
  begin
    d := d + 2 * (deltay - deltax);
    y := y + 1;
  end;
x := x + 1;

It's that simple!

ZDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDBDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
3 Speeding Up The Line Algorithm 3
@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDY

There are several useful techniques for speeding up Bresenhams line
algorithm.

For starters, notice that all multiplications are by 2. This can be
performed with a simple shift left instruction (Shl in Pascal, << in C).

Next notice that the values you add to the decision variable do not change
throughout the loop, so they can be precalculated beforehand.

One property of lines is that they are symetrical about their mid-points,
and we can use this property to speed up the algorithm. Store two x and y
values, (xa, ya) and (xb, yb). Have each pair start on either end of the
line. For each pass through the loop you draw the pixel at both points, add
1 to xa and subtract one from xb. When d >= 0 add 1 to ya and subtract one
from yb. You then only need to loop until xa = xb.

It's also obvious that if the decision variable becomes the same value
it was when it was initialised, then the rest of the line is just
copies of the line you have already drawn up to that point. You might be
able to speed the algorithm up by keeping an array of how y has been
modified and then use this array if the line starts repeating itself. If
you are using the Intel registers to store all values then you probably
wouldn't get much of a speed increase (in fact it could slow it down), but
it would probably be useful for thing like linear texture mapping (discussed
below). I've never actually tried implementing this technique, and I would
like to hear the results if anyone does.

Above all remember that these optimisations will only significantly speed
up the line drawing algorithm if the whole thing is done in assembly. A
profile of the example program at the end of this file showed that 40% of
CPU time was spent in the slow PutPixel routine I was using, the loop
mechanics and testing the sign of the decision variable.

ZDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDBDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
3 Other Uses for the Line Algorithm 3
@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDY

A line can be represented by the equation y = mx + c, where
m = deltay / deltax. Note that this is a version of the standard linear
equation ax + bx + c = 0. There are many algorithms which use this equation.

One good use for the bresenham line algorithm is for quickly drawing filled
concave polygons (eg triangles). You can set up an array of minimum and
maximum x values for every horizontal line on the screen. You then use
bresenham's algorithm to loop along each of the polygon's sides, find where
it's x value is on every line and adjust the min and max values accordingly.
When you've done it for every line you simply loop down the screen drawing
horizontal lines between the min and max values for each line.

Another area is in linear texture mapping (see the PC-GPE article on texture
mapping). This method involves taking a string of bitmap pixels and
stretching them out (or squashing them in) to a line of pixels on the screen.
Typically you would draw a vertical line down the screen and use Bresenhams
to calculate which bitmap pixel should be drawn at each screen pixel.

ZDDDDDDDDDDDDDDDDDDBDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
3 Circle Algorithm 3
@DDDDDDDDDDDDDDDDDDY

Circles have the property of being highly symetrical, which is handy
when it comes to drawing them on a display screen.

      |y          (This diagram is supposed to be a circle, try viewing
      |           it in 50 line mode).
  \ ..... /
   .  |  .        We know that there are 360 degrees in a circle. First we
  . \ | / .       see that a circle is symetrical about the x axis, so
  .  \|/  .       only the first 180 degrees need to be calculated. Next
--.---+---.--     we see that it's also symetrical about the y axis, so now
  .  /|\  . x     we only need to calculate the first 90 degrees. Finally
  . / | \ .       we see that the circle is also symetrical about the 45
   .  |  .        degree diagonal axis, so we only need to calculate the
  / ..... \       first 45 degrees.
      |
      |

Bresenhams circle algorithm calculates the locations of the pixels in the
first 45 degrees. It assumes that the circle is centered on the origin. So
for every pixel (x,y) it calculates we draw a pixel in each of the 8 octants
of the circle :

PutPixel(CenterX + X, Center Y + Y)
PutPixel(CenterX + X, Center Y - Y)
PutPixel(CenterX - X, Center Y + Y)
PutPixel(CenterX - X, Center Y - Y)
PutPixel(CenterX + Y, Center Y + X)
PutPixel(CenterX + Y, Center Y - X)
PutPixel(CenterX - Y, Center Y + X)
PutPixel(CenterX - Y, Center Y - X)

So let's get into the actual algorithm. Given a radius for the circle
we perform this initialisation:

d := 3 - (2 * RADIUS)
x := 0
y := RADIUS

Now for each pixel we do the following operations:

Draw the 8 circle pixels
if d < 0 then
    d := d + (4 * x) + 6
else
  begin
    d := d + 4 * (x - y) + 10
    y := y - 1;
  end;

And we keep doing this until x = y. Note that the values added to the
decision variable in this algorithm (x and y) are constantly changing, so
we cannot precalculate them. The muliplications however are by 4, and we
can accomplish this by shifting left twice.


ZDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDBDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
3 A Pascal General Line Procedure 3
@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDY

The basic bresenham line algorithm can be modified to handle all types of
lines. In this section assume that deltax = abs(x2 - x1) and
deltay = abs(y2 - y1).

First let's take lines where deltax >= deltay. Now if x1 > x2 then you will
need to subtract 1 from x for every pass through the loop. Similarly if y1 >
y2 then you will be also need to subtract 1 from y for every pass through the
loop where d < 0.

Lines where deltax < deltay can be handled the same way, you just swap all
the deltax's and deltay's around.

The fastest method of handling all cases is to write a custom routine for
each of the 8 line types:

1) x1 <= x2, y1 <= y2, deltax >= deltay
2) x1 <= x2, y1 <= y2, deltax <  deltay
3) x1 <= x2, y1 >  y2, deltax >= deltay
4) x1 <= x2, y1 >  y2, deltax <  deltay
5) x1 >  x2, y1 <= y2, deltax >= deltay
6) x1 >  x2, y1 <= y2, deltax <  deltay
7) x1 >  x2, y1 >  y2, deltax >= deltay
8) x1 >  x2, y1 >  y2, deltax <  deltay

This will give you the fastest results, but will also make your code 8
times larger! Alternatively you can declare a few extra variables and
use a common inner loop for all lines:

numpixels = number of pixels to draw
          = deltax if deltax >= deltay or
          = deltay if deltax < deltay
dinc1 = the amount to add to d when d < 0
dinc2 = the amount to add to d when d >= 0
xinc1 = the amount to add to x when d < 0
xinc2 = the amount to add to x when d >= 0
yinc1 = the amount to add to y when d < 0
yinc2 = the amount to add to y when d >= 0

The following is a simple example program which uses this technique:


DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD

{

BRESLINE.PAS - A general line drawing procedure.
               By Mark Feldman

This is a very simple implementation of bresenhams' line algorithm with
no optimisations. It can draw about 6000 random lines a second in mode 13h
on my 486SX33 with sloooooow Paradise Extended VGA.

}

procedure Line(x1, y1, x2, y2 : integer; color : byte);
var i, deltax, deltay, numpixels,
    d, dinc1, dinc2,
    x, xinc1, xinc2,
    y, yinc1, yinc2 : integer;
begin

  { Calculate deltax and deltay for initialisation }
  deltax := abs(x2 - x1);
  deltay := abs(y2 - y1);

  { Initialize all vars based on which is the independent variable }
  if deltax >= deltay then
    begin

      { x is independent variable }
      numpixels := deltax + 1;
      d := (2 * deltay) - deltax;
      dinc1 := deltay Shl 1;
      dinc2 := (deltay - deltax) shl 1;
      xinc1 := 1;
      xinc2 := 1;
      yinc1 := 0;
      yinc2 := 1;
    end
  else
    begin

      { y is independent variable }
      numpixels := deltay + 1;
      d := (2 * deltax) - deltay;
      dinc1 := deltax Shl 1;
      dinc2 := (deltax - deltay) shl 1;
      xinc1 := 0;
      xinc2 := 1;
      yinc1 := 1;
      yinc2 := 1;
    end;

  { Make sure x and y move in the right directions }
  if x1 > x2 then
    begin
      xinc1 := - xinc1;
      xinc2 := - xinc2;
    end;
  if y1 > y2 then
    begin
      yinc1 := - yinc1;
      yinc2 := - yinc2;
    end;

  { Start drawing at <x1, y1> }
  x := x1;
  y := y1;

  { Draw the pixels }
  for i := 1 to numpixels do
    begin
      PutPixel(x, y, color);
      if d < 0 then
        begin
          d := d + dinc1;
          x := x + xinc1;
          y := y + yinc1;
        end
      else
        begin
          d := d + dinc2;
          x := x + xinc2;
          y := y + yinc2;
        end;
    end;
end;

DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD






Note that if you are writing a line routine for mode 13h (for example) you
can speed it up by converting the inner loop to assembly and including
mode 13h specific code. This portion of the above routine works the same but
the <x, y> values are stored in a single variable (screen) which holds the
memory address of the current pixel, screeninc1 and screeninc2 are the
update values for screen.

DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD

var screen : word;
    screeninc1, screeninc2 : integer;
     .
     .
     .
  { Start drawing at <x1, y1> }
  screen := word(y1) * 320 + x1;
  screeninc1 := yinc1 * 320 + xinc1;
  screeninc2 := yinc2 * 320 + xinc2;

  { Draw the pixels }
  asm

    { Use as many registers as are available }
    push $A000
    pop es
    mov di, screen
    mov dx, d
    mov al, color
    mov cx, numpixels
    mov bx, dinc1

    @bres1:

    { Draw the current pixel and compare the decision variable to 0 }
    mov es:[di], al
    cmp dx, 0
    jnl @bres2

    { D < 0 }
    add dx, bx { bx = dinc1 }
    add di, screeninc1
    jmp @bres3

    @bres2:

    { D >= 0 }
    add dx, dinc2
    add di, screeninc2

    @bres3:

    loop @bres1
  end;

DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD


Well hope this is enough for you !!!
0
 
LVL 6

Expert Comment

by:thresher_shark
ID: 1178428
Too bad it's assembly and pascal rather than C/C++.
0
 

Author Comment

by:pr12
ID: 1178429
This is not really helpful because all the code is in BASIC and I wanted some help in C++, but it helped me in understanding the working of the mouse and since then I have succeded in developing my own program to do the same.Thanks any way
With regards
Bart
0
 
LVL 6

Expert Comment

by:thresher_shark
ID: 1178430
You should have Rejected the answer then, I am certain that if you had left it open you could have gotten a sufficient answer.
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now