home *** CD-ROM | disk | FTP | other *** search
- ; 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. │
- ;└────────────────────────────────────────────────────────────────────────┘
-