Qbasicnews.com

Full Version: Checking mouse-position: isn't working. (ASM, MASM)
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
The program I wrote is supposed to quit when you mouse over the green pixel placed at 100,100 (screen mode 13h, 320x200x256).
This is the code. It assembles, but doesn't quite when you mouse over the pixel. I can't see anything wrong:
Code:
.model small
.stack 100h
.code
main PROC
   ;Set screen mode:
      mov ah,00      ;int 10h, function 00h: set screen mode in al
      mov al,13h
      int 10h
   ;Put pixel at 100,100:
      mov cx,100     ;x-pos
      mov dx,100     ;y-pos
      mov al,2       ;color: green
      mov ah,0ch     ;int 10h, function 0Ch, set screen mode
      int 10h
   ;Set up mouse:
      mov ax,0000    ;int 33h, function 00h: reset mouse driver and read status
      int 33h
      mov ax,0001    ;int 33h, function 01h: show mouse cursor
      int 33h
LoopTop:
   ;Poll mouse:
      mov ax,0003h   ;int 33h, function 03h: poll status of mouse
      int 33h;
   cmp cx,100     ;mouse-x=100?
   jz CheckMouseY ;yes - check mouseY pos
   jmp LoopTop    ;no - go back
CheckMouseY:
   cmp dx,100     ;mouse-y=100?
   jz EndProg     ;yes, all done, quit
   jmp LoopTop    ;no, go back
EndProg:
   mov ah,4ch
   int 21h
main ENDP
END main
try dividing X coordinate by two. (SHR cx just before the CMP CX,100)
Great, it works now. Smile
Why, though? Why divide by 2?

And one more question: what is MSDOS's default screen mode? I'm switching back to mode 00 at the end (just realized I need that, heheh), but it isn't DOS's default. What is, and how do I switch to it?
Code:
.model small
.stack 100h
.code
main PROC
   ;Set screen mode:
      mov ah,00      ;int 10h, function 00h: set screen mode in al
      mov al,13h
      int 10h
   ;Put pixel at 100,100:
      mov cx,100     ;x-pos
      mov dx,100     ;y-pos
      mov al,2       ;color: green
      mov ah,0ch     ;int 10h, function 0Ch, set screen mode
      int 10h
   ;Set up mouse:
      mov ax,0000    ;int 33h, function 00h: reset mouse driver and read status
      int 33h
      mov ax,0001    ;int 33h, function 01h: show mouse cursor
      int 33h
LoopTop:
   ;Poll mouse:
      mov ax,0003h   ;int 33h, function 03h: poll status of mouse
      int 33h
   shr cx,1          ;??? thanks, Nath
   cmp cx,100     ;mouse-x=100?
   jz CheckMouseY ;yes - check mouseY pos
   jmp LoopTop    ;no - go back
CheckMouseY:
   cmp dx,100     ;mouse-y=100?
   jz EndProg     ;yes, all done, quit
   jmp LoopTop    ;no, go back
EndProg:
   ;Clean up
      mov ah,00
      mov al,00
      int 10h
      mov ah,4ch
      int 21h
main ENDP
END main
DOS's default is usually mode 3 (80x25 color), I think.

You could just get the current video mode with int 10h function 0Fh, save it, then set that mode on exit.
Thanks, Sterling.
*Wonders about the dividing by 2*
When taking X coords from the driver in mode 13 you have to divide by 2, when giving X coords to the driver you have to multiply by 2.
320*2 = 640.

In 80x25 text mode, you have to divide by 8.
80*8 = 640.

In 640x480, you don't have to adjust the x coordinate at all.

This suggests to me that a horizontal resolution of 640 is hardwired into the driver regardless of the screen resolution, but I don't know for sure, nor do I know why that would be.

EDIT: The problem with my theory is that vesa libraries like UGL or Future.Library don't have to scale the x coordinates to 640 for the driver (at least for modes wider than as wide as 640), the driver is happy to set a mouse range of (0,0)-(799,599).

EDIT #2: I figured it out. The driver lets you set any range you want, even (0,0)-(319,199) or (0,0)-(1279,1023). But the part of the driver that draws the cursor on the screen assumes that the x range is 0-639 and compensates for that depending on the screen resolution. And that part of the driver only supports VGA modes, vesa libraries do it themselves.
Quote:This suggests to me that a horizontal resolution of 640 is hardwired into the driver regardless of the screen resolution, but I don't know for sure, nor do I know why that would be.
Just like a joystick always (DOS) has coordinate range of 0-200. About the dividing by a number, it's the planes per pixel (did I spell it right?). Anyway, in text modes this is the horizontal resolution of a text character (DOS Mode 3h Fonts are 8x16). But really WHY they did it... I don't know... Ask mouse developers... Wink
Hmm, that doesn't make sense, Sterling. When using the BIOS interrupt to PLACE a pixel at (100,100), it places it right there. So you don't have to multiply by two. If you did, then the pixel would show up at (50,50), and it certainly isn't there. :-?
When you place a pixel at 100,100 that has nothing to do with the mouse.

The standard mouse driver is a lame thing introduced with IBM PS/1 and PS/2 computers, which featured ¡a mouse! and ¡a VGA!. Make some calculations: VGAs horizontal coordinates range from 0 to either 319 or 639 (not counting text mode which is 720 but in fact is just 640 with an extra pixel column per text column). To make things easier, the mouse driver doesn't give a damn about which screen mode is active (only when drawing the mouse cursor), so it always measures 640 pixels width.

Make a test: write a basic mouse driver and just a loop that prints the current coordinates. Change to each VGA video mode (SCREEN 1, 2, 7, 8, 9, 10, 11, 12 and 13) and notice how the horizontal coordinates ALWAYS range from 0 to 639.
I see. But Sterling said that when GIVING x coords (read: placing pixels with the int 10h BIOS interrupt), you need to multiply them by two. But you don't.
So it's only int 33h that's lazy?
Pages: 1 2