Unit normMaus;
{$A+,D+,E+,F+,G+,N+,B-,I-,L-,P-,Q-,R-,S-,T-,V-,X-}

InterFace

Type

  TMAUS = Object
    Constructor Init(SpriteX,SpriteY : Integer; Breite,Hoehe : Byte; FromMemory : Boolean);
      Procedure Sichtbar;
      Procedure Unsichtbar;
      Procedure SetPoint(PunktX,PunktY : Byte);
      Procedure Move(NeueX,NeueY : Integer);
      Procedure HorizontalMax(Minimal,Maximal : Integer);
      Procedure VertikalMax(Minimal,Maximal : Integer);
      Procedure InstallMaus(OnOff : Boolean);
      Procedure ChangeSprite(SpriteX,SpriteY : Integer; Breite,Hoehe : Byte; FromMemory : Boolean);
      Function X : Integer;
      Function Y : Integer;
      Function Knopf : Byte;
      Function FieldCheck(LObenX,LObenY,RUntenX,RUntenY : Integer; Button : Byte) : Boolean;
    Destructor Done;
  End;

  Function IsMausInstalled : Boolean;
  Procedure LoadMouseSprite(DateiName : String);

Const
  ToggleMouse : Boolean = True;

Var
  Maus : TMAUS;

Implementation
Uses Vga256,Dos;
Const
  RelativPunktX : Byte = 0;
  RelativPunktY : Byte = 0;

Var
  XKoordinate,YKoordinate : Integer;
  MausZeiger,BackGround : TSprite;
  OldInt33h : Procedure;
  IsSichtbar : Boolean;
  OldInt08h : Pointer;

Function IsMausInstalled : Boolean; Assembler;
Asm
  Xor AX,AX
  PushF
  Call OldInt33h
  Cmp AX,0FFFFh
  Jne @NoMouse
  Mov AL,True
  Jmp @Ende
  @NoMouse:
  Mov AL,False
  @Ende:
End;

Procedure LoadMouseSprite(DateiName : String);
Begin
  MausZeiger.Init(4,4);
  MausZeiger.LoadSprite(DateiName);
  BackGround.Init(MausZeiger.Width,MausZeiger.Height);
  Asm
    Xor AX,AX
    PushF
    Call OldInt33h
    Mov AX,21h
    PushF
    Call OldInt33h
    Mov AX,2Fh
    PushF
    Call OldInt33h
    Xor AX,AX
    PushF
    Call OldInt33h
  End;
  Maus.HorizontalMax(0,640 - MausZeiger.Width);
  Maus.VertikalMax(0,200 - MausZeiger.Height);
  Asm
    Mov AX,04h
    Mov CX,160
    Mov DX,100
    PushF
    Call OldInt33h
  End;
  XKoordinate := 160;
  YKoordinate := 100;
  IsSichtbar := False;
End;

Procedure Animate; Interrupt;
Var
  RegsCX,RegsDX : Integer;

Begin
  If (IsSichtbar = True) then
  Begin
    Asm
      Mov AX,03h
      PushF
      Call OldInt33h
      Shr CX,1
      Mov RegsCX,CX
      Mov RegsDX,DX
    End;
    If (RegsCX <> XKoordinate) or (RegsDX <> YKoordinate) then
    Begin
      Asm
        Mov DX,3DAh
        @Jump1:
        In AL,DX
        Test AL,8D
        Jnz @Jump1
        @Jump2:
        In AL,DX
        Test AL,8D
        Jz @Jump2
      End;
      BackGround.DropSprite(XKoordinate,YKoordinate);
      BackGround.GrabSprite(RegsCX,RegsDX);
      If (ToggleMouse = True) then MausZeiger.ToggleSprite(RegsCX,RegsDX)
        Else MausZeiger.DropSprite(RegsCX,RegsDX);
      XKoordinate := RegsCX;
      YKoordinate := RegsDX;
    End;
  End;
  Asm
    Mov AL,20h
    Out 20h,AL
  End;
End;

Constructor TMAUS.Init(SpriteX,SpriteY : Integer; Breite,Hoehe : Byte; FromMemory : Boolean);
Begin
  Asm
    Xor AX,AX
    PushF
    Call OldInt33h
    Mov AX,21h
    PushF
    Call OldInt33h
    Mov AX,2Fh
    PushF
    Call OldInt33h
    Xor AX,AX
    PushF
    Call OldInt33h
  End;
  MausZeiger.Init(Breite,Hoehe);
  BackGround.Init(Breite,Hoehe);
  Case FromMemory of
    True : MausZeiger.GrabSpritefromMemory(SpriteX,SpriteY);
    False : MausZeiger.GrabSprite(SpriteX,SpriteY);
  End;
  HorizontalMax(0,640 - (Breite * 2));
  VertikalMax(0,200 - Hoehe);
  Asm
    Mov AX,04h
    Mov CX,160
    Mov DX,100
    PushF
    Call OldInt33h
  End;
  XKoordinate := 160;
  YKoordinate := 100;
  IsSichtbar := False;
End;

Procedure TMAUS.Sichtbar;
Var
  RegsCX,RegsDX : Integer;

Begin
  Asm
    Mov AX,03h
    PushF
    Call OldInt33h
    Mov YKoordinate,DX
    Shr CX,1
    Mov RegsCX,CX
    Mov RegsDX,DX
  End;
  XKoordinate := RegsCX;
  BackGround.GrabSprite(RegsCX,RegsDX);
  Case ToggleMouse of
    True : MausZeiger.ToggleSprite(RegsCX,RegsDX);
    False : MausZeiger.DropSprite(RegsCX,RegsDX);
  End;
  IsSichtbar := True;
End;

Procedure TMAUS.Unsichtbar;
Begin
  BackGround.DropSprite(XKoordinate,YKoordinate);
  IsSichtbar := False;
End;

Procedure TMAUS.SetPoint(PunktX,PunktY : Byte);
Begin
  RelativPunktX := PunktX;
  RelativPunktY := PunktY;
End;

Procedure TMAUS.Move(NeueX,NeueY : Integer);
Begin
  If (IsSichtbar = True) then BackGround.DropSprite(XKoordinate,YKoordinate);
  BackGround.GrabSprite(NeueX,NeueY);
  If (IsSichtbar = True) then
  Case ToggleMouse of
    True : MausZeiger.ToggleSprite(NeueX,NeueY);
    False : MausZeiger.DropSprite(NeueX,NeueY);
  End;
  XKoordinate := NeueX;
  YKoordinate := NeueY;
  Asm
    Mov AX,04h
    Mov CX,NeueX
    Mov DX,NeueY
    PushF
    Call OldInt33h
  End;
End;

Procedure TMAUS.HorizontalMax(Minimal,Maximal : Integer); Assembler;
Asm
  Mov AX,0007h
  Mov CX,Minimal
  Mov DX,Maximal
  PushF
  Call OldInt33h
End;

Procedure TMAUS.VertikalMax(Minimal,Maximal : Integer); Assembler;
Asm
  Mov AX,0008h
  Mov CX,Minimal
  Mov DX,Maximal
  PushF
  Call OldInt33h
End;

Procedure TMAUS.InstallMaus(OnOff : Boolean);
Const
  OldInt : Word = 103;

Var
  OldInt08 : Pointer;
  Faktor : LongInt;

Begin
  If (OnOff = True) then
  Begin
    InLine($FA);
    Port[$43] := $36;
    Faktor := 1193180 div 2000;
    Port[$40] := Lo(Faktor);
    Port[$40] := Hi(Faktor);
    GetIntVec($08,OldInt08h);
    SetIntVec($08,Addr(Animate));
    InLine($FB);
    Exit;
  End;
  InLine($FA);
  Faktor := $FFFF;
  Port[$40] := Lo(Faktor);
  Port[$40] := Hi(Faktor);
  SetIntVec($08,OldInt08h);
  InLine($FB);
End;

Procedure TMAUS.ChangeSprite(SpriteX,SpriteY : Integer; Breite,Hoehe : Byte; FromMemory : Boolean);
Begin
  MausZeiger.Done;
  BackGround.Done;
  MausZeiger.Init(Breite,Hoehe);
  BackGround.Init(Breite,Hoehe);
  If (FromMemory = True) then MausZeiger.GrabSpriteFromMemory(SpriteX,SpriteY)
    Else MausZeiger.GrabSprite(SpriteX,SpriteY);
  HorizontalMax(0,640 - (Breite * 2));
  VertikalMax(0,200 - Hoehe);
End;

Function TMAUS.X : Integer;
Var
  X2 : Integer;

Begin
  Asm
    Mov AX,03h
    PushF
    Call OldInt33h
    Shr CX,1
    Mov X2,CX
  End;
  Inc(X2,RelativPunktX);
  X := X2;
End;

Function TMAUS.Y : Integer;
Var
  Y2 : Integer;

Begin
  Asm
    Mov AX,03h
    PushF
    Call OldInt33h
    Mov Y2,DX
  End;
  Inc(Y2,RelativPunktY);
  Y := Y2;
End;

Function TMAUS.Knopf : Byte; Assembler;
Asm
  Mov AX,03h
  PushF
  Call OldInt33h
  Mov AL,BL
End;

Function TMAUS.FieldCheck(LObenX,LObenY,RUntenX,RUntenY : Integer; Button : Byte) : Boolean;
Var
  RegsBX,RegsCX,RegsDX : Integer;

Begin
  Asm
    Mov AX,03h
    PushF
    Call OldInt33h
    Shr CX,1
    Mov RegsCX,CX
    Mov RegsDX,DX
    Mov RegsBX,BX
  End;
  FieldCheck := False;
  If (RegsCX >= LObenX) and (RegsCX <= RUntenX) and (RegsDX >= LObenY)
    and (RegsDX <= RUntenY) and (RegsBX = Button) then FieldCheck := True;
End;

Destructor TMAUS.Done;
Begin
  Asm
    Xor AX,AX
    PushF
    Call OldInt33h
    Mov AX,21h
    PushF
    Call OldInt33h
    Mov AX,2Fh
    PushF
    Call OldInt33h
    Xor AX,AX
    PushF
    Call OldInt33h
  End;
  BackGround.DropSprite(XKoordinate,YKoordinate);
  MausZeiger.Done;
  BackGround.Done;
End;

Begin
  GetIntVec($33,Addr(OldInt33h));
End.