[Back to CURSOR SWAG index]  [Back to Main SWAG index]  [Original]


{ Updated CURSOR.SWG on May 26, 1995 }

{
Hi everyone.  Recently, I made a program to animate the cursor, and
when I added support for hiding and showing the cursor, my program
ceased to work like it should (all int 10h functions (video) didn't
work right.)  If anyone has any suggestions, optimizations, or ways
to get this to take up less memory, please reply.

----8<-cut-here-
Program AnimateCursor;
{ AnimateCursor Copyright (C) 1995 by Jonathan Anderson }
{ This program does what it says -- it makes the cursor move up and down }
{ thanks to John Baldwin for nice description of cursor handling }

{-$DEFINE Debug}        { Define this if changing the code }
{$DEFINE Use286}       { Define this to use 286 code }

{$IFDEF Debug}

{$M $1000,0,0}   { 4K stack, no heap }
{$A+,B-,D+,E-,F-,G-,I-,L+,N-,O-,R-,S+,V+,X-}     { TP6 compile options }

{$ELSE}

{$M $400,0,0}    { 1K stack, no heap }
{$A+,B-,D-,E-,F-,G-,I-,L-,N-,O-,R-,S-,V-,X-}

{$ENDIF}

{$IFDEF Use286}
{$G+}
{$ENDIF}

Uses Dos;

Var OldInt1C, OldInt09 : Procedure;
    OldInt10           : Pointer;     { status = cursor blink pattern }
    x, z, status       : Byte;        { x = top scan line for cursor }
    y                  : Boolean;     { z = width (in scan lines) of cursor }
                                      { y = cursor going up (F) or down (T) }

Procedure RemoveAnimate; Assembler;
Asm                  { thanks to Luis Mezquita Raya for this... }
  cli
  mov   ah,1
  mov   ch,6                { this procedure (c) Jul 94 Luis Mezquita Raya }
  mov   cl,7
  int   10h
  mov   ah,49h
  mov   es,PrefixSeg
  push  es
  mov   es,es:[2ch]
  int   21h
  pop   es
  mov   ah,49h
  int   21h
  sti
End;

{$F+}
Procedure NewInt09; Interrupt;      { KBD handler for unloading hotkey }
Var KB : Byte;
Begin
  KB := Port[$60];
  Inline($9C);                      { pushf }
  OldInt09;                         { call old interrupt }
  If KB = 88 Then                   { Use F12 to unload from memory }
    Begin
      SetIntVec($1C, @OldInt1C);
      SetIntVec($10, OldInt10);
      SetIntVec($09, @OldInt09);
      RemoveAnimate;
    End;
End;

Procedure NewInt10; Interrupt; Assembler;  { handler to allow programs  }
Asm                                        { to hide & show cursor...   }
{$IFDEF Use286}                            { right now, it doesn't work }
  pusha
{$ELSE}
  push  ax
  push  bx
  push  cx
  push  dx
  push  si
  push  di
{$ENDIF}
  cmp   ah,1                               { check for cursor change }
  jnz   @Skip                              { request & jump if not   }
  mov   status,ch
  and   status,60h                         { isolate bits 5 and 6 }
@Skip:
{$IFDEF Use286}
  popa
{$ELSE}
  pop   ax
  pop   bx
  pop   cx
  pop   dx
  pop   si
  pop   di
{$ENDIF}
  call  oldint10                           { call olt interrupt }
End;

Procedure NewInt1C; Interrupt;             { timer handler; changes cursor }
Var ctype : Byte;
Begin
  If (x=129) or (x=143-z) Then y := Not(y);  { reverse direction of cursor }
  If y Then Asm dec x End                  { why use Inc() and Dec() ? }
  Else Asm inc x End;
  ctype := status OR x;            { combine status bits with position bits }
  Asm
    mov  ah,1                      { request cursor change }
    mov  ch,ctype                  { set top scan line }
    mov  cl,ctype                  { set bottom scan line }
    add  cl,z
    call OldInt10      { call oldint instead of wasting time calling new one }
  End;
  Inline($9C);         { pushf }
  OldInt1C;            { call old interrupt }
End;
{$F-}

Begin
  x := 129;  { had to mess with this value for use of all scan lines in char }
  z := 1;                    { cusor width = 1 }
  status := 0;               { normal cursor }
  y := True;                 { MUST be true...}
  GetIntVec($09, @OldInt09);
  SetIntVec($09, @NewInt09);
  GetIntVec($10, OldInt10);
  SetIntVec($10, @NewInt10); { comment this line for prog. to work w/o int10 }
  GetIntVec($1C, @OldInt1C);
  SetIntVec($1C, @NewInt1C);
  Keep(0);                   { terminate, stay resident }
End.

(*
  From: Kelly Small

You don't restore the registers properly during the Int $10 ISR.
You need to pop them in the reverse order that they were pushed:

>Procedure NewInt10; Interrupt; Assembler;  { handler to allow programs  }
>Asm                                        { to hide & show cursor...   }
>  push  ax
>  push  bx
>  push  cx
>  push  dx
>  push  si
>  push  di


>  pop   ax
>  pop   bx
>  pop   cx
>  pop   dx
>  pop   si
>  pop   di

After this you would have ax = di
                          bx = si etc.

Reverse the order of your pop's and it should work.
*)

[Back to CURSOR SWAG index]  [Back to Main SWAG index]  [Original]