sword@vu-vlsi.UUCP (Ronin) (12/01/87)
Well, since I haven't been told where to post this, I'll just post it here (please forgive me if this is wrong). This code is an example of a TSR (written the old way with INT 27H) which intercepts INT 10H and looks for cursor calls. It then moves an inverse block to where the cursor is. There are several bugs, and I'm not a good enough 8086 programmer to know a way around them. That's why I'm posting it. I'm hoping some brave soul might be able to figure it out. Anyways, if posting code with some bugs is a bad thing, then I'm sure someone will let me know. But please, no flames. Stats: Written in 8086/88 Assembly Language steps to use: ASM BLOCK; ! uses no macro stuff, so doesn't need MASM LINK BLOCK,BLOCK,CON:; EXE2BIN BLOCK.EXE BLOCK.COM BLOCK Any question, please send mail to one of the addresses given in the source code. Without further adieu, the program. ----- Larry Esmonde, Program Director of SWORD (Students Working On R & D) Computer Science Dept. Villanova University Villanova, Pa. 19085 --------------------------CUT HERE--------------------------- ; BLOCK.ASM -- IBM 8086/88 Assembler -- 11.27.87 -- BLOCK.COM ; ; This program simulates a block, non-blinking cursor (ala ; DEC VT-100/200 Series terminals) in replacement of the blinking ; IBM Personal Computer. ; ; Author: Larry Esmonde Jr. ; ; UUCP : {cbmvax,bpa,psuvax1}!vu-vlsi!excalibur!159628317 ; BITNET : 159628317@vuvaxcom, larry@villvm ; CSnet : esmonde@villanova.edu ; ; ; *NOTE* - This code is buggy. It will not work with Turbo Pascal ; or PC BASIC. Also, it has problems with the screen ; scrolling during cursor placement. ; You have been warned. ; ; This code may be freely modified and redistributed, as long ; as credit is given for any interim authors and modifiers. ; ; If any modifications are made, please let me know, for ; I'd be glad to know how bugs were overcome ; ; ;-----------------------------------------------------------------; ; VECTORS - Absolute Segment at 0000H ; ; ; ; This segment allows access to the interrupt vector table, ; ; which contains the memory locations of all the interrupts ; ; which the computer uses. ; ; ; ;-----------------------------------------------------------------; vectors segment at 0000H org 10H*4 ; the offset of the video int. int10 label dword vectors ends ;-----------------------------------------------------------------; ; MDA - Absolute Segment at B000H ; ; ; ; This segment allows access to the monochrome screen via ; ; direct memory access. ; ; ; ;-----------------------------------------------------------------; mda segment at 0B000H ; the monochrome display adapter address org 0 mda ends ;-----------------------------------------------------------------; ; CGA - Absolute Segment at B800H ; ; ; ; This segment allows access to the color/graphics screen ; ; via direct memory access. ; ; ; ;-----------------------------------------------------------------; cga segment at 0B800H ; the color/graphics adapter address org 0 cga ends ;-----------------------------------------------------------------; ; ROM_BIOS - Absolute Segment at 0040H ; ; ; ; This segment allows access to the ROM-BIOS table, which ; ; contains various system information, like which display ; ; adapter is currently in use. ; ; ; ;-----------------------------------------------------------------; rom_bios segment at 0040H org 10H equip dw ? ; Used to determine display type rom_bios ends ;-----------------------------------------------------------------; ; CODE - Relative Segment at CS ; ; ; ; This segment contains all of the programming code for the ; ; program. It is also referenced when INT10, from the VECTORS ; ; segment is loaded with the CS value. ; ; ; ;-----------------------------------------------------------------; code segment assume cs:code org 100H start: jmp fix_int ; fix-up the interrupt vector table ; old10 dd ? ; this is the address of the old INT 10 newpos dw ? ; holding area for the new cursor position curpos dw ? ; " " " " old cursor " scraddr dw ? ; the absolute memory address on screen scrattr db ? ; the attributes of the address row db ? ; row of cursor call col db ? ; column of cursor call cursor db 0 ; binary true/false for cursor call inverse db 70H ; this is the hex value of inverse ;-----------------------------------------------------------------; ; CALC_ADDRESS - Near Procedure ; ; ; ; This procedure calculates the absolute memory value of a ; ; given cursor coordinate (i.e. cursor location (y=2,x=6) is ; ; equal to (2*160)+(2*6) = 326. It returns the calculated ; ; value in the SCRADDR variable ; ; ; ; Input Parameters: ROW and COL ; ; Output Parameters: SCRADDR ; ;-----------------------------------------------------------------; calc_address proc near push ax push bx push cx mov ax,0 mov bx,0 mov cx,0 mov al,row ; get the row value mov bl,col ; get the column value mov cl,160 ; multiply the row value by 160 (80*2) mul cl mov scraddr,ax ; store the row value mov al,bl ; restore the column value mov ah,0 ; zero-out the high-order bits mov cl,2 ; multiply the column value by 2 mul cl add scraddr,ax ; add the column value to the row value pop cx pop bx pop ax ret ; return to caller calc_address endp ;-----------------------------------------------------------------; ; MOVE_BLOCK - Near Procedure ; ; ; ; This procedure is called every time the cursor is ; ; repositioned on the screen. It taps directly into video ; ; memory at either segment B000 or B800. ; ; ; ; Calls: CALC_ADDRESS ; ;-----------------------------------------------------------------; move_block proc near push ax ; save AX, BX, CX, DX & DS push bx ; push cx ; push dx ; push ds mov ax,rom_bios ; fix up DS to the ROM_BIOS segment mov ds,ax ; assume ds:rom_bios ; mov ax,equip ; determine which adapter is active and al,30H ; isolate adapter information cmp al,30H ; is the mda active? jne cga_active ; no: setup for cga move mov ax,mda ; fix up DS to the MDA segment mov ds,ax ; assume ds:mda jmp change_pos ; now move the block cga_active: mov ax,cga ; fix up DS to the CGA segment mov ds,ax ; assume ds:cga ; change_pos: mov ax,curpos ; first, remove the current inverse block ; and restore the original attributes mov row,ah ; row & col are value parameters for the mov col,al ; calc_address procedure call calc_address ; calculate the address of curpos mov bx,scraddr ; the value is returned in SCRADDR mov al,scrattr ; put the old attributes for restoring in AL mov byte ptr [bx+01],al mov ax,newpos ; load the new cursor position for calculation mov row,ah ; load row and col with the appropriate mov col,al ; values call calc_address ; calculate the address of newpos mov bx,scraddr ; the value in returned in SCRADDR mov al,byte ptr [bx+01] ; get the attribute value mov scrattr,al ; store it in SCRATTR mov al,inverse ; load the inverse attr. value mov byte ptr [bx+01],al ; put it to the screen mov ax,newpos ; get the new position mov curpos,ax ; store it in CURPOS for a later call ; pop ds ; restore the registers pop dx pop cx pop bx pop ax ret ; let's go home move_block endp ;-----------------------------------------------------------------; ; INTERCEPT_VIDEO_INT - Near Procedure ; ; ; ; This procedure determines whether or not a change in cursor ; ; position is being requested (AH=02H). If not, then proceed as ; ; usual, else allow the change, then update the position of the ; ; inverse block. ; ; ; ; Calls: MOVE_BLOCK ; ; OLD10 ; ;-----------------------------------------------------------------; intercept_video_int proc near ; assume ds:nothing pushf mov cursor,0 ; set the case "cursor change?" to false (0) mov newpos,dx ; just in case it is a cursor change, store ; the value in newpos pushf ; save the flags cmp ah,02H ; is it a cursor change? jnz not_cursor1 ; NO: don't set the true/false variable mov cursor,1 ; YES: set CURSOR to true (1) not_cursor1: popf ; restore the flags call old10 ; do the cursor change mov al,cursor ; load the boolean value cmp al,1 ; is this a cursor call? jnz not_cursor2 ; no: exit via IRET call move_block ; yes: move the solid block not_cursor2: iret ; do an interrupt return to caller intercept_video_int endp ;-----------------------------------------------------------------; ; MAKE_BLOCK - Near Procedure ; ; ; ; This procedure initializes the value of CURPOS to the ; ; current location of the cursor. It also retrieves the ; ; attributes from that location. ; ;-----------------------------------------------------------------; make_block proc near assume ds:nothing push ax ; save the regs push bx push cx push dx mov ah,15 ; get current video state (active page in BH) int 10H mov ah,03 ; get current cursor position on active page int 10H mov curpos,dx ; store this value for later mov ah,08 ; get the attributes at the current position int 10H mov scrattr,ah ; store this value for later mov ah,01 ; set the cursor "off" by setting the scan- mov cx,0F0FH ; lines from 15 to 15, in CX int 10H pop dx ; restore the regs pop cx pop bx pop ax ret ; return to caller make_block endp ;-----------------------------------------------------------------; ; FIX_INT - Near Procedure ; ; ; ; This procedure initializes the interrupt vector for INT 10H ; ; (the video interrupt), to point to our routine. The old values ; ; in the table are stored in OLD10. ; ; ; ; Calls: MAKE_BLOCK ; ; OLD10 ; ;-----------------------------------------------------------------; fix_int proc near call make_block ; set up the initial values for the 1st call mov ax,vectors mov ds,ax ; set up data segment to vectors seg. assume ds:vectors cli ; disable interrupts mov ax,int10 ; save the address of the original INT 10H mov old10,ax ; vector values in the doubleword OLD10 mov ax,int10[2] ; mov old10[2],ax ; mov int10,offset intercept_video_int mov int10[2],cs sti ; enable interrupts mov dx,offset fix_int int 27H ; the TSR (Terminate but Stay Resident) int. fix_int endp code ends end start