Home Memoirs of a Gamer Movies I watched Guidebook Links

the Lobdegg's Comprehensive Guidebook to DOS Programming

Chapter 3 - Input

Section 3: Mouse Support

Initialization
Updating Our Status
Clean Up
References

Introduction

Initialization

Initialization of the mouse really breaks down to 4 steps:

Fortunately there are software interrupts provided by BIOS that can help us perform these tasks!

Resetting the Mouse
Assembly Borland Turbo C++ /
Open Watcom 16bit
Open Watcom 32bit
    xor ax, ax
    int 0x33
union REGS regs;
regs.x.ax = 0;
int86(0x33, &regs, &regs);
union REGS regs;
regs.x.ax = 0;
int386(0x33, &regs, &regs);

After executing int 33, whether our mouse is detected will be stored in AX (0 for no, -1 for yes) and the number of buttons detected will be stored in BX. Keep in mind that in the DOS days only 2 buttons were thought of as standard. Middle mouse button was fit into the spec but it wasn't common place until well into the Windows era. Sadly no scroll wheel was available in DOS.

Centering the Mouse
Assembly Borland Turbo C++ /
Open Watcom 16bit
Open Watcom 32bit
    mov ax, 4
    mov cx, 160
    mov dx, 100
    int 0x33
union REGS regs;
regs.x.ax = 4;
regs.x.cx = 160;
regs.x.dx = 100;
int86(0x33, &regs, &regs);
union REGS regs;
regs.x.ax = 4;
regs.x.cx = 160;
regs.x.dx = 100;
int386(0x33, &regs, &regs);

So let's move the mouse pointer to the center of the screen. We'll assume that we're using 320x200 as our screen resolution so we want our X coordinate to be 160 and our Y coordinate to be 100.

Setting the Horizontal Span
Assembly Borland Turbo C++ /
Open Watcom 16bit
Open Watcom 32bit
    mov ax, 7
    mov cx, 0
    mov dx, 319
    int 0x33
union REGS regs;
regs.x.ax = 7;
regs.x.cx = 0;
regs.x.dx = 319;
int86(0x33, &regs, &regs);
union REGS regs;
regs.x.ax = 7;
regs.x.cx = 0;
regs.x.dx = 319;
int386(0x33, &regs, &regs);

Now we have the BIOS driver aware of how wide the screen should be in virtual pixels.

Setting the Vertical Span
Assembly Borland Turbo C++ /
Open Watcom 16bit
Open Watcom 32bit
    mov ax, 8
    mov cx, 0
    mov dx, 199
    int 0x33
union REGS regs;
regs.x.ax = 8;
regs.x.cx = 0;
regs.x.dx = 199;
int86(0x33, &regs, &regs);
union REGS regs;
regs.x.ax = 8;
regs.x.cx = 0;
regs.x.dx = 199;
int386(0x33, &regs, &regs);

And finally we've set how tall our screen is in virtual pixels. Now we should be ready to use our mouse!

Putting that all together

Assembly Borland Turbo C++ /
Open Watcom 16bit
Open Watcom 32bit
mouse_init:
    push bx
    push cx
    xor ax, ax
    int 0x33
    mov mouse_button_count, bx
    cmp ax, -1
    jnz error
    mov ax, 4
    mov cx, 160
    mov dx, 100
    int 0x33
    mov ax, 7
    mov cx, 0
    mov dx, 319
    int 0x33
    mov ax, 8
    mov cx, 0
    mov dx, 199
    int 0x33
    pop cx
    pop bx
    xor ax, ax
    ret
error:
    pop cx
    pop bx
    mov ax, -1
    ret
union REGS regs;
regs.x.ax = 0;
int86(0x33, &regs, &regs);
if (regs.x.ax==-1) return -1;
mouse.buttoncount = regs.x.bx;
regs.x.ax = 4;
regs.x.cx = 160;
regs.x.dx = 100;
int86(0x33, &regs, &regs);
regs.x.ax = 7;
regs.x.cx = 0;
regs.x.dx = 319;
int86(0x33, &regs, &regs);
regs.x.ax = 8;
regs.x.cx = 0;
regs.x.dx = 199;
int86(0x33, &regs, &regs);
return 0;
union REGS regs;
regs.x.ax = 0;
int386(0x33, &regs, &regs);
if (regs.x.ax==-1) return -1;
mouse.buttoncount = regs.x.bx;
regs.x.ax = 4;
regs.x.cx = 160;
regs.x.dx = 100;
int386(0x33, &regs, &regs);
regs.x.ax = 7;
regs.x.cx = 0;
regs.x.dx = 319;
int386(0x33, &regs, &regs);
regs.x.ax = 8;
regs.x.cx = 0;
regs.x.dx = 199;
int386(0x33, &regs, &regs);
return 0;

Updating Our Status

Polling the Mouse
Assembly Borland Turbo C++ /
Open Watcom 16bit
Open Watcom 32bit
    mov ax, 3
    int 0x33
    mov mouse_x, cx
    mov mouse_y, dx
    mov mouse_buttons, bx
union REGS regs;
regs.x.ax = 3;
int86(0x33, &regs, &regs);
mouse.x = regs.x.cx;
mouse.y = regs.x.dx;
mouse.buttons = regs.x.bx
union REGS regs;
regs.x.ax = 3;
int386(0x33, &regs, &regs);
mouse.x = regs.x.cx;
mouse.y = regs.x.dx;
mouse.buttons = regs.x.bx

One strange quirk you may want to keep in mind when integrating mouse support is the BIOS routine usually doesn't track the least significant bit on the X coordinate. What this means is that you'll see your cursor skip every odd X coordinate. This can be remedied by setting the horizontal spacing to twice your resolution - 1, and then bit shift the resulting mouse X coordinate read by 1 (divide by 2).

Clean Up

Resetting the Mouse one last time
Assembly Borland Turbo C++ /
Open Watcom 16bit
Open Watcom 32bit
    xor ax, ax
    int 0x33
union REGS regs;
regs.x.ax = 0;
int86(0x33, &regs, &regs);
union REGS regs;
regs.x.ax = 0;
int386(0x33, &regs, &regs);