189 lines
7.1 KiB
NASM
189 lines
7.1 KiB
NASM
|
%SUBTTL "Scroll Window Left routine with sample driver"
|
||
|
;
|
||
|
; Scroll2.Asm
|
||
|
;
|
||
|
; see ScrollLeft description for complete explanation of this program
|
||
|
;
|
||
|
MODEL small
|
||
|
IDEAL
|
||
|
STACK 200h ; this is more than enough stack
|
||
|
CODESEG
|
||
|
start:
|
||
|
;
|
||
|
; this test stub scrolls the window at (4,3)-(22,68) left 9 columns,
|
||
|
; filling in with spaces of attribute white on black (07)
|
||
|
;
|
||
|
mov al,9 ; number of columns to scroll
|
||
|
mov bh,07 ; attribute to use for blanked chars
|
||
|
mov ch,4 ; row of upper left hand corner of window
|
||
|
mov cl,3 ; col of upper left hand corner of window
|
||
|
mov dh,22 ; row of lower right hand corner of window
|
||
|
mov dl,68 ; col of lower right hand corner of window
|
||
|
|
||
|
call ScrollLeft
|
||
|
|
||
|
mov ah,4ch ; exit with errorlevel from scroll routine
|
||
|
int 21h
|
||
|
;
|
||
|
; ScrollLeft
|
||
|
;
|
||
|
; PURPOSE: scrolls a rectangular region of a text screen (window) to the
|
||
|
; left by a variable number of columns
|
||
|
;
|
||
|
;
|
||
|
; INPUTS: AL = number of columns to scroll (if zero, no effect)
|
||
|
; BH = attribute to use for blanked characters
|
||
|
; CH,CL = row, col for upper left hand corner of window
|
||
|
; DH,DL = row, col for lower right hand corner of window
|
||
|
;
|
||
|
; NOTES: upper left hand corner of screen (home) is (0,0)
|
||
|
; video adapter is checked to see if it's in text mode
|
||
|
; screen dimensions are taken from BIOS data
|
||
|
; calling sequence is nearly identical to BIOS scroll routine
|
||
|
; display pages supported
|
||
|
; dual monitors supported
|
||
|
; MDA/CGA/EGA/VGA supported
|
||
|
;
|
||
|
; RETURNS: On error, Carry flag set, AX contains error number
|
||
|
; otherwise carry is clear, AX contains 0
|
||
|
;
|
||
|
; Error codes: 0 - no error
|
||
|
; -1 - some error occurred
|
||
|
;
|
||
|
PROC ScrollLeft
|
||
|
ScrRows equ 0484h ; location of BIOS rows data
|
||
|
ScrCols equ 044ah ; location of BIOS cols data
|
||
|
ScrMode equ 0449h ; location of BIOS mode data
|
||
|
ScrOffs equ 044eh ; location of BIOS scrn offset data
|
||
|
|
||
|
; first, save all of the registers we're going to trash
|
||
|
push bx
|
||
|
push cx
|
||
|
push dx
|
||
|
push si
|
||
|
push di
|
||
|
push bp
|
||
|
push es
|
||
|
push ds
|
||
|
|
||
|
mov bl,al ; stow cols in BL
|
||
|
xor ax,ax
|
||
|
mov ds,ax ; point data seg to 0000 to read BIOS data
|
||
|
cmp ch,dh ; srow > erow ?
|
||
|
ja @@badcoords
|
||
|
cmp cl,dl ; scol > ecol ?
|
||
|
ja @@badcoords
|
||
|
;
|
||
|
; now we need to load ScrRows, if we haven't got EGA or better
|
||
|
;
|
||
|
mov al,[ScrRows] ; is MAXROWS = 0 ?
|
||
|
cmp al,0 ; if so, then assume we've got MDA or CGA
|
||
|
jne @@ega_plus ; if not, we've got correct value already
|
||
|
mov al,24 ; otherwise, assume 25 rows (and load 25-1)
|
||
|
@@ega_plus:
|
||
|
cmp dh,al ; erow >= MAXROWS?
|
||
|
;
|
||
|
; note that BIOS actually stores MAXROWS-1 in this location, so the
|
||
|
; actual jump instruction is (correctly) written as ja
|
||
|
;
|
||
|
ja @@badcoords
|
||
|
cmp dl,[ScrCols] ; ecol >= MAXCOLS?
|
||
|
jae @@badcoords
|
||
|
mov ah,bl ; remember cols
|
||
|
add ah,cl ; cols + scol
|
||
|
cmp ah,dl ; (cols + scol) > ecol ?
|
||
|
ja @@badcoords
|
||
|
|
||
|
; figure out where the video buffer starts
|
||
|
mov bp,0b800h ; first guess
|
||
|
mov al,[ScrMode] ; get mode from BIOS' RAM
|
||
|
cmp al,4 ; if mode is 0 through 3, we're all set
|
||
|
jb @@modeOK
|
||
|
mov bp,0b000h ; second guess
|
||
|
cmp al,7 ; is it mode 7 (monochrome 80 col) ?
|
||
|
je @@modeOK ; if so, we're still OK
|
||
|
@@badcoords:
|
||
|
mov ax,-1 ; set error code
|
||
|
stc ; and set error (carry) flag
|
||
|
jmp @@exit
|
||
|
@@modeOK:
|
||
|
mov es,bp ; set up our video pointer segment
|
||
|
|
||
|
; ES:DI = endloc = Screen + 2 * (MAXCOLS * srow + scol)
|
||
|
|
||
|
mov di,[ScrOffs] ; offset of screen buffer
|
||
|
xor ah,ah ; clear out high half of AX
|
||
|
mov al,[ScrCols] ; get the width of the screen
|
||
|
mul ch ; multiply width by the row number
|
||
|
add al,cl ; now add the column number
|
||
|
adc ah,0 ; propagate carry bit to other half of AX
|
||
|
shl ax,1 ; now multiply by 2 bytes/char
|
||
|
add di,ax ; add the offset to the screen start address
|
||
|
|
||
|
; DS:DI = startloc = endloc + 2 * cols
|
||
|
|
||
|
xor ah,ah ; clear top half of ax
|
||
|
mov al,bl ; recall cols
|
||
|
mov si,di ; start address = end address
|
||
|
add si,ax ; add cols
|
||
|
add si,ax ; and again
|
||
|
|
||
|
; start on count calculation (figure ecol-scol+1)
|
||
|
sub dl,cl ; ecol - scol
|
||
|
inc dl ; now dl = ecol - scol + 1
|
||
|
|
||
|
; calculate increment and stow in BP
|
||
|
; increment = (MAXCOLS - (ecol - scol + 1)) * 2
|
||
|
xor ah,ah ; clear top half of ax
|
||
|
mov al,dl ; use partial count calculation
|
||
|
neg ax
|
||
|
add al,[ScrCols] ; now add in screen width
|
||
|
adc ah,0 ; propagate carry bit to hi half of AX
|
||
|
shl ax,1 ; now double it (2 bytes/char)
|
||
|
mov bp,ax
|
||
|
|
||
|
; finish count calculations and put in DL
|
||
|
; count = (ecol - scol + 1) - cols
|
||
|
|
||
|
sub dl,bl ; figure in cols
|
||
|
|
||
|
mov ax,es ; recall our video pointer
|
||
|
mov ds,ax ; now duplicate it
|
||
|
|
||
|
; load up AX with char and attribute for blank space
|
||
|
mov al,32 ; ASCII space character
|
||
|
mov ah,bh ; passed attribute byte
|
||
|
|
||
|
sub dh,ch ; get row count
|
||
|
mov dh,bh ; save loop count (rows to move) in bh
|
||
|
xor ch,ch ; zero out hi half of CX
|
||
|
cld ; assure that we move the right direction (up)
|
||
|
@@looptop:
|
||
|
mov cl,dl ; load in count (words to move)
|
||
|
rep movsw ; move the line over
|
||
|
mov cl,bl ; recall cols (blanks to insert)
|
||
|
rep stosw ; fill in the rest of the line
|
||
|
add di,bp ; advance to next line by adding increment
|
||
|
mov si,di ; now set up the other (source) pointer
|
||
|
mov cl,bl ; recall cols
|
||
|
add si,cx ; add in cols
|
||
|
add si,cx ; and again (because 2 bytes/char)
|
||
|
dec bh ; decrement loop counter
|
||
|
ja @@looptop ; skip back if we're not done yet
|
||
|
mov ax,0 ; set error code to zero (all OK)
|
||
|
clc ; and clear error (carry) flag
|
||
|
@@exit:
|
||
|
pop ds ; restore all of our registers
|
||
|
pop es
|
||
|
pop bp
|
||
|
pop di
|
||
|
pop si
|
||
|
pop dx
|
||
|
pop cx
|
||
|
pop bx
|
||
|
ret ; mosey on home again
|
||
|
|
||
|
ENDP ScrollLeft
|
||
|
END start
|
||
|
-+------- cut here -----------
|