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