home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / QBAS / QBNWS204.ZIP / WINDOWS.ZIP / DISPLAY7.ASM < prev    next >
Assembly Source File  |  1991-07-15  |  32KB  |  608 lines

  1. ; DISPLAY.ASM ─ contains a collection of video-related procedures and
  2. ;               functions for use with Microsoft high-level languages.
  3. ;
  4. ;   Author:     Christy Gemmell
  5. ;   For:        Assembly-Language Toolbox for QuickBASIC
  6. ;   Version:    5.0
  7. ;   Date:       9/6/1991
  8. ;
  9. ;   Compatible with Microsoft Extended QuickBASIC and BASIC 7 PDS
  10. ;   Assembled using Microsoft Macro Assembler, MASM version 5.1
  11. ;
  12. ;┌────────────────────────────────────────────────────────────────────────┐
  13. ;│      Global symbols and procedures.                                    │
  14. ;└────────────────────────────────────────────────────────────────────────┘
  15. ;
  16.                 .model  medium
  17.  
  18.                 public  ScreenAddress
  19.                 public  ScreenCopy
  20.                 public  ScreenRead
  21.                 public  ScreenWrite
  22.                 public  VideoType
  23.                 public  WriteByte
  24.                 public  Attribute
  25.                 public  Delay
  26.                 public  Explode
  27.                 public  FastPrint
  28.  
  29.                 extrn   StringAddress: proc
  30.  
  31.                 .code
  32.  
  33. ;┌────────────────────────────────────────────────────────────────────────┐
  34. ;│      Data Division.                                                    │
  35. ;└────────────────────────────────────────────────────────────────────────┘
  36. ;
  37. ;   Video parameters - default to monochrome screen display
  38. ;
  39. SnowFlag        db      0                       ; Snow prevention flag
  40. VideoRam        dw      0B000h                  ; Current video segment
  41. VideoPort       dw      03BAh                   ; Current video status port
  42. Param1          label   word
  43. Mode            db      7                       ; Current screen mode  
  44. Columns         db      80                      ; Current screen width
  45. Param2          label   word
  46. Rows            db      25                      ; Current screen length
  47. ActivePage      db      0                       ; Current video page
  48. TopLeft         label   word                    ; Upper left co-ordinates
  49. H1              db      ?                       ; Horizontal length
  50. V1              db      ?                       ; Vertical height
  51. BotRight        label   word                    ; Lower right co-ordinates
  52. H2              db      ?                       ; Horizontal length
  53. V2              db      ?                       ; Vertical height
  54.  
  55. Factor          label   word
  56.                 dw      0
  57.                 dw      0
  58. Counter         label   word
  59.                 dw      ?
  60.                 dw      ?
  61. Seed            label   word
  62.                 dw      7397
  63.                 dw      29447
  64.                 dw      802
  65. Multiple        label   word
  66.                 dw      179
  67.                 dw      183
  68.                 dw      182
  69. Modulus         label   word
  70.                 dw      32771
  71.                 dw      32779
  72.                 dw      32783
  73.  
  74. ;┌────────────────────────────────────────────────────────────────────────┐
  75. ;│      Calculate address from a pair of row/column co-ordinates.         │
  76. ;└────────────────────────────────────────────────────────────────────────┘
  77. ;
  78. ;   Given the row/column column co-ordinate of a character on the screen,
  79. ;   this function returns the segment:offset address of that character in
  80. ;   video memory. The address is correctly adjusted to the start of the
  81. ;   the currently active display page, but no check is made to ensure that
  82. ;   the co-ordinates supplied are within the actual screen bounds.
  83. ;
  84. ;   Input:      AL      = Row co-ordinate of character (base zero).
  85. ;               AH      = Column co-ordinate of character (base zero).
  86. ;
  87. ;   Output:     ES:DI==>  Address in video display buffer of the
  88. ;                         character cell specified.
  89. ;               DX      = CRT status register port address.
  90. ;
  91. ;   It is assumed that a previous call has been made to the VideoType
  92. ;   function, above, to determine the screen width, the port address of
  93. ;   the CRT status register and the correct video display segment.
  94. ;
  95. ScreenAddress   proc    far
  96.                 push    ax                      ; Save working registers
  97.                 push    bx
  98.                 mov     bh,ah                   ; Column to BH
  99.                 mov     bl,cs:Columns           ; Get current screen width
  100.                 shl     bl,1                    ; Add in attribute bytes
  101.                 mul     bl                      ; Multiply by row number
  102.                 xor     bl,bl                   ; Calculate
  103.                 xchg    bh,bl                   ;    column offset
  104.                 shl     bl,1                    ;      in BX
  105.                 add     ax,bx                   ; Add it to the row offset
  106.                 mov     di,ax                   ;    and copy to DI  
  107.                 xor     ax,ax                   ; Index to ROM-BIOS
  108.                 mov     es,ax                   ;    data in low memory
  109.                 mov     ax,es:[44Eh]            ; Get offset of current page
  110.                 add     di,ax                   ; Adjust target pointer
  111.                 mov     es,cs:VideoRam          ; Return segment of video RAM
  112.                 mov     dx,cs:VideoPort         ; Return CRT status port    
  113.                 pop     bx                      ; Clean up the stack
  114.                 pop     ax
  115.                 ret                             ;    and return to caller
  116. ScreenAddress   endp
  117.  
  118. ;┌────────────────────────────────────────────────────────────────────────┐
  119. ;│      Copy a character and attribute from the video display.            │
  120. ;└────────────────────────────────────────────────────────────────────────┘
  121. ;
  122. ;   If the 'snow prevention' flag is set, this routine waits until the
  123. ;   beginning of the next CRT horizontal retrace period before reading
  124. ;   data from the display. This is necessary only on machines fitted with
  125. ;   a Colour Graphics Adaptor (CGA) which may suffer from glitches or
  126. ;   screen snow if data is copied from the screen while the video buffer
  127. ;   is being refreshed.
  128. ;
  129. ;   Input:      DS:SI==>    Address of the screen location from which
  130. ;                           the data is to be copied. 
  131. ;               ES:DI==>    Address of the buffer into which the data
  132. ;                           is to be copied.
  133. ;               DX =        Port address of CRT status register.
  134. ;
  135. ;   Output:     SI and DI   Updated to point to next buffer locations.
  136. ;               AX          destroyed.
  137. ;
  138. ScreenCopy      proc    far  
  139.                 cmp     cs:SnowFlag,0           ; Snow prevention needed?
  140.                 cli                             ; Don't interrupt!
  141.                 jz      Copy_03                 ; No, don't bother
  142. Copy_01:
  143.                 in      al,dx                   ; Read video port
  144.                 test    al,1                    ; Test bit zero
  145.                 jnz     Copy_01                 ; Wait until it's reset
  146. Copy_02:
  147.                 in      al,dx                   ; Read port again
  148.                 test    al,1                    ; Test bit zero
  149.                 jz      Copy_02                 ; Wait until it's set
  150. Copy_03:
  151.                 movsw                           ; Transfer one word
  152.                 sti                             ; Restore interrupts
  153.                 ret
  154. ScreenCopy      endp
  155.  
  156. ;┌────────────────────────────────────────────────────────────────────────┐
  157. ;│      Read a character and attribute from the display.                  │
  158. ;└────────────────────────────────────────────────────────────────────────┘
  159. ;
  160. ;   This procedure is similar to ScreenCopy, above, except that the word
  161. ;   is simply loaded into AX instead of being copied into a buffer.
  162. ;
  163. ;   Input:      DS:SI==>    address, in the video display buffer, from
  164. ;                           where the data is to be read
  165. ;               DX =        port address of the CRT status register.
  166. ;
  167. ;   Output:     AL =        character at the specified address
  168. ;               AH =        display attribute given to character
  169. ;               DI          updated to point to the next word address
  170. ;
  171. ScreenRead      proc    far
  172.                 cmp     cs:SnowFlag,0           ; Snow prevention needed?
  173.                 jz      Read_03                 ; No, don't bother
  174.                 cli                             ; Don't interrupt!
  175. Read_01:
  176.                 in      al,dx                   ; Read video port
  177.                 test    al,1                    ; Test bit zero
  178.                 jnz     Read_01                 ; Wait until it's reset
  179. Read_02:
  180.                 in      al,dx                   ; Read port again
  181.                 test    al,1                    ; Test bit zero
  182.                 jz      Read_02                 ; Wait until it's set
  183. Read_03:
  184.                 lodsw                           ; Get character and attribute
  185.                 sti                             ; You were saying?
  186.                 ret
  187. ScreenRead      endp
  188.  
  189. ;┌────────────────────────────────────────────────────────────────────────┐
  190. ;│      Output a character and attribute to the video display.            │
  191. ;└────────────────────────────────────────────────────────────────────────┘
  192. ;
  193. ;   If the 'snow prevention' flag is set, this routine waits until the
  194. ;   beginning of the next CRT horizontal retrace period before writing
  195. ;   data to the display. This is necessary only on machines fitted with
  196. ;   a Colour Graphics Adaptor (CGA) which may suffer from glitches or
  197. ;   screen snow if data is written to the screen while the video buffer
  198. ;   is being refreshed.
  199. ;
  200. ;   Input:      ES:DI==>    Address in the video display buffer where
  201. ;                           the data is to be written. 
  202. ;               DX =        Port address of CRT status register.
  203. ;               AL =        Character to output.
  204. ;               AH =        Display attribute of character.
  205. ;
  206. ;   Output:     DI          Updated to point to next output address.
  207. ;
  208. ScreenWrite     proc    far  
  209.                 push    bx                      ; Preserve BX
  210.                 cmp     cs:SnowFlag,0           ; Snow prevention needed?
  211.                 cli                             ; Don't interrupt!
  212.                 jz      Write_3                 ; No, don't bother
  213.                 mov     bx,ax                   ; Save byte and attribute  
  214. Write_1:
  215.                 in      al,dx                   ; Read video port
  216.                 test    al,1                    ; Test bit zero
  217.                 jnz     Write_1                 ; Wait until it's reset
  218. Write_2:
  219.                 in      al,dx                   ; Read port again
  220.                 test    al,1                    ; Test bit zero
  221.                 jz      Write_2                 ; Wait until it's set
  222.                 mov    ax,bx                    ; Recover data
  223. Write_3:
  224.                 stosw                           ; Write data to screen
  225.                 sti                             ; Restore interrupts
  226.                 pop     bx                      ; Restore BX
  227.                 ret
  228. ScreenWrite     endp
  229.  
  230. ;┌────────────────────────────────────────────────────────────────────────┐
  231. ;│      Collect information about the current video display.              │
  232. ;└────────────────────────────────────────────────────────────────────────┘
  233. ;
  234. ;   Output:     AL =    Current display mode
  235. ;               AH =    Screen width in columns
  236. ;               BL =    Screen height in rows
  237. ;               BH =    Active display page
  238. ;
  239. ;   The correct video display segment and CRT status port addresses are
  240. ;   determined for the current system and, if necessary, the internal
  241. ;   'snow' prevention flag is set.
  242. ;
  243. VideoType       proc    far
  244.                 push    bp                      ; Preserve these registers
  245.                 push    cx
  246.                 push    dx
  247.                 push    es
  248.                 mov     ah,0Fh                  ; ROM-BIOS Service 16
  249.                 int     10h                     ; - Check video mode
  250.                 cmp     al,7                    ; Monochrome display?
  251.                 je      Type_02                 ; Yes, use defaults
  252.                 mov     cs:VideoRam,0B800h      ; Otherwise set up
  253.                 mov     cs:VideoPort,03DAh      ;    for colour
  254. Type_01:
  255.                 mov     cs:Param1,ax            ; Save display mode and width
  256.                 push    bx                      ; Save active display page
  257.                 xor     bh,bh  
  258.                 mov     dl,24                   ; Default to 25 rows
  259.                 mov     ax,1130h                ; ROM-BIOS Service 16
  260.                 int     10h                     ;  - get font information
  261.                 pop     bx
  262.                 mov     bl,dl                   ; DL = number of rows - 1
  263.                 inc     bl
  264.                 mov     cs:Param2,bx            ; Save video page and height
  265.                 mov     bl,10h                  ; Test for presence
  266.                 mov     ah,12h                  ;    of an EGA or VGA
  267.                 int     10h                     ;      display adaptor
  268.                 cmp     bl,10h                  ; Any response?
  269.                 jne     Type_02                 ; Yes, can't be a CGA
  270.                 mov     cs:SnowFlag,1           ; Set snow prevention flag
  271. Type_02:
  272.                 mov     bx,cs:Param2            ; Recover page and height
  273.                 mov     ax,cs:Param1            ; Recover mode and width
  274.                 pop     es                      ; Clean up the stack
  275.                 pop     dx
  276.                 pop     cx
  277.                 pop     bp
  278.                 ret
  279. VideoType       endp  
  280.  
  281. ;┌────────────────────────────────────────────────────────────────────────┐
  282. ;│      Output a byte of data to video memory.                            │
  283. ;└────────────────────────────────────────────────────────────────────────┘
  284. ;
  285. ;   This procedure is similar to ScreenWrite, above, except that only a
  286. ;   single byte is written. It is used by the BackFill routine to reset
  287. ;   the display attribute of a character, without changing the character
  288. ;   itself.
  289. ;
  290. ;   Input:      ES:DI==>    address, in the video display buffer, where
  291. ;                           the byte is to be written.
  292. ;               DX =        port address of the CRT status register.
  293. ;               AL =        the byte value to be written.
  294. ;
  295. ;   Output:     DI          updated to point to the next byte address
  296. ;
  297. WriteByte       proc    far
  298.                 push    ax                      ; Preserve this register
  299.                 cmp     cs:SnowFlag,0           ; Snow prevention needed?
  300.                 jz      Byte_03                 ; No, don't bother
  301.                 mov     ah,al                   ; Save character to output
  302.                 cli                             ; Don't interrupt!
  303. Byte_01:
  304.                 in      al,dx                   ; Read video port
  305.                 test    al,1                    ; Test bit zero
  306.                 jnz     Byte_01                 ; Wait until it's reset
  307. Byte_02:
  308.                 in      al,dx                   ; Read port again
  309.                 test    al,1                    ; Test bit zero
  310.                 jz      Byte_02                 ; Wait until it's set
  311.                 mov     al,ah                   ; Retrieve character
  312. Byte_03:
  313.                 stosb                           ; Write data to the screen
  314.                 sti                             ; You were saying?
  315.                 pop     ax                      ; Clean up the stack
  316.                 ret
  317. WriteByte       endp
  318.  
  319. ;┌────────────────────────────────────────────────────────────────────────┐
  320. ;│      Calculate display attribute from fore and background colours.     │
  321. ;└────────────────────────────────────────────────────────────────────────┘
  322. ;
  323. Attribute       proc    far
  324.                 push    bp                      ; Save Base pointer
  325.                 mov     bp,sp                   ; Establish stack frame
  326.                 mov     dx,[bp+8]               ; Get foreground colour
  327.                 mov     ax,[bp+6]               ; Get background colour
  328.                 and     ax,000Fh                ; Only 0-15 allowed
  329.                 mov     cl,4                    ; Multiply it
  330.                 shl     ax,cl                   ;    by sixteen
  331.                 mov     dh,dl                   ; Foreground to DH
  332.                 and     dh,10h                  ; Only 0-31 allowed
  333.                 mov     cl,3                    ; Multiply it
  334.                 shl     dh,cl                   ;    by eight
  335.                 or      al,dh                   ; Adjust
  336.                 or      al,dl                   ;    to fit
  337.                 pop     bp                      ; Clean up the stack
  338.                 ret     4                       ; Return to QuickBASIC
  339. Attribute       endp
  340.  
  341. ;┌────────────────────────────────────────────────────────────────────────┐
  342. ;│      Millisecond delay loop.                                           │
  343. ;└────────────────────────────────────────────────────────────────────────┘
  344. ;
  345. ;   The delay interval, in milliseconds, should be passed by value.
  346. ;
  347. Delay           proc    far
  348.                 push    bp                      ; Save Base Pointer
  349.                 mov     bp,sp                   ; Establish stack frame
  350.                 push    ds                      ; Save all registers
  351.                 push    bx
  352.                 push    cx
  353.                 push    dx                
  354.                 mov     cx,[bp+6]               ; Get delay required
  355.                 jcxz    Delay_4                 ; Ignore if zero
  356.                 push    cs                      ; Align code and
  357.                 pop     ds                      ;    data segments
  358.                 mov     ax,Factor               ; Load fudge factor
  359.                 mov     dx,Factor[2]            ;    into DX:AX
  360.                 or      ax,ax                   ; Has fudge been set?
  361.                 jnz     Delay_1                 ; Yes, continue
  362.                 call    Fudge                   ; Otherwise set it
  363. Delay_1:
  364.                 mov     bx,44                   ; Divide by 44 to get
  365.                 div     bx                      ;    loop counter value
  366. Delay_2:
  367.                 mov     Counter,ax              ; Set up for 1 msec delay
  368.                 mov     Counter[2],0            ; High word is not used
  369. Delay_3:
  370.                 sub     Counter,1               ; Decrement count
  371.                 sbb     Counter[2],0
  372.                 jns     Delay_3                 ;    for 1 millisecond
  373.                 loop    Delay_2                 ;      for n milliseconds
  374. Delay_4:
  375.                 pop     dx                      ; Clean up the stack
  376.                 pop     cx
  377.                 pop     bx
  378.                 pop     ds
  379.                 pop     bp
  380.                 ret     2                       ; Return to QuickBASIC
  381. Delay           endp
  382.  
  383. ;┌────────────────────────────────────────────────────────────────────────┐
  384. ;│      Calculate delay fudge factor for host system.                     │
  385. ;└────────────────────────────────────────────────────────────────────────┘
  386. ;
  387. Fudge           proc    near
  388.                 push    es                      ; Save this register
  389.                 xor     ax,ax                   ; Zero AX
  390.                 mov     Factor,ax               ; Initialise
  391.                 mov     Factor[2],ax            ;    local data
  392.                 mov     es,ax                   ; Point ES to page zero
  393.                 mov     al,es:[46Ch]            ; Get current timer count
  394. Fudge_1:
  395.                 cmp     al,es:[46Ch]            ; Has it changed?
  396.                 je      Fudge_1                 ; No, wait till it does
  397.                 mov     al,es:[46Ch]            ; Yes, get new count
  398. Fudge_2:
  399.                 add     Factor,1                ; Increment
  400.                 adc     Factor[2],0             ;    fudge factor
  401.                 cmp     al,es:[46Ch]            ; Has timer changed yet?
  402.                 je      Fudge_2                 ; No, keep incrementing
  403.                 mov     ax,Factor               ; Yes, load fudge
  404.                 mov     dx,Factor[2]            ;    factor and return
  405.                 pop     es                      ; Clean up the stack
  406.                 ret                             ; Return to caller
  407. Fudge           endp
  408.  
  409. ;┌────────────────────────────────────────────────────────────────────────┐
  410. ;│  Clear screen rectangle explosively.                                   │
  411. ;└────────────────────────────────────────────────────────────────────────┘
  412. ;
  413. ;   The panel is cleared, starting at the centre point, and progressively
  414. ;   moving outwards until the defined borders are reached. This gives the
  415. ;   impression of the clear area exploding onto the screen.
  416. ;
  417. Explode         proc    far
  418.                 push    bp                      ; Save Base pointer
  419.                 mov     bp,sp                   ; Establish stack frame
  420.                 push    es                      ; Save Extra Segment,
  421.                 push    ds                      ;    Data segment,
  422.                 push    si                      ;      and index
  423.                 push    di                      ;        pointers
  424.                 call    VideoType               ; Get video parameters
  425.                 push    cs                      ; Align Code and
  426.                 pop     ds                      ;    Data segments
  427.                 mov     al,[bp+16]              ; Get top-left row
  428.                 dec     al                      ; Use ROM-BIOS numbering
  429.                 cmp     al,0                    ; Check for
  430.                 jae     Exp_01                  ;    legal
  431.                 xor     al,al                   ;      values
  432. Exp_01:                
  433.                 mov     [bp+16],al              ; Save it for later
  434.                 mov     al,[bp+14]              ; Get top-left column
  435.                 dec     al                      ; Use ROM-BIOS numbering
  436.                 cmp     al,0                    ; Check for
  437.                 jae     Exp_02                  ;    legal
  438.                 xor     al,al                   ;      values
  439. Exp_02:                
  440.                 mov     [bp+14],al              ; Save it for later
  441.                 mov     al,[bp+12]              ; Get bottom-right row
  442.                 dec     al                      ; Use ROM-BIOS numbering
  443.                 cmp     al,Rows                 ; Check
  444.                 jb      Exp_03                  ;    for
  445.                 mov     al,Rows                 ;      legal
  446.                 dec     al                      ;        values
  447. Exp_03:                
  448.                 mov     [bp+12],al              ; Save it for later
  449.                 mov     al,[bp+10]              ; Get bottom-right column
  450.                 dec     al                      ; Use ROM-BIOS numbering
  451.                 cmp     al,Columns              ; Check
  452.                 jb      Exp_04                  ;    for
  453.                 mov     al,Columns              ;      legal
  454.                 dec     al                      ;        values 
  455. Exp_04:                
  456.                 mov     [bp+10],al              ; Save it for later
  457.                 mov     al,[bp+16]              ; Get top-left row
  458.                 cmp     al,[bp+12]              ; Below bottom-right?
  459.                 jb      Exp_05                  ; If so, proceed
  460.                 jmp     Exp_15                  ; If not, abort
  461. Exp_05:
  462.                 add     al,[bp+12]              ; Add bottom-right row
  463.                 shr     al,1                    ; Divide by two
  464.                 mov     V1,al                   ; Store the result
  465.                 mov     V2,al                   ;    twice
  466.                 mov     al,[bp+14]              ; Get top-left column
  467.                 cmp     al,[bp+10]              ; Left of right-hand edge?
  468.                 jb      Exp_06                  ; If so, proceed
  469.                 jmp     Exp_15                  ; If not, abort
  470. Exp_06:
  471.                 add     al,[bp+10]              ; Add bottom-right column
  472.                 shr     al,1                    ; Divide by two
  473.                 mov     H1,al                   ; Store the result
  474.                 mov     H2,al                   ;    twice
  475.                 mov     ax,[bp+6]               ; Get delay value
  476.                 cmp     ax,1                    ; Check for
  477.                 jge     Exp_07                  ;    legal
  478.                 mov     ax,1                    ;      values
  479. Exp_07:
  480.                 mov     [bp+6],ax               ; Save it for later
  481.                 mov     bh,[bp+8]               ; Get display attribute
  482. Exp_08:
  483.                 mov     al,[bp+16]              ; Check top-left row
  484.                 cmp     al,V1                   ; Reached it yet?
  485.                 jae     Exp_09                  ; If not bump
  486.                 dec     V1                      ;    the counter
  487. Exp_09:
  488.                 mov     al,[bp+12]              ; Check bottom-right row
  489.                 cmp     al,V2                   ; Reached it yet?
  490.                 jbe     Exp_10                  ; If not bump
  491.                 inc     V2                      ;    the counter
  492. Exp_10:
  493.                 mov     al,[bp+14]              ; Check top-left column
  494.                 mov     cx,3                    ; Iteration count
  495. Exp_11:
  496.                 cmp     al,H1                   ; Reached it yet?
  497.                 jae     Exp_12                  ; If not bump
  498.                 dec     H1                      ;    the counter
  499.                 loop    Exp_11                  ; Up to three times
  500. Exp_12:
  501.                 mov     al,[bp+10]              ; Check bottom-right column
  502.                 mov     cx,3                    ; Iteration count
  503. Exp_13:                
  504.                 cmp     al,H2                   ; Reached it yet?
  505.                 jbe     Exp_14                  ; If not bump
  506.                 inc     H2                      ;    the counter
  507.                 loop    Exp_13                  ; Up to three times
  508. Exp_14:
  509.                 mov     dx,BotRight             ; Get lower right co-ordinate
  510.                 mov     cx,TopLeft              ; Get upper left co-ordinate
  511.                 mov     ax,0700h                ; BIOS display service 7
  512.                 int     10h                     ;  - scroll down window
  513.                 push    [bp+6]                  ; Get delay count
  514.                 call    Delay                   ; Pause awhile
  515.                 mov     al,[bp+16]              ; Get top-left row
  516.                 cmp     al,V1                   ; Reached it?
  517.                 jb      Exp_08                  ; No, do it again
  518.                 mov     al,[bp+14]              ; Get top-left column
  519.                 cmp     al,H1                   ; Reached it?
  520.                 jb      Exp_08                  ; No, do it again
  521.                 mov     al,[bp+12]              ; Get bottom-right row
  522.                 cmp     al,V2                   ; Reached it?
  523.                 ja      Exp_08                  ; No, do it again
  524.                 mov     al,[bp+10]              ; Get bottom-right column
  525.                 cmp     al,H2                   ; Reached it?
  526.                 ja      Exp_08                  ; No, do it again
  527. Exp_15:
  528.                 pop     di                      ; Clean up the stack
  529.                 pop     si
  530.                 pop     ds
  531.                 pop     es
  532.                 pop     bp
  533.                 ret     12                      ; Return to QuickBASIC
  534. Explode         endp
  535.  
  536. ;┌────────────────────────────────────────────────────────────────────────┐
  537. ;│  Fast screen printing.                                                 │
  538. ;└────────────────────────────────────────────────────────────────────────┘
  539. ;
  540. ;   This procedure outputs text directly to the video display without
  541. ;   going through DOS or ROM-BIOS services.
  542. ;
  543. FastPrint       proc    far
  544.                 push    bp                      ; Save Base pointer
  545.                 mov     bp,sp                   ; Establish stack frame
  546.                 push    es                      ; Save Extra Segment,
  547.                 push    ds                      ;    Data segment,
  548.                 push    si                      ;      and index
  549.                 push    di                      ;        pointers
  550.                 call    VideoType               ; Get video parameters
  551.                 mov     dh,ah                   ; Load screen dimensions
  552.                 mov     dl,bl                   ;    into DX
  553.                 mov     ax,[bp+12]              ; Get row number
  554.                 dec     al                      ; Convert to base zero
  555.                 cmp     al,0                    ; Top screen row?
  556.                 jae     Fast_01                 ; Jump if not below
  557.                 xor     al,al                   ; Don't go over the top!
  558. Fast_01:
  559.                 cmp     al,dl                   ; Bottom row?
  560.                 jb      Fast_02                 ; Go no further
  561.                 mov     al,dl
  562.                 dec     al
  563. Fast_02:
  564.                 mov     bx,[bp+10]              ; Get column number
  565.                 mov     ah,bl                   ;    into AH
  566.                 dec     ah                      ; Convert to base zero
  567.                 cmp     ah,0                    ; Leftmost column?
  568.                 jae     Fast_03                 ; Jump if not below
  569.                 xor     ah,ah                   ; Don't go off the screen
  570. Fast_03:
  571.                 cmp     ah,dh                   ; Rightmost column?
  572.                 jb      Fast_04                 ; Go no further
  573.                 mov     ah,dh                   ; Don't go off the screen
  574.                 dec     ah                      ; Base zero, remember?
  575. Fast_04:
  576.                 push    ax                      ; Save display co-ordinates
  577.                 mov     ax,[bp+8]               ; Index to string descriptor
  578.                 push    ax                      ; Call BASIC for
  579.                 call    StringAddress           ;    string parameters
  580.                 pop     bx                      ; Recover co-ordinates
  581.                 jcxz    Fast_06                 ; Abort if a null string
  582.                 mov     ds,dx                   ; String segment to DS
  583.                 mov     si,ax                   ; DS:SI==> string data
  584.                 mov     ax,bx                   ; Co-ordinates to AX
  585.                 call    ScreenAddress           ; Calculate target address
  586.                 mov     ax,[bp+6]               ; Get display attribute
  587.                 xchg    ah,al                   ;    into AH
  588.                 cld                             ; Clear direction flag
  589. Fast_05:
  590.                 lodsb                           ; Get a byte from the string
  591.                 call    ScreenWrite             ; Write byte and attribute
  592.                 loop    Fast_05                 ; For length of string
  593.                 xor     ax,ax                   ; Report success        
  594. Fast_06:
  595.                 pop     di                      ; Clean up the stack
  596.                 pop     si
  597.                 pop     ds
  598.                 pop     es
  599.                 pop     bp
  600.                 ret     8                       ; Return to QuickBASIC
  601. FastPrint       endp
  602.  
  603.                 end
  604.  
  605. ;┌────────────────────────────────────────────────────────────────────────┐
  606. ;│      (c) 1988,1991  By Christy Gemmell and Singular SoftWare.          │
  607. ;└────────────────────────────────────────────────────────────────────────┘
  608.