home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
ddkx86v5.zip
/
DDKX86
/
SRC
/
VDH
/
CGASCROL.ASM
< prev
next >
Wrap
Assembly Source File
|
1995-04-14
|
63KB
|
1,164 lines
;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; COPYRIGHT Copyright (C) 1995 IBM Corporation
;
; The following IBM OS/2 WARP source code is provided to you solely for
; the purpose of assisting you in your development of OS/2 WARP device
; drivers. You may use this code in accordance with the IBM License
; Agreement provided in the IBM Device Driver Source Kit for OS/2. This
; Copyright statement may not be removed.;
;*****************************************************************************/
PAGE 60,132
TITLE CGASCROL.ASM -- CGA Buffer Scroll Routines
;/*****************************************************************************
;*
;* SOURCE FILE NAME = CGASCROL.ASM
;*
;* DESCRIPTIVE NAME = CGA Buffer Scroll Routines
;*
;*
;* VERSION V2.0
;*
;* DATE
;*
;* DESCRIPTION BUFFERUPDATE scroll routines
;*
;* FUNCTIONS ScrollUp
;* ScrollDown
;* ScrollLeft
;* ScrollRight
;* ValidateScrollParms
;* GetScrollByteCount
;* GetLineSkipByteCount
;* GetLVB_PVB_Cell
;*
;* NOTES NONE
;*
;* STRUCTURES NONE
;*
;* EXTERNAL REFERENCES _MOVSW, _STOSW
;*
;* EXTERNAL FUNCTIONS
;*
;* NONE
;*
;* CHANGE ACTIVIY =
;* DATE FLAG APAR CHANGE DESCRIPTION
;* -------- ---------- ----- --------------------------------------
;* mm/dd/yy @Vr.mpppxx xxxxx xxxxxxx
;****************************************************************************/
.286c ; 286 protect mode instructions
.xlist
INCLUDE struc.inc ; Structure macro
INCLUDE error2.inc ; Subsystem error equates
INCLUDE vdhstruc.inc ; Buffer update data structures
INCLUDE vdhequ.inc ; Buffer update equates
.list
EXTRN _MOVSW : FAR ; Move words from DS:SI to ES:DI
EXTRN _STOSW : FAR ; Store words from AX to ES:DI
R2CSEG SEGMENT WORD PUBLIC 'CODE'
ASSUME CS:R2CSEG,DS:NOTHING,ES:NOTHING
;/****************************************************************************
;*
;* SUBROUTINE NAME: ScrollUp
;*
;* DESCRIPTIVE NAME: Video device handler scroll up routine
;*
;* FUNCTION: Process scroll up sub-function
;* Scrolls a portion of the PVB, LVB up a specified
;* number of times and then fill the vacant portion
;* with the user specified cell.
;*
;* ENTRY POINT: ScrollUp
;* LINKAGE: Near Call from BUFFERUPDATE rouinte
;*
;* INPUT:
;*
;* AX = 0
;* SS:BP ---> Stack frame (see VDHSTRUC.INC)
;* DS:SI ---> Parameter block buffer (see CGABUFUP.ASM)
;* ES:DI ---> Mode data in environment buffer (see CGABUFUP.ASM)
;*
;* PARAMETER BLOCK FORMAT:
;*
;* SIZE DESCRIPTION
;* ---- -----------
;*
;* WORD Parameter length
;* WORD Flags (target buffer - LVB, PVB)
;* DWORD Application data address
;* DWORD Application data2 address (cell to be used to fill void)
;* WORD Index (3)
;* WORD Starting row (top row)
;* WORD Starting column (left column)
;* WORD Secondary row (bottom row)
;* WORD Secondary column (right column)
;* WORD RepeatFactor (# of times to scroll)
;* WORD LogicalBufSel
;*
;* OUTPUT:
;*
;* EXIT-NORMAL: AX = 0
;*
;* EXIT-ERROR: AX = ValidateScrollParms
;*
;* EFFECTS: All
;*
;* INTERNAL REFERENCES: ValidateScrollParms,
;*
;* EXTERNAL REFERENCES: _MOVSW, _STOSW
;*
;****************************************************************************/
PUBLIC ScrollUp
ScrollUp PROC NEAR
;/*
;** Validate input row, column parameters. The carry flag is used
;** to indicate whether an abnormal condition occured. On exit the
;** following registers are also setup if the carry flag is not set:
;** AX, [bp].TopRow = Adjusted starting row
;** BX, [bp].BottomRow = Adjusted ending row
;** CX, [bp].LeftCol = Adjusted starting column
;** DX, [bp].RightCol = Adjusted ending column
;*/
call ValidateScrollParms ; Validate row, column values
.if <nc> NEAR ; Continue?
;/*
;** Locate the offset to the upper right hand corner of the target
;** rectangle to be scrolled. This is achieved by taking the TopRow
;** value, multiply it by the screen width and then add LeftCol value
;** to the result.
;*/
mul es:[di].TextCols ; Target offset = (TopRow
add ax, cx ; * screen columns
add ax, ax ; + LeftCol) * 2
push ax ; Save Target offset
;/*
;** Use the scroll scale factor to calculate the total number of bytes
;** neccessary to determine where the source offset is located.
;** GetScrollByteCount returns this value in AX.
;*/
call GetScrollByteCount ; AX = byte count
pop bx ; BX = Target offset
;/*
;** Determine the source offset by taking the byte count obtained
;** above and add to it the target buffer offset.
;*/
add ax, bx ; Source offset = Target offset
push ax ; + (# of lines to scroll *
; screen columns * 2)
;/*
;** Locate the offset to the bottom right hand corner of the target
;** rectangle to be scrolled. This is achieved by taking the BottomRow
;** value, multiply it by the screen width and then add RightCol value
;** to the result.
;*/
mov ax, es:[di].TextCols ; End offset = (BottomRow *
mul [bp].BottomRow ; screen columns + RightCol
add ax, [bp].RightCol ; + 1) * 2
inc ax ;
add ax, ax ;
mov dx, ax ; DX = End offset
;/*
;** Calculate the number of bytes to skip between the end of one line
;** and the beginning of the next line. This is achieved by taking
;** the screen width and subtract it by the number of columns between
;** the RightCol and LeftCol and then multiply it by 2.
;** GetLineSkipByteCount returns this value in CX.
;*/
call GetLineSkipByteCount ; CX = # of bytes to skip
;/*
;** Setup source and destination selectors. If both LVB and PVB are
;** selected for update then all changes will go to the LVB first
;** before transfering the changes to the PVB. GetLVB_PVB_Cell will
;** also return the cell in AX.
;*/
call GetLVB_PVB_Cell ; AX = cell
; BX = Target offset
; DX = End offset
pop si ; DS:SI -> Source buffer
mov di, bx ; ES:DI -> Target buffer
;/*
;** If each line within the target rectangle to be scrolled occupies
;** the entire width of the screen then a contiguous block move will
;** be opted.
;** For non-contiguous lines, scroll up is done by moving each line up
;** one at a time until the requested number of lines are scrolled.
;*/
.if <ncxz> ; Non-contiguous lines?
push bx ; Save Target offset
push ax ; Save cell
mov ax, [bp].SkipLength ; AX = skip length
mov bx, [bp].Retrace ; Setup retrace indicator
.if <si b dx> ; Any to scroll?
.repeat ;
mov cx, [bp].LineLength
call _MOVSW ; Copy one line
add si, ax ; Advance to start of
add di, ax ; next line
.until <si ae dx> ; More to scroll?
.endif ;
mov si, [bp].SkipLength ; SI = Skip length
pop ax ; AX = cell
.repeat ;
mov cx, [bp].LineLength ; CX = line length
call _STOSW ; Fill line with cell
add di, si ; Advance to start of next line
.until <di ae dx> ; More lines to fill?
pop di ; DI = Target offset
; DX = End offset
;/*
;** If PVB update is also required then transfer the updated rectangle
;** from the LVB to the corresponding location in the PVB.
;*/
.if <[bp].PVB_Sel a cx> ; Required update to PVB?
mov es, [bp].PVB_Sel ; ES:DI -> PVB buffer
mov ax, [bp].SkipLength ; AX = skip length
mov si, di ; DS:SI -> LVB buffer
inc bx ; Retrace wait required
.while <di b dx> ; More to copy?
mov cx, [bp].LineLength
call _MOVSW ; Copy a line from LVB to PVB
add si, ax ; Advance to start of
add di, ax ; next line
.endwhile ;
.endif ;
.else ; Non contiguous lines!
; DX = End offset
push di ; Save target offset
mov cx, dx ; CX = (End offset - Source
sub cx, si ; offset) / 2
shr cx, 1 ; CX = transfer count
mov bx, [bp].Retrace ; Pass retrace indicator
.if <ncxz> ; Source = Destination?
call _MOVSW ; Block copy
.endif ;
mov cx, dx ; CX = (End offset - current
sub cx, di ; Target offset) / 2
shr cx, 1 ; CX = cell transfer count
call _STOSW ; Copy cell to remaining lines
;/*
;** If PVB update is also required then transfer the updated rectangle
;** from the LVB to the corresponding location in the PVB.
;*/
pop di ; DI = target offset
.if <[bp].PVB_Sel a cx> ; Required update to PVB?
mov es, [bp].PVB_Sel ; ES:DI -> PVB buffer
mov si, di ; DS:SI -> LVB buffer
mov cx, dx ; CX = End offset - Target
sub cx, di ; offset) / 2
shr cx, 1 ; CX = entire rectangle
inc bx ; Retrace wait required
call _MOVSW ; Copy rectangle to PVB
.endif ;
.endif ;
sub ax, ax ; Clear return code
.endif ;
ret ;
ScrollUp ENDP
;/****************************************************************************
;*
;* SUBROUTINE NAME: ScrollDown
;*
;* DESCRIPTIVE NAME: Video device handler scroll down routine
;*
;* FUNCTION: Process scroll down sub-function
;* Scrolls a portion of the PVB, LVB down a specified
;* number of times and then fill the vacant portion
;* with the user specified cell.
;*
;* ENTRY POINT: ScrollDown
;* LINKAGE: Near Call from BUFFERUPDATE rouinte
;*
;* INPUT:
;*
;* AX = 0
;* SS:BP ---> Stack frame (see VDHSTRUC.INC)
;* DS:SI ---> Parameter block buffer (see CGABUFUP.ASM)
;* ES:DI ---> Mode data in environment buffer (see CGABUFUP.ASM)
;*
;* PARAMETER BLOCK FORMAT:
;*
;* SIZE DESCRIPTION
;* ---- -----------
;*
;* WORD Parameter length
;* WORD Flags (target buffer - LVB, PVB)
;* DWORD Application data address
;* DWORD Application data2 address (cell to be used to fill void)
;* WORD Index (4)
;* WORD Starting row (top row)
;* WORD Starting column (left column)
;* WORD Secondary row (bottom row)
;* WORD Secondary column (right column)
;* WORD RepeatFactor (# of times to scroll)
;* WORD LogicalBufSel
;*
;* OUTPUT:
;*
;* EXIT-NORMAL: AX = 0
;*
;* EXIT-ERROR: AX = ValidateScrollParms
;*
;* EFFECTS: All
;*
;* INTERNAL REFERENCES: ValidateScrollParms,
;*
;* EXTERNAL REFERENCES: _MOVSW, _STOSW
;*
;****************************************************************************/
PUBLIC ScrollDown
ScrollDown PROC NEAR
;/*
;** Validate input row, column parameters. The carry flag is used
;** to indicate whether an abnormal condition occured. On exit the
;** following registers are also setup if the carry flag is not set:
;** AX, [bp].TopRow = Adjusted starting row
;** BX, [bp].BottomRow = Adjusted ending row
;** CX, [bp].LeftCol = Adjusted starting column
;** DX, [bp].RightCol = Adjusted ending column
;*/
call ValidateScrollParms ; Validate row, column values
.if <nc> NEAR ; Continue?
;/*
;** Locate the offset to the bottom right hand corner of the target
;** rectangle to be scrolled. This is achieved by taking the BottomRow
;** value, multiply it by the screen width and then add RightCol value
;** to the result.
;*/
mov ax, es:[di].TextCols ; Target offset = (BottomRow
mul bx ; * screen columns +
add ax, [bp].RightCol ; right column) * 2
add ax, ax ;
push ax ; Save Target offset
;/*
;** Use the scroll scale factor to calculate the total number of bytes
;** neccessary to determine where the source offset is located.
;** GetScrollByteCount returns this value in AX.
;*/
call GetScrollByteCount ; AX = byte count
pop bx ; BX = Target offset
;/*
;** Determine the source offset by taking the byte count obtained
;** above and subtract from the target buffer offset.
;*/
mov dx, bx ; Source offset = Target offset
sub dx, ax ; - (# of lines to scroll *
; screen columns * 2)
push dx ; Save Source offset
;/*
;** Locate the offset to the top left hand corner of the target
;** rectangle to be scrolled. This is achieved by taking the TopRow
;** value, multiply it by the screen width and then add LeftCol value
;** to the result.
;*/
mov ax, es:[di].TextCols ; End offset = (TopRow *
mul [bp].TopRow ; screen columns + LeftCol
add ax, [bp].LeftCol ; -1) * 2
dec ax ;
add ax, ax ;
mov dx, ax ; DX = End offset
;/*
;** Calculate the number of bytes to skip between the end of one line
;** and the beginning of the next line. This is achieved by taking
;** the screen width and subtract it by the number of columns between
;** the RightCol and LeftCol and then multiply it by 2.
;** GetLineSkipByteCount returns this value in CX.
;*/
call GetLineSkipByteCount ; CX = # of bytes to skip
;/*
;** Setup source and destination selectors. If both LVB and PVB are
;** selected for update then all changes will go to the LVB first
;** before transfering the changes to the PVB. GetLVB_PVB_Cell will
;** also return the cell in AX.
;*/
call GetLVB_PVB_Cell ; AX = cell
; BX = Target offset
; DX = End offset
pop si ; DS:SI -> Source buffer
mov di, bx ; ES:DI -> Target buffer
std ; Transfer from right to
; left, bottom up
;/*
;** If each line within the target rectangle to be scrolled occupies
;** the entire width of the screen then a contiguous block move will
;** be opted.
;** For non-contiguous lines, scroll down is done by moving each line
;** down one at a time until the requested number of lines are scrolled.
;*/
.if <ncxz> ; Non-contiguous lines?
mov dx, [bp].BottomRow ; DX = row count between
sub dx, [bp].TopRow ; TopRow and BottomRow
inc dx ;
push dx ; Save total row count
push di ; Save Target offset
push ax ; Save cell
sub dx, [bp].ScrollCount ; DX = # of row to move down
mov ax, [bp].SkipLength ; AX = skip length
mov bx, [bp].Retrace ; Setup retrace indicator
.if <nonzero dx> ; Any lines to scroll?
.repeat ;
mov cx, [bp].LineLength
call _MOVSW ; Copy one line
sub si, ax ; Advance to start of
sub di, ax ; next line
dec dx ; Adjust row count
.until <z> ; More lines to scroll?
.endif ;
mov si, ax ; SI = skip length
pop ax ; AX = cell
mov dx, [bp].ScrollCount ; DX = remaining row count
.repeat ;
mov cx, [bp].LineLength ; CX = line length
call _STOSW ; Fill line with cell
sub di, si ; Advance to start of next line
dec dx ; Adjust row count
.until <z> ; More lines to fill?
pop di ; DI = Target offset
pop dx ; DX = total row count
;/*
;** If PVB update is also required then transfer the updated rectangle
;** from the LVB to the corresponding location in the PVB.
;*/
.if <[bp].PVB_Sel a 0> ; Required update to PVB?
mov es, [bp].PVB_Sel ; ES:DI -> PVB buffer
mov ax, si ; AX = skip length
mov si, di ; DS:SI -> LVB buffer
inc bx ; Retrace wait required
.repeat ;
mov cx, [bp].LineLength
call _MOVSW ; Copy a line to PVB
sub si, ax ; Advance to start of
sub di, ax ; next line
dec dx ; Adjust row count
.until <z> ; More lines to copy?
.endif ;
.else ; Non contiguous lines!
; DX = End offset
push di ; Save Target offset
push dx ; Save End offset
mov cx, si ; CX = (Source offset -
sub cx, dx ; End offset) / 2
shr cx, 1 ; CX = transfer count
mov bx, [bp].Retrace ; Setup retrace indicator
.if <ncxz> ; Source = destination?
call _MOVSW ; Block copy
.endif ;
pop dx ; DX = End offset
mov cx, di ; CX = (current destination
sub cx, dx ; offset - End offset) / 2
shr cx, 1 ;
call _STOSW ; Copy cell to remaining lines
;/*
;** If PVB update is also required then transfer the updated rectangle
;** from the LVB to the corresponding location in the PVB.
;*/
pop di ; DI = Target offset
.if <[bp].PVB_Sel a cx> ; Required update to PVB?
mov es, [bp].PVB_Sel ;
mov si, di ; DS:SI -> LVB buffer
mov cx, di ; CX = (Target offset - End
sub cx, dx ; offset) / 2
shr cx, 1 ;
inc bx ; Retrace wait required
call _MOVSW ; Copy rectangle to PVB
.endif ;
.endif ;
cld ;
sub ax, ax ; Clear return code
.endif ;
ret ;
ScrollDown ENDP
;/****************************************************************************
;*
;* SUBROUTINE NAME: ScrollLeft
;*
;* DESCRIPTIVE NAME: Video device handler scroll left routine
;*
;* FUNCTION: Process scroll left sub-function
;* Scrolls a portion of the PVB, LVB left a specified
;* number of times and then fill the vacant portion
;* with the user specified cell.
;*
;* ENTRY POINT: ScrollLeft
;* LINKAGE: Near Call from BUFFERUPDATE rouinte
;*
;* INPUT:
;*
;* AX = 0
;* SS:BP ---> Stack frame (see VDHSTRUC.INC)
;* DS:SI ---> Parameter block buffer (see CGABUFUP.ASM)
;* ES:DI ---> Mode data in environment buffer (see CGABUFUP.ASM)
;*
;* PARAMETER BLOCK FORMAT:
;*
;* SIZE DESCRIPTION
;* ---- -----------
;*
;* WORD Parameter length
;* WORD Flags (target buffer - LVB, PVB)
;* DWORD Application data address
;* DWORD Application data2 address (cell to be used to fill void)
;* WORD Index (5)
;* WORD Starting row (top row)
;* WORD Starting column (left column)
;* WORD Secondary row (bottom row)
;* WORD Secondary column (right column)
;* WORD RepeatFactor (# of times to scroll)
;* WORD LogicalBufSel
;*
;* OUTPUT:
;*
;* EXIT-NORMAL: AX = 0
;*
;* EXIT-ERROR: AX = ValidateScrollParms
;*
;* EFFECTS: All
;*
;* INTERNAL REFERENCES: ValidateScrollParms,
;*
;* EXTERNAL REFERENCES: _MOVSW, _STOSW
;*
;****************************************************************************/
PUBLIC ScrollLeft
ScrollLeft PROC NEAR
;/*
;** Validate input row, column parameters. The carry flag is used
;** to indicate whether an abnormal condition occured. On exit the
;** following registers are also setup if the carry flag is not set:
;** AX, [bp].TopRow = Adjusted starting row
;** BX, [bp].BottomRow = Adjusted ending row
;** CX, [bp].LeftCol = Adjusted starting column
;** DX, [bp].RightCol = Adjusted ending column
;*/
call ValidateScrollParms ; Validate row, column values
.if <nc> NEAR ; Continue?
;/*
;** Locate the offset to the upper right hand corner of the target
;** rectangle to be scrolled. This is achieved by taking the TopRow
;** value, multiply it by the screen width and then add LeftCol value
;** to the result.
;*/
mul es:[di].TextCols ; Target offset = (TopRow
add ax, cx ; * screen columns
add ax, ax ; + LeftCol) * 2
push ax ; Save Target offset
;/*
;** Scroll left is accomplished by moving each line left starting from
;** a source location within the same line. The source location is
;** obtained by advancing from the target location N cells to the right
;** where each advancement of a cell represents one scroll factor to
;** the left.
;*/
mov dx, ax ; DX = Source offset
mov ax, [bp].RightCol ; AX = column count between
sub ax, [bp].LeftCol ; RightCol and LeftCol
inc ax ;
mov cx, ax ; CX = column count
.if <cx a [si].RepeatFactor> ; Column count > scroll count?
mov ax, [si].RepeatFactor ; Source offset = N cells to
add dx, ax ; the right of the target
add dx, ax ; location
.endif ;
push dx ; Save Source offset
mov [bp].ScrollCount, ax ; Column count < scroll count
sub cx, ax ; Line length = column count -
mov [bp].LineLength, cx ; scroll count
sub ax, es:[di].TextCols ; AX = # of bytes to skip
neg ax ; between lines
sub ax, cx ;
add ax, ax ;
mov [bp].SkipLength, ax ;
mov dx, [bp].ScrollCount ; DX = adjustment byte count to
shl dx, 1 ; compensate for cell fill
mov cx, [bp].BottomRow ; CX = # of rows between
sub cx, [bp].TopRow ; TopRow and BottomRow
inc cx ;
;/*
;** Setup source and destination selectors. If both LVB and PVB are
;** selected for update then all changes will go to the LVB first
;** before transfering the changes to the PVB. GetLVB_PVB_Cell will
;** also return the cell in AX.
;*/
call GetLVB_PVB_Cell ; AX = cell
pop si ; DS:SI -> Source buffer
pop di ; DS:SI -> Target buffer
push di ; Save Target offset
push cx ; Save total row count
mov bx, [bp].Retrace ; Setup retrace indicator
.repeat ;
push cx ; Save current row count
mov cx, [bp].LineLength ; CX = line length
.if <ncxz> ; Source = destination?
call _MOVSW ; Shift line left
.endif ;
mov cx, [bp].ScrollCount ; CX = cell count
call _STOSW ; Fill N cells
add si, dx ; Account for cells filled
add si, [bp].SkipLength ; Advance to start of
add di, [bp].SkipLength ; next line
pop cx ; Restore current row count
.loop ;
pop cx ; CX = total row count
pop di ; DI = Target offset
; DX = cell adjustment byte
; count
;/*
;** If PVB update is also required then transfer the updated rectangle
;** from the LVB to the corresponding location in the PVB.
;*/
.if <[bp].PVB_Sel a 0> ; Required update to PVB?
mov es, [bp].PVB_Sel ; ES:DI -> PVB buffer
mov si, di ; DS:SI -> LVB buffer
shr dx, 1 ; Word align cell byte count
add [bp].LineLength, dx ; Gross line length
mov dx, [bp].SkipLength ;
inc bx ; Retrace wait required
.repeat ;
push cx ; Save current row count
mov cx, [bp].LineLength ; CX = line length
call _MOVSW ; Copy a line to PVB
add si, dx ; Skip to next line
add di, dx ;
pop cx ; Restore current row count
.loop ;
.endif ;
sub ax, ax ; Clear return code
.endif ;
ret ;
ScrollLeft ENDP
;/****************************************************************************
;*
;* SUBROUTINE NAME: ScrollRight
;*
;* DESCRIPTIVE NAME: Video device handler scroll right routine
;*
;* FUNCTION: Process scroll right sub-function
;* Scrolls a portion of the PVB, LVB right to a specified
;* number of times and then fill the vacant portion with
;* the user specified cell.
;*
;* ENTRY POINT: ScrollRight
;* LINKAGE: Near Call from BUFFERUPDATE rouinte
;*
;* INPUT:
;*
;* AX = 0
;* SS:BP ---> Stack frame (see VDHSTRUC.INC)
;* DS:SI ---> Parameter block buffer (see CGABUFUP.ASM)
;* ES:DI ---> Mode data in environment buffer (see CGABUFUP.ASM)
;*
;* PARAMETER BLOCK FORMAT:
;*
;* SIZE DESCRIPTION
;* ---- -----------
;*
;* WORD Parameter length
;* WORD Flags (target buffer - LVB, PVB)
;* DWORD Application data address
;* DWORD Application data2 address (cell to be used to fill void)
;* WORD Index (6)
;* WORD Starting row (top row)
;* WORD Starting column (left column)
;* WORD Secondary row (bottom row)
;* WORD Secondary column (right column)
;* WORD RepeatFactor (# of times to scroll)
;* WORD LogicalBufSel
;*
;* OUTPUT:
;*
;* EXIT-NORMAL: AX = 0
;*
;* EXIT-ERROR: AX = ValidateScrollParms
;*
;* EFFECTS: All
;*
;* INTERNAL REFERENCES: ValidateScrollParms,
;*
;* EXTERNAL REFERENCES: _MOVSW, _STOSW
;*
;****************************************************************************/
PUBLIC ScrollRight
ScrollRight PROC NEAR
;/*
;** Validate input row, column parameters. The carry flag is used
;** to indicate whether an abnormal condition occured. On exit the
;** following registers are also setup if the carry flag is not set:
;** AX, [bp].TopRow = Adjusted starting row
;** BX, [bp].BottomRow = Adjusted ending row
;** CX, [bp].LeftCol = Adjusted starting column
;** DX, [bp].RightCol = Adjusted ending column
;*/
call ValidateScrollParms ; Validate row, column values
.if <nc> NEAR ; Continue?
;/*
;** Locate the offset to the bottom right hand corner of the target
;** rectangle to be scrolled. This is achieved by taking the BottomRow
;** value, multiply it by the screen width and then add RightCol value
;** to the result.
;*/
mov ax, es:[di].TextCols ; Target offset = (BottomRow
mul bx ; * screen columns +
add ax, [bp].RightCol ; RightCol) * 2
add ax, ax ;
push ax ; Save Target offset
;/*
;** Scroll right is accomplished by moving each line right starting
;** from a source location within the same line. The source location
;** is obtained by descending from the target location N cells to the
;** left where each descending movement of a cell represents one scroll
;** factor to the right.
;*/
mov dx, ax ; DX = Source offset
mov ax, [bp].RightCol ; AX = column count between
sub ax, [bp].LeftCol ; RightCol and LeftCol
inc ax ;
mov cx, ax ; CX = column count
.if <cx a [si].RepeatFactor> ; Column count > scroll count?
mov ax, [si].RepeatFactor ; Source offset = N cells to
sub dx, ax ; the left of the target
sub dx, ax ; location
.endif ;
push dx ; Save Source offset
mov [bp].ScrollCount, ax ; Column count < scroll count
sub cx, ax ; Line length = column count -
mov [bp].LineLength, cx ; scroll count
sub ax, es:[di].TextCols ; AX = # of bytes to skip
neg ax ; between lines
sub ax, cx ;
add ax, ax ;
mov [bp].SkipLength, ax ;
mov dx, [bp].ScrollCount ; DX = adjustment byte count to
shl dx, 1 ; compensate for cell fill
mov cx, [bp].BottomRow ; CX = row count between
sub cx, [bp].TopRow ; TopRow and BottomRow
inc cx ;
;/*
;** Setup source and destination selectors. If both LVB and PVB are
;** selected for update then all changes will go to the LVB first
;** before transfering the changes to the PVB. GetLVB_PVB_Cell will
;** also return the cell in AX.
;*/
call GetLVB_PVB_Cell ; AX = cell
pop si ; DS:SI -> Source buffer
pop di ; ES:DI -> Target buffer
push di ; Save Target offset
push cx ; Save total row count
mov bx, [bp].Retrace ; Setup retrace indicator
std ; Transfer from right to
; left, bottom up
.repeat ;
push cx ; Save current row count
mov cx, [bp].LineLength ; CX = line length
.if <ncxz> ; Source = destination?
call _MOVSW ; Shift line right
.endif ;
mov cx, [bp].ScrollCount ; CX = cell count
call _STOSW ; Fill N cells
sub si, dx ; Account for cells filled
sub si, [bp].SkipLength ; Advance to start of
sub di, [bp].SkipLength ; next line
pop cx ; Restore current row count
.loop ;
pop cx ; CX = total row count
pop di ; DI = Target offset
; DX = cell adjustment byte
; count
;/*
;** If PVB update is also required then transfer the updated rectangle
;** from the LVB to the corresponding location in the PVB.
;*/
.if <[bp].PVB_Sel a 0> ; Required update to PVB?
mov es, [bp].PVB_Sel ; ES:DI -> PVB buffer
mov si, di ; DS:SI -> LVB buffer
shr dx, 1 ; Word align cell byte count
add [bp].LineLength, dx ; Gross line length
mov dx, [bp].SkipLength ;
inc bx ; Retrace wait required
.repeat ;
push cx ; Save current row count
mov cx, [bp].LineLength ; CX = line length
call _MOVSW ; Copy a line to PVB
sub si, dx ; Skip to next line
sub di, dx ;
pop cx ; Restore current row count
.loop ;
.endif ;
sub ax, ax ; Clear return code
cld ;
.endif ;
ret ;
ScrollRight ENDP
;/****************************************************************************
;*
;* SUBROUTINE NAME: ValidateScrollParms
;*
;* DESCRIPTIVE NAME: Video device handler scroll parameter
;* validation procedure
;*
;* FUNCTION: Determine whether the row, column parameters given
;* are ambiguous. For example: ending row is greater
;* than starting row or ending column is greater than
;* starting column.
;*
;* ENTRY POINT: ValidateScrollParms
;* LINKAGE: Near Call from ScrollUp, ScrollDown,
;* ScrollLeft, ScrollRight
;*
;* INPUT:
;*
;* AX = 0
;* SS:BP ---> Stack frame (see VDHSTRUC.INC)
;* DS:SI ---> Parameter block buffer (see CGABUFUP.ASM)
;* ES:DI ---> Mode data in environment buffer (see CGABUFUP.ASM)
;*
;* OUTPUT: AX, [bp].TopRow = starting row
;* BX, [bp].BottomRow = ending row
;* CX, [bp].LeftCol = starting column
;* DX, [bp].RightCol = ending column
;* CY = 1 for invalid parameters or [SI].RepeatCount = 0
;*
;* EXIT-NORMAL: CY = 0
;* CY = 1 AND AX = 0
;*
;* EXIT-ERROR: CY = 1
;* AX = ERROR_VIO_COL
;* AX = ERROR_VIO_ROW
;*
;* EFFECTS: AX, BX, CX, DX, CY
;*
;* INTERNAL REFERENCES: None
;*
;* EXTERNAL REFERENCES: None
;*
;****************************************************************************/
PUBLIC ValidateScrollParms
ValidateScrollParms PROC NEAR
.if <[si].RepeatFactor a ax> ; Anything to scroll?
push bp ;
;/*
;** If either of the starting and ending row value is beyond the
;** normalized text resolution of the current display mode then
;** convert it to the current maximum row value allowed.
;*/
mov bp, es:[di].TextRows ; Get max row resolution
dec bp ; Normalize it
mov ax, [si].Row ; Get input starting row value
.if <ax a bp> ; Starting row beyond limit?
mov ax, bp ; Set it to max allowed
.endif ;
mov bx, [si].Row2 ; Get input ending row value
.if <bx a bp> ; Ending row beyond limit?
mov bx, bp ; Set it to max allowed
.endif ;
;/*
;** If either of the starting and ending column value is beyond the
;** normalized text resolution of the current display mode then
;** convert it to the current maximum column value allowed.
;*/
mov bp, es:[di].TextCols ; Get max column resolution
dec bp ; Normalize it
mov cx, [si].Col ; Get input starting col value
.if <cx a bp> ; Starting col beyond limit?
mov cx, bp ; Set it to max allowed
.endif ;
mov dx, [si].Col2 ; Get input ending col value
.if <dx a bp> ; Ending col beyond limit?
mov dx, bp ; Set it to max allowed
.endif ;
pop bp ;
;/*
;** Validate input row, column values. An error is returned if either
;** the ending row value is greater than the starting row value or the
;** the ending column value is greater than the starting column value.
;**
;** Notice that the comparison is made in such a way that the carry
;** flag is set when the comparison fails.
;*/
.if <bx ae ax> ; Ending row >= starting row?
.if <dx ae cx> ; Ending col >= starting col?
mov [bp].TopRow, ax ; Save the converted input
mov [bp].BottomRow, bx ; row, column values
mov [bp].LeftCol, cx ;
mov [bp].RightCol, dx ; Carry flag bit must be clear
.else ;
mov ax, ERROR_VIO_COL ; Carry flag should be set
.endif ;
.else ;
mov ax, ERROR_VIO_ROW ; Carry flag shoud be set
.endif ;
.else ;
stc ; Force normal exit
.endif ;
ret ;
ValidateScrollParms ENDP
;/****************************************************************************
;*
;* SUBROUTINE NAME: GetScrollByteCount
;*
;* DESCRIPTIVE NAME: Video device handler get scroll byte count
;*
;* FUNCTION: Determine how many lines the caller is intended to
;* scroll up within the rectangle specified and then
;* use this number to calculate the number of bytes
;* it takes from the beginning of the target location
;* to the start of the source line.
;*
;* ENTRY POINT: GetScrollByteCount
;* LINKAGE: Near Call from ScrollUp, ScrollDown
;*
;* INPUT:
;*
;* BX = Bottom row
;* SS:BP ---> Stack frame (see VDHSTRUC.INC)
;* DS:SI ---> Parameter block buffer (see CGABUFUP.ASM)
;* ES:DI ---> Mode data in environment buffer (see CGABUFUP.ASM)
;*
;* OUTPUT: AX = # of bytes from the beginning of the buffer
;* to the start of the first scroll line
;* [si].RepeatFactor = Actual # of lines to scroll
;* [bp].ScrollCount = Actual # of lines to scroll
;*
;* EXIT-NORMAL: None
;*
;* EXIT-ERROR: None
;*
;* EFFECTS: AX, DX
;*
;* INTERNAL REFERENCES: None
;*
;* EXTERNAL REFERENCES: None
;*
;****************************************************************************/
PUBLIC GetScrollByteCount
GetScrollByteCount PROC NEAR
ASSUME CS:R2CSEG, DS:NOTHING, ES:NOTHING
mov ax, bx ; Calculate the number of
sub ax, [bp].TopRow ; rows between top row
inc ax ; and bottom row
.if <ax b [si].RepeatFactor> ; Use the user supplied repeat
mov [si].RepeatFactor, ax ; factor if it is less than
.endif ; number of rows in the
mov ax, [si].RepeatFactor ; target rectangle
mov [bp].ScrollCount, ax ; Save scroll count on stack
mul es:[di].TextCols ; Calculate the total byte
add ax, ax ; count based on the # of
ret ; lines to scroll
GetScrollByteCount ENDP
;/****************************************************************************
;*
;* SUBROUTINE NAME: GetLineSkipByteCount
;*
;* DESCRIPTIVE NAME: Video device handler get scroll byte count
;*
;* FUNCTION: Determine the number of bytes to skip between the
;* end of one line and the beginning of the next line.
;*
;* ENTRY POINT: GetLineSkipByteCount
;* LINKAGE: Near Call from ScrollUp, ScrollDown
;*
;* INPUT:
;*
;* CX = Left column
;* SS:BP ---> Stack frame (see VDHSTRUC.INC)
;* DS:SI ---> Parameter block buffer (see CGABUFUP.ASM)
;* ES:DI ---> Mode data in environment buffer (see CGABUFUP.ASM)
;*
;* OUTPUT: AX, [bp].LineLength = Actual length in cells for
;* each line
;* CX, [bp].SkipLength = # of bytes to skip between
;* lines
;* EXIT-NORMAL: None
;*
;* EXIT-ERROR: None
;*
;* EFFECTS: AX, CX
;*
;* INTERNAL REFERENCES: None
;*
;* EXTERNAL REFERENCES: None
;*
;****************************************************************************/
PUBLIC GetLineSkipByteCount
GetLineSkipByteCount PROC NEAR
ASSUME CS:R2CSEG, DS:NOTHING, ES:NOTHING
mov ax, [bp].RightCol ; Calculate the number of
sub ax, cx ; columns between right
inc ax ; column and left column
mov [bp].LineLength, ax ; Save line length
mov cx, es:[di].Textcols ; Calculate the number of
sub cx, ax ; bytes to skip between
add cx, cx ; lines
mov [bp].SkipLength, cx ; CX = bytes to skip between
ret ; lines
GetLineSkipByteCount ENDP
;/****************************************************************************
;*
;* SUBROUTINE NAME: GetLVB_PVB_Cell
;*
;* DESCRIPTIVE NAME: Video device handler get LVB, PVB and cell
;*
;* FUNCTION: Determine which buffer address to use based on
;* the input flags set. If the user wishes to
;* scroll both the LVB and the PVB then the LVB
;* will be updated first before the PVB is refreshed.
;*
;* ENTRY POINT: GetLVB_PVB_Cell
;* LINKAGE: Near Call from ScrollUp, ScrollDown,
;* ScrollLeft, ScrollRight
;*
;* INPUT:
;*
;* CX = Left column
;* SS:BP ---> Stack frame (see VDHSTRUC.INC)
;* DS:SI ---> Parameter block buffer (see CGABUFUP.ASM)
;* ES:DI ---> Mode data in environment buffer (see CGABUFUP.ASM)
;*
;* OUTPUT: DS = PVB or LVB
;* ES = PVB or LVB
;* [bp].PVB_Sel = PVB if user requests both LVB & PVB
;* AX = Cell
;*
;* EXIT-NORMAL: None
;*
;* EXIT-ERROR: None
;*
;* EFFECTS: AX, SI, DI, DS, ES
;*
;* INTERNAL REFERENCES: None
;*
;* EXTERNAL REFERENCES: None
;*
;****************************************************************************/
PUBLIC GetLVB_PVB_Cell
GetLVB_PVB_Cell PROC NEAR
ASSUME CS:R2CSEG, DS:NOTHING, ES:NOTHING
mov di, [bp].PVB_Sel ; Assume PVB update
test [si].Flags, LVB_SEL_BIT ;
.if <nz> ; LVB requested?
test [si].Flags, PVB_SEL_BIT ;
.if <z> ; LVB update only?
mov [bp].PVB_Sel, 0 ; Indicate as such
.endif ;
mov di, [si].LogicalBufSel ; Use LVB instead
.else ; PVB only!
mov [bp].PVB_Sel, 0 ; Indicate PVB update only
inc [bp].Retrace ; Retrace wait required
.endif ;
lds si, [si].AppCellAddr ;
lodsw ; AX = user supplied cell
mov ds, di ; DS, ES = PVB or LVB
mov es, di ;
ret ;
GetLVB_PVB_Cell ENDP
R2CSEG ENDS
END