page ,132
title QPRINT - 8088 routine CALLed from BASIC   Dan Rollins Byte 7/83 p408

comment * This routine prints a string to the video display at
          10 times the speed of BASIC. Works for color or
          monochrome in 80 or 40 column TEXT modes (no graphics)
          Characters are displayed with the existing color,
          blink, and underline attributes.

Called from BASIC via:

  CALL QPRINT(VAR$,ROW%,CLM%)

Where:

  CLM% is an integer variable name (1-80)
  ROW% is an integer variable name (1-25)
  VAR$ is a string variable name.

  VAR$ is displayed beginning at position CLM% of line
       ROW%. If too long, it will wrap around to
       the next line.

note: Color card pages 1-7 may be accesed by setting
      ROW% above 25.
*
bios_data  segment at 40h       ;set up labels to determine
           org     10h          ; color or mono card
equip_flag label   word
           org     4ah          ; 40 or 80 column display
crt_clms   label   word
           org     63h
addr_6845  label   word         ; points to video card ports
bios_data ends

cseg    segment
        assume CS:cseg, DS:nothing, ES:nothing
;
;Define the file header so that the BASIC
;BLOAD file loader will know what to do.
; ------these bytes not executed--------
;
 header:
        db      0fdh            ;indicate BLOAD file
        dw      0               ;segment--BASIC will use default
        dw      0               ;offset--specify in BLOAD command
        dw      rtn_len         ;length of the subroutine
        page
 qprint proc     far
        push    es              ;must save for BASIC
        mov     bp,sp           ;point to arguments on stack

        mov     bx,[bp+6]       ;set addr of CLM% storage
        mov     di,[bx]         ; set the column value
        dec     di              ; adjust for the LOCATE format

        mov     bx,[bp+8]       ;set address of ROW% storage
        mov     ax,[bx]         ; set the screen line value
        dec     ax              ; adjust for LOCATE format

        mov     bx,[bp+10]      ;set ptr to string descriptor
        xor     ch,ch           ; zero the high byte
        mov     cl,[bx]         ;set length of string
        cmp     cl,0            ;null string
        je      exit            ; if so, do nothing, Else,
        mov     si,[bx+1]       ; SI => 1st character of VAR$
;
        mov     bx,bios_data    ;set ready to determine card type
        mov     es,bx           ; and number of columns

        mul     es:crt_clms     ;AX = CLM% * words per line
        add     di,ax           ;DI = words from start of screen
        shl     di,1            ; adjust for attribute bytes

        mov     dx,es:addr_6845 ;point to 6845 base port
        add     dx,6            ;point to status port

; CX has the count of characters to write,
; SI (Source Index) points to the string data,
; DI (Destination Index) points to a screen position,
        mov     ax,0b800h       ;default to color card
        mov     bx,es:equip_flag
        and     bx,30h
        cmp     bx,30h          ;is it monochrome?
        jne     card_ok         ; no, so
        mov     ax,0b000h       ; yes, set for monochrome
card_ok:
        mov     es,ax           ; point ES to video

; DS (Data Segment) points to BASIC variables area
; ES (Extra Segment) points to video card memory
; Now display VAR$ on the screen.

        call    print_string
exit:
        pop     es              ;restore segment register
        ret     6               ;intersegment return,
                                ; clearing stack of 3 args
qprint  endp
        page
;this procedure displays a string of characters
;expects:
;       DS:SI => first character of the string
;       ES:DI => screen memory to display it
;       CX    =  number of characters to display
;       DX    => status port of video card

print_string    proc    near

;------------wait for horizontal retrace
test_low:
        in      al,dx           ;get status
        test    al,1            ; is it low?
        jnz     test_low        ; no, keep checking
        cli                     ;turn off interrupts
test_hi:
        in      al,dx           ;get status
        test    al,1            ; is it high?
        jz      test_hi         ; no, keep checking
;-----------okay to write to screen now (no 'hash')

        movsb                   ;[DS:SI] -> [ES:DI], DI++, SI++, CX--

        inc     di              ;skip the attribute byte
        loop    test_low        ;do till end of string

        sti                     ;turn interrupts back on
        ret                     ;back to qprint proc
print_string endp

rtn_len equ     $ - qprint      ;define length for BLOAD header
cseg    ends
        end     header          ;needed for .BIN file conversion
