[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]