home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
QBAS
/
QBNWS204.ZIP
/
WINDOWS.ZIP
/
DISPLAY.ASM
next >
Wrap
Assembly Source File
|
1991-07-15
|
32KB
|
599 lines
; DISPLAY.ASM ─ contains a collection of video-related procedures and
; functions for use with Microsoft high-level languages.
;
; Author: Christy Gemmell
; For: Assembly-Language Toolbox for QuickBASIC
; Version: 5.0
; Date: 9/6/1991
;
; Compatible with Microsoft QuickBASIC 4.x and BASIC 6 compilers.
; Assembled using Microsoft Macro Assembler, MASM version 5.1
;
;┌────────────────────────────────────────────────────────────────────────┐
;│ Global symbols and procedures. │
;└────────────────────────────────────────────────────────────────────────┘
;
.model medium
public ScreenAddress
public ScreenCopy
public ScreenRead
public ScreenWrite
public VideoType
public WriteByte
public Attribute
public Delay
public Explode
public FastPrint
.code
;┌────────────────────────────────────────────────────────────────────────┐
;│ Data Division. │
;└────────────────────────────────────────────────────────────────────────┘
;
; Video parameters - default to monochrome screen display
;
SnowFlag db 0 ; Snow prevention flag
VideoRam dw 0B000h ; Current video segment
VideoPort dw 03BAh ; Current video status port
Param1 label word
Mode db 7 ; Current screen mode
Columns db 80 ; Current screen width
Param2 label word
Rows db 25 ; Current screen length
ActivePage db 0 ; Current video page
TopLeft label word ; Upper left co-ordinates
H1 db ? ; Horizontal length
V1 db ? ; Vertical height
BotRight label word ; Lower right co-ordinates
H2 db ? ; Horizontal length
V2 db ? ; Vertical height
Factor label word
dw 0
dw 0
Counter label word
dw ?
dw ?
Seed label word
dw 7397
dw 29447
dw 802
Multiple label word
dw 179
dw 183
dw 182
Modulus label word
dw 32771
dw 32779
dw 32783
;┌────────────────────────────────────────────────────────────────────────┐
;│ Calculate address from a pair of row/column co-ordinates. │
;└────────────────────────────────────────────────────────────────────────┘
;
; Given the row/column column co-ordinate of a character on the screen,
; this function returns the segment:offset address of that character in
; video memory. The address is correctly adjusted to the start of the
; the currently active display page, but no check is made to ensure that
; the co-ordinates supplied are within the actual screen bounds.
;
; Input: AL = Row co-ordinate of character (base zero).
; AH = Column co-ordinate of character (base zero).
;
; Output: ES:DI==> Address in video display buffer of the
; character cell specified.
; DX = CRT status register port address.
;
; It is assumed that a previous call has been made to the VideoType
; function, above, to determine the screen width, the port address of
; the CRT status register and the correct video display segment.
;
ScreenAddress proc far
push ax ; Save working registers
push bx
mov bh,ah ; Column to BH
mov bl,cs:Columns ; Get current screen width
shl bl,1 ; Add in attribute bytes
mul bl ; Multiply by row number
xor bl,bl ; Calculate
xchg bh,bl ; column offset
shl bl,1 ; in BX
add ax,bx ; Add it to the row offset
mov di,ax ; and copy to DI
xor ax,ax ; Index to ROM-BIOS
mov es,ax ; data in low memory
mov ax,es:[44Eh] ; Get offset of current page
add di,ax ; Adjust target pointer
mov es,cs:VideoRam ; Return segment of video RAM
mov dx,cs:VideoPort ; Return CRT status port
pop bx ; Clean up the stack
pop ax
ret ; and return to caller
ScreenAddress endp
;┌────────────────────────────────────────────────────────────────────────┐
;│ Copy a character and attribute from the video display. │
;└────────────────────────────────────────────────────────────────────────┘
;
; If the 'snow prevention' flag is set, this routine waits until the
; beginning of the next CRT horizontal retrace period before reading
; data from the display. This is necessary only on machines fitted with
; a Colour Graphics Adaptor (CGA) which may suffer from glitches or
; screen snow if data is copied from the screen while the video buffer
; is being refreshed.
;
; Input: DS:SI==> Address of the screen location from which
; the data is to be copied.
; ES:DI==> Address of the buffer into which the data
; is to be copied.
; DX = Port address of CRT status register.
;
; Output: SI and DI Updated to point to next buffer locations.
; AX destroyed.
;
ScreenCopy proc far
cmp cs:SnowFlag,0 ; Snow prevention needed?
cli ; Don't interrupt!
jz Copy_03 ; No, don't bother
Copy_01:
in al,dx ; Read video port
test al,1 ; Test bit zero
jnz Copy_01 ; Wait until it's reset
Copy_02:
in al,dx ; Read port again
test al,1 ; Test bit zero
jz Copy_02 ; Wait until it's set
Copy_03:
movsw ; Transfer one word
sti ; Restore interrupts
ret
ScreenCopy endp
;┌────────────────────────────────────────────────────────────────────────┐
;│ Read a character and attribute from the display. │
;└────────────────────────────────────────────────────────────────────────┘
;
; This procedure is similar to ScreenCopy, above, except that the word
; is simply loaded into AX instead of being copied into a buffer.
;
; Input: DS:SI==> address, in the video display buffer, from
; where the data is to be read
; DX = port address of the CRT status register.
;
; Output: AL = character at the specified address
; AH = display attribute given to character
; DI updated to point to the next word address
;
ScreenRead proc far
cmp cs:SnowFlag,0 ; Snow prevention needed?
jz Read_03 ; No, don't bother
cli ; Don't interrupt!
Read_01:
in al,dx ; Read video port
test al,1 ; Test bit zero
jnz Read_01 ; Wait until it's reset
Read_02:
in al,dx ; Read port again
test al,1 ; Test bit zero
jz Read_02 ; Wait until it's set
Read_03:
lodsw ; Get character and attribute
sti ; You were saying?
ret
ScreenRead endp
;┌────────────────────────────────────────────────────────────────────────┐
;│ Output a character and attribute to the video display. │
;└────────────────────────────────────────────────────────────────────────┘
;
; If the 'snow prevention' flag is set, this routine waits until the
; beginning of the next CRT horizontal retrace period before writing
; data to the display. This is necessary only on machines fitted with
; a Colour Graphics Adaptor (CGA) which may suffer from glitches or
; screen snow if data is written to the screen while the video buffer
; is being refreshed.
;
; Input: ES:DI==> Address in the video display buffer where
; the data is to be written.
; DX = Port address of CRT status register.
; AL = Character to output.
; AH = Display attribute of character.
;
; Output: DI Updated to point to next output address.
;
ScreenWrite proc far
push bx ; Preserve BX
cmp cs:SnowFlag,0 ; Snow prevention needed?
cli ; Don't interrupt!
jz Write_3 ; No, don't bother
mov bx,ax ; Save byte and attribute
Write_1:
in al,dx ; Read video port
test al,1 ; Test bit zero
jnz Write_1 ; Wait until it's reset
Write_2:
in al,dx ; Read port again
test al,1 ; Test bit zero
jz Write_2 ; Wait until it's set
mov ax,bx ; Recover data
Write_3:
stosw ; Write data to screen
sti ; Restore interrupts
pop bx ; Restore BX
ret
ScreenWrite endp
;┌────────────────────────────────────────────────────────────────────────┐
;│ Collect information about the current video display. │
;└────────────────────────────────────────────────────────────────────────┘
;
; Output: AL = Current display mode
; AH = Screen width in columns
; BL = Screen height in rows
; BH = Active display page
;
; The correct video display segment and CRT status port addresses are
; determined for the current system and, if necessary, the internal
; 'snow' prevention flag is set.
;
VideoType proc far
push bp ; Preserve these registers
push cx
push dx
push es
mov ah,0Fh ; ROM-BIOS Service 16
int 10h ; - Check video mode
cmp al,7 ; Monochrome display?
je Type_02 ; Yes, use defaults
mov cs:VideoRam,0B800h ; Otherwise set up
mov cs:VideoPort,03DAh ; for colour
Type_01:
mov cs:Param1,ax ; Save display mode and width
push bx ; Save active display page
xor bh,bh
mov dl,24 ; Default to 25 rows
mov ax,1130h ; ROM-BIOS Service 16
int 10h ; - get font information
pop bx
mov bl,dl ; DL = number of rows - 1
inc bl
mov cs:Param2,bx ; Save video page and height
mov bl,10h ; Test for presence
mov ah,12h ; of an EGA or VGA
int 10h ; display adaptor
cmp bl,10h ; Any response?
jne Type_02 ; Yes, can't be a CGA
mov cs:SnowFlag,1 ; Set snow prevention flag
Type_02:
mov bx,cs:Param2 ; Recover page and height
mov ax,cs:Param1 ; Recover mode and width
pop es ; Clean up the stack
pop dx
pop cx
pop bp
ret
VideoType endp
;┌────────────────────────────────────────────────────────────────────────┐
;│ Output a byte of data to video memory. │
;└────────────────────────────────────────────────────────────────────────┘
;
; This procedure is similar to ScreenWrite, above, except that only a
; single byte is written. It is used by the BackFill routine to reset
; the display attribute of a character, without changing the character
; itself.
;
; Input: ES:DI==> address, in the video display buffer, where
; the byte is to be written.
; DX = port address of the CRT status register.
; AL = the byte value to be written.
;
; Output: DI updated to point to the next byte address
;
WriteByte proc far
push ax ; Preserve this register
cmp cs:SnowFlag,0 ; Snow prevention needed?
jz Byte_03 ; No, don't bother
mov ah,al ; Save character to output
cli ; Don't interrupt!
Byte_01:
in al,dx ; Read video port
test al,1 ; Test bit zero
jnz Byte_01 ; Wait until it's reset
Byte_02:
in al,dx ; Read port again
test al,1 ; Test bit zero
jz Byte_02 ; Wait until it's set
mov al,ah ; Retrieve character
Byte_03:
stosb ; Write data to the screen
sti ; You were saying?
pop ax ; Clean up the stack
ret
WriteByte endp
;┌────────────────────────────────────────────────────────────────────────┐
;│ Calculate display attribute from fore and background colours. │
;└────────────────────────────────────────────────────────────────────────┘
;
Attribute proc far
push bp ; Save Base pointer
mov bp,sp ; Establish stack frame
mov dx,[bp+8] ; Get foreground colour
mov ax,[bp+6] ; Get background colour
and ax,000Fh ; Only 0-15 allowed
mov cl,4 ; Multiply it
shl ax,cl ; by sixteen
mov dh,dl ; Foreground to DH
and dh,10h ; Only 0-31 allowed
mov cl,3 ; Multiply it
shl dh,cl ; by eight
or al,dh ; Adjust
or al,dl ; to fit
pop bp ; Clean up the stack
ret 4 ; Return to QuickBASIC
Attribute endp
;┌────────────────────────────────────────────────────────────────────────┐
;│ Millisecond delay loop. │
;└────────────────────────────────────────────────────────────────────────┘
;
; The delay interval, in milliseconds, should be passed by value.
;
Delay proc far
push bp ; Save Base Pointer
mov bp,sp ; Establish stack frame
push ds ; Save all registers
push bx
push cx
push dx
mov cx,[bp+6] ; Get delay required
jcxz Delay_4 ; Ignore if zero
push cs ; Align code and
pop ds ; data segments
mov ax,Factor ; Load fudge factor
mov dx,Factor[2] ; into DX:AX
or ax,ax ; Has fudge been set?
jnz Delay_1 ; Yes, continue
call Fudge ; Otherwise set it
Delay_1:
mov bx,44 ; Divide by 44 to get
div bx ; loop counter value
Delay_2:
mov Counter,ax ; Set up for 1 msec delay
mov Counter[2],0 ; High word is not used
Delay_3:
sub Counter,1 ; Decrement count
sbb Counter[2],0
jns Delay_3 ; for 1 millisecond
loop Delay_2 ; for n milliseconds
Delay_4:
pop dx ; Clean up the stack
pop cx
pop bx
pop ds
pop bp
ret 2 ; Return to QuickBASIC
Delay endp
;┌────────────────────────────────────────────────────────────────────────┐
;│ Calculate delay fudge factor for host system. │
;└────────────────────────────────────────────────────────────────────────┘
;
Fudge proc near
push es ; Save this register
xor ax,ax ; Zero AX
mov Factor,ax ; Initialise
mov Factor[2],ax ; local data
mov es,ax ; Point ES to page zero
mov al,es:[46Ch] ; Get current timer count
Fudge_1:
cmp al,es:[46Ch] ; Has it changed?
je Fudge_1 ; No, wait till it does
mov al,es:[46Ch] ; Yes, get new count
Fudge_2:
add Factor,1 ; Increment
adc Factor[2],0 ; fudge factor
cmp al,es:[46Ch] ; Has timer changed yet?
je Fudge_2 ; No, keep incrementing
mov ax,Factor ; Yes, load fudge
mov dx,Factor[2] ; factor and return
pop es ; Clean up the stack
ret ; Return to caller
Fudge endp
;┌────────────────────────────────────────────────────────────────────────┐
;│ Clear screen rectangle explosively. │
;└────────────────────────────────────────────────────────────────────────┘
;
; The panel is cleared, starting at the centre point, and progressively
; moving outwards until the defined borders are reached. This gives the
; impression of the clear area exploding onto the screen.
;
Explode proc far
push bp ; Save Base pointer
mov bp,sp ; Establish stack frame
push es ; Save Extra Segment,
push ds ; Data segment,
push si ; and index
push di ; pointers
call VideoType ; Get video parameters
push cs ; Align Code and
pop ds ; Data segments
mov al,[bp+16] ; Get top-left row
dec al ; Use ROM-BIOS numbering
cmp al,0 ; Check for
jae Exp_01 ; legal
xor al,al ; values
Exp_01:
mov [bp+16],al ; Save it for later
mov al,[bp+14] ; Get top-left column
dec al ; Use ROM-BIOS numbering
cmp al,0 ; Check for
jae Exp_02 ; legal
xor al,al ; values
Exp_02:
mov [bp+14],al ; Save it for later
mov al,[bp+12] ; Get bottom-right row
dec al ; Use ROM-BIOS numbering
cmp al,Rows ; Check
jb Exp_03 ; for
mov al,Rows ; legal
dec al ; values
Exp_03:
mov [bp+12],al ; Save it for later
mov al,[bp+10] ; Get bottom-right column
dec al ; Use ROM-BIOS numbering
cmp al,Columns ; Check
jb Exp_04 ; for
mov al,Columns ; legal
dec al ; values
Exp_04:
mov [bp+10],al ; Save it for later
mov al,[bp+16] ; Get top-left row
cmp al,[bp+12] ; Below bottom-right?
jb Exp_05 ; If so, proceed
jmp Exp_15 ; If not, abort
Exp_05:
add al,[bp+12] ; Add bottom-right row
shr al,1 ; Divide by two
mov V1,al ; Store the result
mov V2,al ; twice
mov al,[bp+14] ; Get top-left column
cmp al,[bp+10] ; Left of right-hand edge?
jb Exp_06 ; If so, proceed
jmp Exp_15 ; If not, abort
Exp_06:
add al,[bp+10] ; Add bottom-right column
shr al,1 ; Divide by two
mov H1,al ; Store the result
mov H2,al ; twice
mov ax,[bp+6] ; Get delay value
cmp ax,1 ; Check for
jge Exp_07 ; legal
mov ax,1 ; values
Exp_07:
mov [bp+6],ax ; Save it for later
mov bh,[bp+8] ; Get display attribute
Exp_08:
mov al,[bp+16] ; Check top-left row
cmp al,V1 ; Reached it yet?
jae Exp_09 ; If not bump
dec V1 ; the counter
Exp_09:
mov al,[bp+12] ; Check bottom-right row
cmp al,V2 ; Reached it yet?
jbe Exp_10 ; If not bump
inc V2 ; the counter
Exp_10:
mov al,[bp+14] ; Check top-left column
mov cx,3 ; Iteration count
Exp_11:
cmp al,H1 ; Reached it yet?
jae Exp_12 ; If not bump
dec H1 ; the counter
loop Exp_11 ; Up to three times
Exp_12:
mov al,[bp+10] ; Check bottom-right column
mov cx,3 ; Iteration count
Exp_13:
cmp al,H2 ; Reached it yet?
jbe Exp_14 ; If not bump
inc H2 ; the counter
loop Exp_13 ; Up to three times
Exp_14:
mov dx,BotRight ; Get lower right co-ordinate
mov cx,TopLeft ; Get upper left co-ordinate
mov ax,0700h ; BIOS display service 7
int 10h ; - scroll down window
push [bp+6] ; Get delay count
call Delay ; Pause awhile
mov al,[bp+16] ; Get top-left row
cmp al,V1 ; Reached it?
jb Exp_08 ; No, do it again
mov al,[bp+14] ; Get top-left column
cmp al,H1 ; Reached it?
jb Exp_08 ; No, do it again
mov al,[bp+12] ; Get bottom-right row
cmp al,V2 ; Reached it?
ja Exp_08 ; No, do it again
mov al,[bp+10] ; Get bottom-right column
cmp al,H2 ; Reached it?
ja Exp_08 ; No, do it again
Exp_15:
pop di ; Clean up the stack
pop si
pop ds
pop es
pop bp
ret 12 ; Return to QuickBASIC
Explode endp
;┌────────────────────────────────────────────────────────────────────────┐
;│ Fast screen printing. │
;└────────────────────────────────────────────────────────────────────────┘
;
; This procedure outputs text directly to the video display without
; going through DOS or ROM-BIOS services.
;
FastPrint proc far
push bp ; Save Base pointer
mov bp,sp ; Establish stack frame
push es ; Save Extra Segment,
push si ; and index
push di ; pointers
call VideoType ; Get video parameters
mov dh,ah ; Load screen dimensions
mov dl,bl ; into DX
mov ax,[bp+12] ; Get row number
dec al ; Convert to base zero
cmp al,0 ; Top screen row?
jae Fast_01 ; Jump if not below
xor al,al ; Don't go over the top!
Fast_01:
cmp al,dl ; Bottom row?
jb Fast_02 ; Go no further
mov al,dl
dec al
Fast_02:
mov bx,[bp+10] ; Get column number
mov ah,bl ; into AH
dec ah ; Convert to base zero
cmp ah,0 ; Leftmost column?
jae Fast_03 ; Jump if not below
xor ah,ah ; Don't go off the screen
Fast_03:
cmp ah,dh ; Rightmost column?
jb Fast_04 ; Go no further
mov ah,dh ; Don't go off the screen
dec ah ; Base zero, remember?
Fast_04:
mov bx,[bp+8] ; Index to string descriptor
mov cx,[bx] ; String length to CX
jcxz Fast_06 ; Abort if a null string
mov si,[bx+2] ; DS:SI==> string data
call ScreenAddress ; Calculate target address
mov ax,[bp+6] ; Get display attribute
xchg ah,al ; into AH
cld ; Clear direction flag
Fast_05:
lodsb ; Get a byte from the string
call ScreenWrite ; Write byte and attribute
loop Fast_05 ; For length of string
xor ax,ax ; Report success
Fast_06:
pop di ; Clean up the stack
pop si
pop es
pop bp
ret 8 ; Return to QuickBASIC
FastPrint endp
end
;┌────────────────────────────────────────────────────────────────────────┐
;│ (c) 1988,1991 By Christy Gemmell and Singular SoftWare. │
;└────────────────────────────────────────────────────────────────────────┘