Board index » delphi » Mouse in protected mode

Mouse in protected mode

Hi, folks

I'm trying to make the Mouse interrupt , service 9 (Set graphics cursor)
run in protected mode , but I can't make it work correctly. The mouse
pointer appears like a square of noise, not like the arrow it use to be
in real mode.

Some kind of operation with the segment selectors has to be done to set
correctly ES:DI .

Do someone can help me ?

Thanks in advance
Ricardo Dunna

 

Re:Mouse in protected mode


Quote
Ricardo Dunna wrote:
> I'm trying to make the Mouse interrupt , service 9 (Set graphics cursor)
> run in protected mode , but I can't make it work correctly. The mouse
> pointer appears like a square of noise, not like the arrow it use to be
> in real mode.

> Some kind of operation with the segment selectors has to be done to set
> correctly ES:DI .

Why don't you try to chain the mouse services (int 33h, function 0Ch) and use
own cursor drawing routine? I recommend this because I've also had problems with
mouse pointer under pmode. And this method works.
You may try my GFXXMOUSE example in the grafixx.zip archive at the
http://www.chat.ru/~alexfru

Good Luck
Alexei A. Frounze

Re:Mouse in protected mode


In article <3841261C.97084...@infolink.com.br>,
Ricardo Dunna  <rdu...@infolink.com.br> wrote:

Quote
>Hi, folks

>I'm trying to make the Mouse interrupt , service 9 (Set graphics cursor)
>run in protected mode , but I can't make it work correctly. The mouse
>pointer appears like a square of noise, not like the arrow it use to be
>in real mode.

>Some kind of operation with the segment selectors has to be done to set
>correctly ES:DI .

Try the following. Use it like:

var rg:registers;
...

rg.ax:=9;
rg.dx:=...
rg.cx:=...
rg.es:=seg(cursor);
rg.dx:=ofs(buffer);
SetBuffer(rg.es,eg.dx,nnnn);
Intr($33,rg);
if IntrError then ....

I.we. just like one would use int in DOS-unit with the exception of the
SetBuffer and test for error. The nnnn is the size of the buffer. What
it does is it allocates base memory, copies the bitmap there modifies
the es and dx accordingly and then simulates the interrupt. After that
it copies the bitmap back (which in this case is not necessary)

Remember to use the unit after DOS, or alternatively use Unit
specifiers:

var rg:IntProt.resgisters;
...
Intprot.Intr(...

I have not tested it in this particular case.

Unit IntProt;

interface

{$ifdef dpmi}

uses DOS,WInapi;

{ The register structure for Int 21h, ax=300h. The filler fields
  are because the registers in the structure are 32-bit. We use only
  the lowest 16 bits. One can basically ignore the internals of the
  structure and use it like dos.registers. }

Type registers= record   { for int 31h, ax=300h, simulate RM interrupt }
           DI,f1,SI,f2,BP,f3,f4,f5:word;
           case integer of
            0: (BX,f6,DX,f7,CX,f8,AX,f9:word;
                flags,ES,DS,FS,GS,IP,CS,SP,SS:word);
            1: (BL,BH,f6a,f6b,DL,DH,f7a,f7b:byte;
                CL,CH,f8a,f8b,AL,AH:byte);
         End;

Procedure Intr(inro:word;var rg:registers);
Procedure MsDOS(var rg:registers);

{ This routine is for setting the buffers before Intr or MSDos. One
  tells the segment register, the offset register and the size of the
  buffer. The first two parameters are fields in the register structure.

  for example SetBuffer(rg.ds,rg.si,256);

  If several buffers point to same area in the protected mode memory
  then set the output buffer as as the last one. Otherwise the other
  buffer(s) will overwrite the output }

Procedure SetBuffer(var sg,os:word; size:word);

{ This converts a segment into a selector. Use when the interrupt
  returns a pointer to area in base memory }

Function Selector(x:word):word;

const IntrError:boolean=false;  { check this after the interrupt }

{$else}

{ Dummy functionality for real mode, so one does not have to use any
  compiler directives if one does not wish }

type Selector=word;  { A dummy "function" }
const intrerror=false;

Procedure SetBuffer(seg,ofs,size:word);
inline($83/$C4/$06); {ADD SP,+06}   { Dummy inline procedure }

{$endif}

implementation

{$ifdef dpmi}

const stacksize=1024;  { The size of the real mode stack }
      maxbuff=5;       { Maximum number of buffers allowed }
      nbuff:word=0;    { Number of buffers actually used }

type pword=^word;

var buffers:array[1..maxbuff] of record
                                   s,o:pword;   { pointers to the segment }
                                                { and offset fields }
                                   siz,loc:word;{ Size and offset in buffer }
                                 End;

Procedure SetBuffer(var sg,os:word; size:word);
begin
  if nbuff=maxbuff then runerror(201);
  inc(nbuff);
  with buffers[nbuff] do begin
     s:=@sg;
     o:=@os;
     siz:=size;
     if nbuff=1 then loc:=0
                else loc:=size+buffers[nbuff-1].loc;
  End;
End;

Procedure Intr(inro:word;var rg:registers);
var x:longint;
    AllocSeg,AllocSel:word;
    p:array[1..maxbuff] of pointer;
    i:word;
    allocsize:word;

type words=record lo,hi:word; end;

Begin

  { First allocate the base memory buffer, its size is adjusted to the
    next even number so that the stack will be word adjusted }

  with buffers[nbuff] do allocsize:=(stacksize+siz+loc+1) and not 1;
  x:=globaldosalloc(allocsize);
  if x=0 then begin IntrError:=true; nbuff:=0; exit; end;

  { Get the segment (real mode) and selector (PM) of the allocated block }

  AllocSeg:=words(x).hi;
  AllocSel:=words(x).lo;

  { Set the stack pointers in the registers record }

  rg.ss:=AllocSeg;
  rg.sp:=AllocSize;

  { Now copy the buffers to the base memory buffer
    One also saves the original addresses of the buffers in the array p[]
    and sets the segment and offset registers in the registers field
    to point their new (real mode) values }

  for i:=1 to nbuff do with buffers[i] do begin
    move(ptr(s^,o^)^,ptr(AllocSel,loc)^,siz);
    p[i]:=ptr(s^,o^);
    s^:=AllocSeg;
    o^:=loc;
  End;

  { now one simulates the actual interrupt }

  asm
  mov ax,$300
  mov bl,byte ptr inro
  mov bh,0
  mov cx,0
  les di,rg
  int 31h
  mov ax,0
  adc ax,ax
  mov IntrError,al
  @x:
  end;

  { Now one copies the (possibly altered) buffers back to their original
    locations. Note that if the original buffers are at same location
    the one copied last will dominate. That is the one that was set last

    Note that one restores the registers (fields) to point to the
    original PM buffers only if they were not modified by the interrupt }

  for i:=1 to nbuff do with buffers[i] do begin
    move(ptr(AllocSel,loc)^,p[i]^,siz);
    if (s^=AllocSeg) and (o^=loc) then begin
       s^:=words(p[i]).hi;
       o^:=words(p[i]).lo;
    End;
  End;

  { Finally lets deallocate the base memory buffer and reset the number of
    buffers used }

  GlobalDosFree(AllocSel);
  nbuff:=0;
End;

Procedure MsDOS(var rg:registers);
Begin
  Intr($21,rg);
End;

Function Selector(x:word):word; assembler;
         asm
         mov ax,2
         mov bx,x
         int 31h
         end;

{$endif}

End.

Osmo

Other Threads