home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / CTASK22.ZIP / TSKPRF.ASM < prev    next >
Assembly Source File  |  1990-10-12  |  30KB  |  1,659 lines

  1. ;
  2. ;    --- Version 2.2 90-10-12 10:38 ---
  3. ;
  4. ;    CTask - Printf replacement
  5. ;
  6. ;    Public Domain Software written by
  7. ;        Thomas Wagner
  8. ;        Ferrari electronic Gmbh
  9. ;        Beusselstrasse 27
  10. ;        D-1000 Berlin 21
  11. ;        Germany
  12. ;
  13. ;    This file is new with Version 2.1. 
  14. ;
  15. ;    This module contains substitutes for the standard C printf
  16. ;    family formatting routines. It uses no helper routines, and
  17. ;    thus can be called from Assembler programs and is model
  18. ;    independent. It is smaller and faster (up to 5 times) than
  19. ;    the standard C printf, and supports all output options except 
  20. ;    floating point and some esoteric flags. 
  21. ;
  22. ;    Also supported is output to the second monitor in a dual-
  23. ;    monitor system.
  24. ;
  25. ;    The routines in this module are reentrant in the sense that nothing
  26. ;    will crash if routines are re-entered concurrently. No protection
  27. ;    against a garbled screen is built in, however, so external
  28. ;    resource request/release calls are still necessary to make
  29. ;    sure output to the display stays in proper order. The sprintf
  30. ;    routines need no protection.
  31. ;
  32. ;    No CTask specific stuff is used to allow use of the routines
  33. ;    even when CTask is not installed.
  34. ;
  35. ;    Note that the tsk_fprintf routine takes a different parameter
  36. ;    than the standard fprintf. You have to pass an integer file 
  37. ;    handle, not a FILE *.
  38. ;
  39. ;---------------------------------------------------------------------------
  40. ;
  41. ;    Conversion format:
  42. ;
  43. ;        % [flags] [width] [.precision] [indirection] [size] conversion
  44. ;
  45. ;    Flags supported:
  46. ;
  47. ;        -    Left-justify output
  48. ;
  49. ;        the +, blank, and # flags are not supported.
  50. ;
  51. ;    Width and precision are handled like in standard C, i.e.
  52. ;    the * specification is supported. The only exception is
  53. ;    that numeric output will not be suppressed for an explicit
  54. ;    0 precision.
  55. ;
  56. ;    Size modifiers supported:
  57. ;
  58. ;        N    Near pointer
  59. ;        F    Far pointer
  60. ;        h    Short
  61. ;        l    Long
  62. ;
  63. ;    Conversion characters supported:
  64. ;
  65. ;        c    single character
  66. ;        s    zero-terminated string
  67. ;        x    unsigned hex word, a-f
  68. ;        X    unsigned hex word, A-F
  69. ;        d    signed decimal int
  70. ;        u    unsigned decimal int
  71. ;        p    hex pointer, a-f
  72. ;        P    hex pointer, A-F
  73. ;        n    store converted length at int pointer
  74. ;
  75. ;    In addition, two indirection operators are supported. Both
  76. ;    can be repeated, but they should not normally be mixed.
  77. ;
  78. ;        ^    Near indirection (param is DS-based near pointer)
  79. ;        @    Far indirection (param is far pointer)
  80. ;
  81. ;    Example:
  82. ;        %d    Displays the word parameter
  83. ;        %^d    Displays the word at DS:parameter
  84. ;        %@d    Displays the word at the far address 
  85. ;            given as parameter
  86. ;
  87. ;---------------------------------------------------------------------------
  88. ;
  89.     name    tskprf
  90. ;
  91.     include    tsk.mac
  92. ;
  93.     .tsk_model
  94. ;
  95.     public    tsk_regen        ; far pointer to regen buffer
  96.     public    tsk_regen_s        ; regen buffer segment
  97.     public    tsk_regen_o        ; current regen buffer offset
  98.     public    tsk_disport        ; display controller I/O port
  99. ;
  100.     Pubfunc    tsk_putc        ; put char to screen
  101.     Pubfunc    tsk_puts        ; put string to screen
  102.     Pubfunc    tsk_rputc        ; put char to regen
  103.     Pubfunc    tsk_rputs        ; put string to regen
  104. ;
  105.     CPubfnc    tsk_printf        ; print to screen
  106.     Pubfunc    tsk_vprintf        ; print to screen with arg pointer
  107.     CPubfnc    tsk_fprintf        ; print to file handle
  108.     Pubfunc    tsk_vfprintf        ; print to file handle w. argptr
  109.     CPubfnc    tsk_sprintf        ; print to string
  110.     Pubfunc    tsk_vsprintf        ; print to string w. argptr
  111.     CPubfnc    tsk_rprintf        ; print to regen
  112.     Pubfunc    tsk_vrprintf        ; print to regen w. argptr
  113. ;
  114.     Pubfunc    tsk_setpos        ; set regen cursor position
  115.     Pubfunc    tsk_set_regen        ; set regen address
  116.     Pubfunc    tsk_set_dualdis        ; init secondary monitor
  117.     Pubfunc    tsk_set_currdis        ; init primary monitor
  118.     Pubfunc    tsk_set_colour        ; init colour monitor
  119.     Pubfunc    tsk_set_mono        ; init mono monitor
  120.     Pubfunc    tsk_set_attr        ; set display attribute
  121.     Pubfunc    tsk_set_clreol        ; CR clears to EOL when set
  122. ;
  123. ;
  124. ; Configuration options:
  125. ;
  126. ; FILE_BUFSIZE    Is the local buffer size for tsk_fprintf and tsk_vfprintf.
  127. ;        The buffer is allocated on the stack, so it should
  128. ;        not be chosen too large to avoid stack overflows.
  129. ;        It must be a power of 2, and less than or equal to 256.
  130. ;
  131. FILE_BUFSIZE    =    64 - 1
  132. ;
  133. ;
  134. ; DFLT_FAR    If set, pointers (%p and %n) and strings (%s) are assumed
  135. ;        far by default, near pointers must use the N size
  136. ;        modifiers.
  137. ;        If clear, the default is near, so the F size modifier
  138. ;        must be used for far pointers.
  139. ;
  140. DFLT_FAR    =    1    ; by default, pointers and strings are Far
  141. ;
  142. ;
  143. ;    The local variables used in the main formatter.
  144. ;    Those variables are relative to BP, and are accessed by
  145. ;    several routines in this module (the local routines do not
  146. ;    use the standard stack discipline, they should be viewed as
  147. ;    Pascal-like nested routines within the scope of @disprintf).
  148. ;
  149. dislocrec    struc
  150. convbuf    db    11 dup(?)    ; conversion buffer (hex/dec)
  151. prflags    db    ?        ; formatting flags
  152. prhexch    db    ?        ; Hex format offset for upper/lower case
  153. prfcnt    db    ?        ; file output counter
  154. procnt    dw    ?        ; output char counter
  155. prwidth    dw    ?        ; field width
  156. prec    dw    ?        ; precision
  157. arglen    dw    ?        ; argument length in bytes
  158. prproc    dw    ?        ; output routine offset
  159. prargbx    dw    ?        ; output routine BX argument
  160. prargdx    dw    ?        ; output routine DX argument
  161. dislocrec    ends
  162. ;
  163. ;    formatting flags
  164. ;
  165. F_LONGARG    =    01h    ; argument is long/far (4 bytes)
  166. F_SHORTARG    =    02h    ; argument is single byte
  167. F_PADZERO    =    04h    ; pad with zeros
  168. F_LEFTADJ    =    08h    ; left adjust output
  169. F_SIGNED    =    10h    ; signed number
  170. F_WIDTH        =    20h    ; width is valid
  171. F_PREC        =    40h    ; precision is valid
  172. F_INDIR        =    80h    ; indirection was used
  173. ;
  174. biosdata    segment at 40h
  175.         org    4ah
  176. bios_cols    dw    ?
  177.         org    63h
  178. bios_chipad    dw    ?
  179.         org    84h
  180. bios_rows    db    ?
  181. biosdata    ends
  182. ;
  183.     .tsk_data
  184. ;
  185. tsk_regen    label    dword
  186. tsk_regen_o    dw    0
  187. tsk_regen_s    dw    0b000h        ; default mono screen
  188. ;
  189. tsk_disport    dw    3b4h        ; default mono 6845
  190. tsk_attrib    db    07h        ; default white on black
  191. ;
  192. sc_clreol    db    0        ; default is don't clear
  193. ;
  194. sc_cols    dw    80 * 2
  195. sc_end    dw    25 * 80 * 2
  196. ;
  197. sc_proc    dw    offset @nodis
  198. ;
  199.     .tsk_edata
  200.     .tsk_code
  201. ;
  202. ctdataseg    dw    @CTASK_DATA
  203. ;
  204. ;    setcsr - local routine to set the cursor to the current position
  205. ;         on the regen display.
  206. ;
  207. @setcsr    proc    near
  208. ;
  209.     push    dx
  210.     mov    dx,tsk_disport
  211.     or    dx,dx
  212.     jz    no_cursor
  213.     mov    al,0eh
  214.     out    dx,al
  215.     jmp    $+2
  216.     mov    ax,tsk_regen_o
  217.     shr    ax,1
  218.     xchg    ah,al
  219.     inc    dx
  220.     out    dx,al
  221.     jmp    $+2
  222.     dec    dx
  223.     mov    al,0fh
  224.     out    dx,al
  225.     jmp    $+2
  226.     mov    al,ah
  227.     inc    dx
  228.     out    dx,al
  229. ;
  230. no_cursor:
  231.     pop    dx
  232.     ret
  233. ;
  234. @setcsr    endp
  235. ;
  236. ;
  237. ; disregen - local routine to write char directly into the display 
  238. ;    regen buffer. The following control characters 
  239. ;    are handled special:
  240. ;        08 \b (BS)      backspace one position (no erase)
  241. ;        09 \t (TAB)    tab to next 8th column
  242. ;        0D \r (CR)    carriage return
  243. ;        0A \n (LF)    line feed
  244. ;                Note: the printf routines will not pass
  245. ;                a single line feed unchanged.
  246. ;        0B \v (VT)    clear to end of line
  247. ;        0C \f (FF)    clear to end of screen
  248. ;
  249. ;
  250. ;    Entry:    AL = char to display
  251. ;    Uses:    AX
  252. ;
  253. @disregen    proc    near
  254. ;
  255.     push    ds
  256.     mov    ds,cs:ctdataseg        ; allow access to local vars
  257. ;
  258. ;    First, check for control characters
  259. ;
  260.     cmp    al,0eh            ; 08-0D are special
  261.     jae    no_special
  262.     cmp    al,08h
  263.     jb    no_special
  264.     je    dis_bs            ; 08 = Backspace
  265.     cmp    al,0ah
  266.     jb    dis_tab            ; 09 = Tab
  267.     je    dis_lf            ; 0A = Linefeed
  268.     cmp    al,0ch
  269.     jb    dis_vt            ; 0B = Clear to eol
  270.     jne    dis_cr            ; 0D = Carriage return
  271.     jmp    dis_ff            ; 0C = Clear screen
  272. ;
  273. ;    Carriage return
  274. ;
  275. dis_cr:
  276.     cmp    sc_clreol,0
  277.     jne    dis_vt
  278. discr1:
  279.     push    dx
  280.     cli
  281.     mov    ax,tsk_regen_o        ; current offset
  282.     xor    dx,dx            ; make into doubleword
  283.     div    sc_cols            ; divide by number of columns
  284.     sub    tsk_regen_o,dx        ; subtract remainder
  285.     sti
  286.     pop    dx
  287.     jmp    disreg_end
  288. ;
  289. no_special:
  290.     jmp    disregen_ok
  291. ;
  292. ;    Backspace
  293. ;
  294. dis_bs:
  295.     cli
  296.     cmp    tsk_regen_o,0        ; Handle wraparound
  297.     je    dis_bs2
  298.     sub    tsk_regen_o,2
  299.     sti
  300.     jmp    disreg_end
  301. dis_bs2:
  302.     mov    ax,sc_end        ; Wrap to end of screen
  303.     sub    ax,2
  304.     mov    tsk_regen_o,ax
  305.     sti
  306.     jmp    disreg_end
  307. ;
  308. ;    Tab
  309. ;
  310. dis_tab:
  311.     cli
  312.     mov    ax,tsk_regen_o
  313.     add    ax,16
  314.     and    ax,0fff0h        ; Tabs every 8 cols
  315.     mov    tsk_regen_o,ax
  316.     sti
  317.     jmp    disreg_end
  318. ;
  319. ;    Linefeed
  320. ;
  321. dis_lf:
  322.     cli
  323.     mov    ax,tsk_regen_o
  324.     add    ax,sc_cols        ; Add one line
  325.     mov    tsk_regen_o,ax
  326.     sti
  327.     cmp    ax,sc_end        ; did we get past the end?
  328.     jae    dislf_sc
  329.     jmp    disreg_end
  330. ;
  331. dislf_sc:
  332.     push    es            ; then setup regs and go scroll
  333.     push    di
  334.     mov    es,tsk_regen_s
  335.     mov    di,ax
  336.     jmp    short disreg_scroll
  337. ;
  338. ;    Vertical tab (clear to end of line)
  339. ;
  340. dis_vt:
  341.     push    es
  342.     push    di
  343.     push    cx
  344.     push    ax
  345.     les    di,tsk_regen
  346.     mov    cx,sc_cols        ; number of columns
  347.     mov    ax,di            ; current offset
  348.     xor    dx,dx            ; make into doubleword
  349.     div    cx            ; divide by number of columns
  350.     sub    cx,dx            ; subtract remainder
  351.     shr    cx,1            ; number of words
  352.     mov    ah,tsk_attrib
  353.     mov    al,' '
  354.     rep stosw
  355.     pop    ax
  356.     pop    cx
  357.     cmp    al,0dh
  358.     jne    disreg_ok
  359.     pop    di
  360.     pop    es
  361.     jmp    discr1
  362. ;
  363. ;    Formfeed (clear to end of screen)
  364. ;
  365. dis_ff:
  366.     push    es
  367.     push    di
  368.     push    cx
  369.     les    di,tsk_regen
  370.     mov    cx,sc_end        ; total number of chars
  371.     sub    cx,di            ; minus current offset
  372.     shr    cx,1            ; number of words
  373.     mov    ah,tsk_attrib
  374.     mov    al,' '
  375.     rep stosw
  376.     pop    cx
  377.     jmp    short disreg_ok
  378. ;
  379. ;    Normal character output
  380. ;
  381. disregen_ok:
  382.     push    es
  383.     push    di
  384.     cli
  385.     les    di,tsk_regen        ; load current regen buffer addr
  386.     mov    ah,tsk_attrib
  387.     stosw
  388.     mov    tsk_regen_o,di        ; new offset
  389.     sti
  390.     cmp    di,sc_end        ; past the end?
  391.     jb    disreg_ok
  392. ;
  393. ;    Scroll up one line
  394. ;
  395. disreg_scroll:
  396.     sub    di,sc_cols        ; one line up
  397.     mov    tsk_regen_o,di
  398.     push    cx
  399.     push    si
  400.     push    ds
  401.     mov    si,sc_cols        ; second line
  402.     mov    cx,sc_end
  403.     sub    cx,si            ; screen len minus one line
  404.     shr    cx,1            ; no. of words
  405.     mov    di,es
  406.     mov    ds,di
  407.     mov    di,0            ; first line
  408.     rep movsw
  409.     pop    ds
  410. ;
  411.     mov    cx,sc_cols        ; number of columns
  412.     shr    cx,1            ; number of words
  413.     mov    ah,tsk_attrib
  414.     mov    al,' '
  415.     rep stosw
  416. ;
  417.     pop    si
  418.     pop    cx
  419. ;
  420. disreg_ok:
  421.     pop    di
  422.     pop    es
  423. ;
  424. disreg_end:
  425.     call    @setcsr
  426.     pop    ds
  427.     ret
  428. ;
  429. @disregen    endp
  430. ;
  431. ;
  432. ; nodis - local dummy output routine.
  433. ;    This routine is called if the regen buffer adddress has not
  434. ;    been set, or if there is no secondary monitor.
  435. ;
  436. @nodis    proc    near
  437.     ret
  438. @nodis    endp
  439. ;
  440. ;
  441. ; dischar - local screen output routine.
  442. ;    This routine uses INT 10 TTY output to display the character.
  443. ;    Entry:    AL = char to display
  444. ;    Uses:    AX
  445. ;
  446. @dischar    proc    near
  447.     IF    IBM
  448.     push    bx
  449.     push    bp
  450.         mov    bl,7
  451.         mov     ah,14
  452.     int    10h
  453.     pop    bp
  454.     pop    bx
  455.     ELSE
  456.     push    dx
  457.     mov    dl,al
  458.     mov    ah,2
  459.     int    21h
  460.     pop    dx
  461.     ENDIF
  462.     ret
  463. @dischar    endp
  464. ;
  465. ;
  466. ; filechar - local file output routine.
  467. ;    Write character to file
  468. ;    Entry:    AL = char to display
  469. ;    Uses:    AX
  470. ;
  471. @filechar    proc    near
  472.     push    bx
  473.     push    si
  474.     mov    si,prargdx[bp]
  475.     mov    bl,ss:[si]
  476.     xor    bh,bh
  477.     inc    bx
  478.     mov    ss:[si+bx],al
  479.     cmp    bx,FILE_BUFSIZE - 1
  480.     jb    fcharend
  481.     xchg    si,dx
  482.     inc    dx
  483.     push    ds
  484.     push    ax
  485.     push    cx
  486.     mov    cx,bx
  487.     mov    bx,prargbx[bp]
  488.     mov    ax,ss
  489.     mov    ds,ax
  490.     mov    ah,40h
  491.     int    21h
  492.     pop    cx
  493.     pop    ax
  494.     pop    ds
  495.     xchg    dx,si
  496.     dec    si
  497.     xor    bl,bl
  498. fcharend:
  499.     mov    ss:[si],bl
  500.     pop    si
  501.     pop    bx
  502.     ret
  503. @filechar    endp
  504. ;
  505. ;
  506. ; stringchar - local string output routine.
  507. ;    Entry:    AL = char to write to string
  508. ;        prargbx/dx set to point to destination
  509. ;
  510. ;    Uses:    AX
  511. ;
  512. @stringchar        proc    near
  513.     push    di
  514.     push    es
  515.     les    di,dword ptr prargbx[bp]
  516.     stosb
  517.     mov    prargbx[bp],di
  518.     pop    es
  519.     pop    di
  520.     ret
  521. @stringchar        endp
  522. ;
  523. ;
  524. ; hexdigbp - put hex digit in AL to SS:DI, increment DI and BL.
  525. ;
  526. @hexdigbp    proc    near
  527. ;
  528.     push    ax
  529.         and    al,0fh
  530.     add    al,'0'
  531.         cmp    al,'9'
  532.         jbe    hexbp1
  533.         add    al,prhexch[bp]
  534. hexbp1:
  535.     mov    byte ptr ss:[di],al
  536.     inc    di
  537.     inc    bl
  538.     pop    ax
  539.     ret
  540. ;
  541. @hexdigbp    endp
  542. ;
  543. ;
  544. ;    hexconv - convert hex
  545. ;    Entry:    DX,AX = number
  546. ;        SS:DI = Buffer pointer
  547. ;    Exit:    BX    = converted length
  548. ;        SS:DI = string start + 1
  549. ;    Uses:    CX
  550. ;
  551. @hexconv    proc    near
  552.     xor    bl,bl
  553.     mov    cl,4
  554.     mov    bh,4
  555.     or    dx,dx
  556.     jnz    hchiword
  557. ;
  558. hclp1:
  559.     call    @hexdigbp
  560.     shr    ax,cl
  561.     jz    hcend
  562.     dec    bh
  563.     jnz    hclp1
  564. ;
  565. hcend:
  566.     xor    bh,bh
  567.     ret
  568. ;
  569. hchiword:
  570.     call    @hexdigbp
  571.     shr    ax,cl
  572.     dec    bh
  573.     jnz    hchiword
  574.     mov    ax,dx
  575.     jmp    hclp1
  576. ;
  577. @hexconv    endp
  578. ;
  579. ;
  580. ;    decconv - convert decimal
  581. ;
  582. ;    Entry:    DX,AX = number
  583. ;        SS:DI = Buffer top pointer
  584. ;    Exit:    BX    = converted length
  585. ;        SS:DI = string start + 1
  586. ;    Uses:    CX
  587. ;
  588. @decconv    proc    near
  589.     xor    bx,bx
  590.     mov    cx,10
  591.     or    dx,dx
  592.     jnz    dchiword
  593. ;
  594. dclp1:
  595.     xor    dx,dx
  596.     div    cx
  597.     add    dl,'0'
  598.     mov    byte ptr ss:[di],dl
  599.     inc    di
  600.     inc    bx
  601.     or    ax,ax
  602.     jnz    dclp1
  603.     ret
  604. ;
  605. dchiword:
  606.     push    si
  607.     mov    si,dx
  608. ;
  609. dchilp:
  610.     xchg    ax,si
  611.     xor    dx,dx
  612.     div    cx
  613.     xchg    ax,si
  614.     div    cx
  615.     add    dl,'0'
  616.     mov    byte ptr ss:[di],dl
  617.     inc    di
  618.     inc    bx
  619.     or    si,si
  620.     jnz    dchilp
  621. ;
  622.     pop    si
  623.     jmp    dclp1
  624. ;
  625. @decconv    endp
  626. ;
  627. ;
  628. ; getint - read integer at DS:SI
  629. ;    Entry: AL = first char
  630. ;    Exit:  AX = integer
  631. ;    Uses:  BX,DX
  632. ;
  633. @getint    proc    near
  634. ;
  635.     and    ax,0fh
  636.     mov    bl,10
  637. getintlp:
  638.     xchg    ax,dx
  639.     lodsb
  640.     cmp    al,'0'
  641.     jb    getint_end
  642.     cmp    al,'9'
  643.     ja    getint_end
  644.     and    ax,0fh
  645.     xchg    ax,dx
  646.     mul    bl
  647.     add    ax,dx
  648.     jmp    getintlp
  649. ;
  650. getint_end:
  651.     dec    si
  652.     mov    ax,dx
  653.     ret
  654. ;
  655. @getint    endp
  656. ;
  657. ;
  658. ;    padleft - local routine to pad output on the left side.
  659. ;
  660. @padleft    proc    near
  661. ;
  662.     push    cx
  663.     push    dx
  664.     xor    dx,dx
  665.     test    prflags[bp],F_PREC
  666.     jz    padleft_noprec
  667.     cmp    bx,prec[bp]
  668.     jae    padleft_noprec
  669. ;
  670.     mov    dx,prec[bp]
  671.     sub    dx,bx
  672.     test    prflags[bp],F_WIDTH
  673.     jz    padleft_noprec
  674.     sub    prwidth[bp],dx
  675.     jnc    padleft_noprec
  676.     and    prflags[bp],NOT F_WIDTH
  677. ;
  678. padleft_noprec:
  679.     test    prflags[bp],F_LEFTADJ
  680.     jnz    padleft_end
  681.     test    prflags[bp],F_WIDTH
  682.     jz    padleft_end
  683.     cmp    bx,prwidth[bp]
  684.     jae    padleft_end
  685. ;
  686.     mov    cx,prwidth[bp]
  687.     sub    cx,bx
  688.     add    procnt[bp],cx
  689.     mov    al,' '
  690.     test    prflags[bp],F_PADZERO
  691.     jz    padleftlp
  692.     mov    al,'0'
  693. ;
  694. padleftlp:
  695.     push    ax
  696.     call    prproc[bp]
  697.     pop    ax
  698.     loop    padleftlp
  699. ;
  700. padleft_end:
  701.     mov    cx,dx
  702.     jcxz    padleft_exit
  703.     add    procnt[bp],cx
  704. ;
  705. padleftprec:
  706.     mov    al,'0'
  707.     call    prproc[bp]
  708.     loop    padleftprec
  709. ;
  710. padleft_exit:
  711.     pop    dx
  712.     pop    cx
  713.     ret
  714. ;
  715. @padleft    endp
  716. ;
  717. ;    padright - local routine to pad output on the right side
  718. ;
  719. @padright    proc    near
  720. ;
  721.     test    prflags[bp],F_LEFTADJ
  722.     jz    padright_end
  723.     test    prflags[bp],F_WIDTH
  724.     jz    padright_end
  725.     cmp    bx,prwidth[bp]
  726.     jae    padright_end
  727. ;
  728.     push    cx
  729.     mov    cx,prwidth[bp]
  730.     sub    cx,bx
  731.     add    procnt[bp],cx
  732. ;
  733. padrightlp:
  734.     mov    al,' '
  735.     call    prproc[bp]
  736.     loop    padrightlp
  737.     pop    cx
  738. ;
  739. padright_end:
  740.     ret
  741. ;
  742. @padright    endp
  743. ;
  744. ;
  745. ; disprintf: display formatted string.
  746. ;
  747. ;     Entry:    DS:SI = format string
  748. ;         ES:DI = parameter pointer
  749. ;        CX    = output routine address
  750. ;        BX,DX = output routine parameter
  751. ;
  752. ;    Uses:    AX,BX,DX
  753. ;
  754. ;    Usually, the parameter pointer will point to the first
  755. ;    parameter on the stack. For added flexibility, ES:DI is
  756. ;    used here, so that the parameter list may be anywhere in
  757. ;    memory. This allows vprintf-style parameters.
  758. ;
  759. ;
  760. @disprintf    proc    near
  761.     push    bp
  762.     sub    sp,TYPE dislocrec
  763.     mov    bp,sp
  764.     mov    prproc[bp],cx
  765.     mov    prargbx[bp],bx
  766.     mov    prargdx[bp],dx
  767.     mov    procnt[bp],0
  768. ;
  769. disploop:
  770.     lodsb
  771.     or    al,al
  772.     jz    dispend            ; end of string
  773.     cmp    al,'%'
  774.     je    dispformat        ; jump if format character
  775.     cmp    al,0ah
  776.     jne    dispchar
  777.     mov    al,0dh
  778.     call    prproc[bp]        ; translate LF into CR+LF
  779.     inc    procnt[bp]
  780.     mov    al,0ah
  781. ;
  782. dispchar:
  783.     call    prproc[bp]
  784.     inc    procnt[bp]
  785.     jmp    disploop
  786. ;
  787. dispend:
  788.     mov    bx,prargbx[bp]
  789.     add    sp,TYPE dislocrec
  790.     pop    bp
  791.     ret
  792. ;
  793. disploop1:
  794.     pop    di
  795.     pop    es
  796.     add    di,arglen[bp]
  797.     jmp    disploop
  798. ;
  799. ;    Format character found, process conversion
  800. ;
  801. dispformat:
  802.     lodsb
  803.     cmp    al,'%'        ; %% means print single %
  804.     je    dispchar
  805. ;
  806.     push    es
  807.     push    di        ; save parameter pointer
  808.     mov    prflags[bp],0
  809.     mov    arglen[bp],2
  810. ;
  811.     cmp    al,'-'
  812.     jne    no_flags
  813.     or    prflags[bp],F_LEFTADJ
  814.     lodsb
  815. ;
  816. no_flags:
  817.     cmp    al,'0'
  818.     jne    no_zero
  819.     or    prflags[bp],F_PADZERO
  820.     lodsb
  821. ;
  822. no_zero:
  823.     cmp    al,'*'
  824.     je    loadwidth
  825.     cmp    al,'9'
  826.     ja    no_width
  827.     cmp    al,'0'
  828.     jb    no_width
  829.     call    @getint
  830.     jmp    short haswidth
  831. ;
  832. loadwidth:
  833.     mov    ax,word ptr es:[di]
  834.     add    di,2
  835.     add    arglen[bp],2
  836. ;
  837. haswidth:
  838.     or    prflags[bp],F_WIDTH
  839.     mov    prwidth[bp],ax
  840.     lodsb
  841. ;
  842. no_width:
  843.     cmp    al,'.'
  844.     jne    no_prec
  845.     lodsb
  846.     cmp    al,'*'
  847.     je    loadprec
  848.     cmp    al,'9'
  849.     ja    no_prec
  850.     cmp    al,'0'
  851.     jb    no_prec
  852.     call    @getint
  853.     jmp    short hasprec
  854. ;
  855. loadprec:
  856.     mov    ax,word ptr es:[di]
  857.     add    di,2
  858.     add    arglen[bp],2
  859. ;
  860. hasprec:
  861.     or    prflags[bp],F_PREC
  862.     mov    prec[bp],ax
  863.     lodsb
  864. ;
  865. ;    Process indirection.
  866. ;
  867. no_prec:
  868.     mov    dx,ds
  869.     cmp    al,'^'
  870.     je    indir_near
  871.     cmp    al,'@'
  872.     jne    no_indir
  873.     add    arglen[bp],2
  874. ;
  875. indir_near:
  876.     or    prflags[bp],F_INDIR
  877. ;
  878. indir_loop:
  879.     cmp    al,'^'
  880.     je    is_indir
  881.     cmp    al,'@'
  882.     jne    no_indir
  883.     mov    dx,word ptr es:2[di]
  884. is_indir:
  885.     mov    di,word ptr es:[di]
  886.     mov    es,dx
  887.     lodsb            ; next conversion char
  888.     jmp    indir_loop
  889. ;
  890. ;    Indirection finished, check for size modification
  891. ;
  892. no_indir:
  893.     IF    DFLT_FAR
  894.     cmp    al,'s'
  895.     je    dfltsize0
  896.     cmp    al,'n'
  897.     je    dfltsize0
  898.     cmp    al,'p'
  899.     je    dfltsize0
  900.     cmp    al,'P'
  901.     jne    dfltsize1
  902. ;
  903. dfltsize0:
  904.     or    prflags[bp],F_LONGARG
  905.     jmp    short no_sizemod
  906. ;
  907. dfltsize1:
  908.     ENDIF
  909.     cmp    al,'F'
  910.     je    sizemodl
  911.     cmp    al,'N'
  912.     jne    sizemod2
  913.     lodsb
  914.     jmp    short no_sizemod
  915. ;
  916. sizemod2:
  917.     cmp    al,'h'
  918.     jne    sizemod3
  919.     or    prflags[bp],F_SHORTARG
  920.     lodsb
  921.     jmp    short no_sizemod
  922. ;
  923. sizemod3:
  924.     cmp    al,'l'
  925.     jne    no_sizemod
  926. ;
  927. sizemodl:
  928.     or    prflags[bp],F_LONGARG
  929.     lodsb
  930. ;
  931. no_sizemod:
  932.     xor    dx,dx
  933.     test    prflags[bp],F_LONGARG
  934.     jz    loadsingle
  935.     mov    dx,word ptr es:2[di]
  936.     test    prflags[bp],F_INDIR
  937.     jnz    loadsingle
  938.     add    arglen[bp],2
  939. ;
  940. loadsingle:
  941.     mov    bl,al
  942.     mov    ax,word ptr es:[di]
  943.     test    prflags[bp],F_SHORTARG
  944.     jz    noshort
  945.     xor    ah,ah
  946. ;
  947. noshort:
  948.     cmp    bl,'n'
  949.     jne    convc0
  950.     test    prflags[bp],F_LONGARG
  951.     jz    gostorelen
  952.     mov    ds,dx
  953. gostorelen:
  954.     mov    bx,ax
  955.     mov    ax,procnt[bp]
  956.     mov    [bx],ax
  957.     jmp    disploop1
  958. ;
  959. convc0:
  960.     lea    di,convbuf[bp]
  961. ;
  962.     cmp    bl,'c'
  963.     jne    convc1
  964.     mov    byte ptr ss:[di],al
  965.     inc    di
  966.     mov    bx,1
  967.     and    prflags[bp],NOT (F_PREC OR F_PADZERO)
  968.     jmp    out_conv
  969. ;
  970. convc1:
  971.     cmp    bl,'s'
  972.     jne    convc2
  973.     test    prflags[bp],F_LONGARG
  974.     jnz    gofmtstring
  975.     mov    dx,ds
  976. gofmtstring:
  977.     and    prflags[bp],NOT F_PADZERO
  978.     jmp    fmtstring
  979. ;
  980. convc2:
  981.     cmp    bl,'x'
  982.     je    fmthex
  983.     cmp    bl,'X'
  984.     je    fmthex
  985.     cmp    bl,'p'
  986.     je    fmtptr
  987.     cmp    bl,'P'
  988.     je    fmtptr
  989.     cmp    bl,'u'
  990.     je    fmtdec
  991.     cmp    bl,'d'
  992.     jne    badconv
  993.     test    prflags[bp],F_LONGARG
  994.     jnz    signedlong
  995.     test    prflags[bp],F_SHORTARG
  996.     jz    signedint
  997.     cbw
  998. ;
  999. signedint:
  1000.     test    ah,80h
  1001.     jz    fmtdec
  1002.     or    prflags[bp],F_SIGNED
  1003.     neg    ax
  1004.     jmp    short fmtdec
  1005. ;
  1006. signedlong:
  1007.     test    dh,80h
  1008.     jz    fmtdec
  1009.     or    prflags[bp],F_SIGNED
  1010.     mov    cx,dx
  1011.     xor    dx,dx
  1012.     neg    ax
  1013.     sbb    dx,cx
  1014.     jmp    short fmtdec
  1015. ;
  1016. ;    Invalid conversion. Reset parameter pointer and output the
  1017. ;    char.
  1018. ;
  1019. badconv:
  1020.     pop    di
  1021.     pop    es
  1022.     mov    al,bl
  1023.     jmp    dispchar
  1024. ;
  1025. ;
  1026. fmtdec:
  1027.     call    @decconv
  1028.     test    prflags[bp],F_SIGNED
  1029.     jz    fmtdnosign
  1030.     mov    byte ptr ss:[di],'-'
  1031.     inc    di
  1032.     inc    bx
  1033. fmtdnosign:
  1034.     jmp    short out_conv
  1035. ;
  1036. fmthex:
  1037.     mov    prhexch[bp],'a'-10-'0'
  1038.     cmp    bl,'x'
  1039.     je    fmthex1
  1040.     mov    prhexch[bp],'A'-10-'0'
  1041. fmthex1:
  1042.     call    @hexconv
  1043.     jmp    short out_conv
  1044. ;
  1045. fmtptr:
  1046.     mov    prhexch[bp],'a'-10-'0'
  1047.     cmp    bl,'p'
  1048.     je    fmtptr1
  1049.     mov    prhexch[bp],'A'-10-'0'
  1050. fmtptr1:
  1051.     and    prflags[bp],NOT (F_PREC OR F_PADZERO)
  1052.     mov    cl,4
  1053.     mov    bh,cl
  1054.     xor    bl,bl
  1055. ;
  1056. fmtplo:
  1057.     call    @hexdigbp
  1058.     shr    ax,cl
  1059.     dec    bh
  1060.     jnz    fmtplo
  1061.     test    prflags[bp],F_LONGARG
  1062.     jz    out_conv
  1063. ;
  1064.     mov    byte ptr ss:[di],':'
  1065.     inc    di
  1066.     inc    bl
  1067.     mov    bh,cl
  1068.     mov    ax,dx
  1069. ;
  1070. fmtphilp:
  1071.     call    @hexdigbp
  1072.     shr    ax,cl
  1073.     dec    bh
  1074.     jnz    fmtphilp
  1075. ;
  1076. ;
  1077. out_conv:
  1078.     mov    cx,bx
  1079.     call    @padleft
  1080.     add    procnt[bp],cx
  1081. outc_out:
  1082.     dec    di
  1083.     mov    al,byte ptr ss:[di]
  1084.     call    prproc[bp]
  1085.     loop    outc_out
  1086.     call    @padright
  1087.     jmp    disploop1
  1088. ;
  1089. ;
  1090. fmtstring:
  1091.     push    si
  1092.     push    ds
  1093.     mov    ds,dx
  1094.     mov    si,ax
  1095. ;
  1096.     mov    es,dx
  1097.     mov    di,ax
  1098.     xor    ax,ax
  1099.     mov    cx,-1
  1100.     repne scasb
  1101.     not    cx
  1102.     dec    cx
  1103.     test    prflags[bp],F_PREC
  1104.     jz    fmtstr_np
  1105.     cmp    cx,prec[bp]
  1106.     jbe    fmtstr_np
  1107.     mov    cx,prec[bp]
  1108. ;
  1109. fmtstr_np:
  1110.     and    prflags[bp],NOT F_PREC
  1111.     mov    bx,cx
  1112.     call    @padleft
  1113.     jcxz    fmtstr_end
  1114.     add    procnt[bp],cx
  1115. fmtstr_out:
  1116.     lodsb
  1117.     call    prproc[bp]
  1118.     loop    fmtstr_out
  1119. fmtstr_end:
  1120.     call    @padright
  1121.     pop    ds
  1122.     pop    si
  1123.     jmp    disploop1
  1124. ;
  1125. ;
  1126. @disprintf    endp
  1127. ;
  1128. ;
  1129. ; void tsk_printf (char far *format, ...)
  1130. ;
  1131. ;    Formatted output to console.
  1132. ;
  1133. CGlobalfunc tsk_printf,<uses ds si di, fmt: far ptr, varg: word>
  1134. ;
  1135.     mov    ax,ss
  1136.     mov    es,ax
  1137.     lds    si,fmt
  1138.     lea    di,varg
  1139.     mov    cx,offset @dischar
  1140.     call    @disprintf
  1141.     ret
  1142. tsk_printf    endp
  1143. ;
  1144. ;
  1145. ; void tsk_vprintf (char far *format, void far *arg)
  1146. ;
  1147. ;    Formatted output to console.
  1148. ;
  1149. Globalfunc tsk_vprintf,<uses ds si di, fmt: far ptr, varg: far ptr>
  1150. ;
  1151.     lds    si,fmt
  1152.     les    di,varg
  1153.     mov    cx,offset @dischar
  1154.     call    @disprintf
  1155.     ret
  1156. tsk_vprintf    endp
  1157. ;
  1158. ;
  1159. ; void tsk_fprintf (int handle, char far *format, ...)
  1160. ;
  1161. ;    Formatted output to file.
  1162. ;
  1163. CGlobalfunc tsk_fprintf    <uses ds si di, handle: word, fmt: far ptr, varg: word>
  1164. ;
  1165.     mov    ax,ss
  1166.     mov    es,ax
  1167.     lds    si,fmt
  1168.     lea    di,varg
  1169.     sub    sp,FILE_BUFSIZE
  1170.     mov    dx,sp
  1171.     mov    bx,sp
  1172.     mov    byte ptr ss:[bx],0
  1173.     mov    cx,offset @filechar
  1174.     mov    bx,handle
  1175.     call    @disprintf
  1176.     mov    si,sp
  1177.     mov    cl,ss:[si]
  1178.     xor    ch,ch
  1179.     jcxz    fprintfend
  1180.     mov    dx,si
  1181.     inc    dx
  1182.     mov    bx,handle
  1183.     mov    ax,ss
  1184.     mov    ds,ax
  1185.     mov    ah,40h
  1186.     int    21h
  1187. fprintfend:
  1188.     add    sp,FILE_BUFSIZE
  1189.     ret
  1190. tsk_fprintf    endp
  1191. ;
  1192. ;
  1193. ; void tsk_vfprintf (int handle, char far *format, void far *arg)
  1194. ;
  1195. ;    Formatted output to file.
  1196. ;
  1197. Globalfunc tsk_vfprintf,<uses ds si di, handle: word, fmt: far ptr, varg: far ptr>
  1198. ;
  1199.     lds    si,fmt
  1200.     les    di,varg
  1201.     sub    sp,FILE_BUFSIZE
  1202.     mov    dx,sp
  1203.     mov    bx,sp
  1204.     mov    byte ptr ss:[bx],0
  1205.     mov    cx,offset @filechar
  1206.     mov    bx,handle
  1207.     call    @disprintf
  1208.     mov    si,sp
  1209.     mov    cl,ss:[si]
  1210.     xor    ch,ch
  1211.     jcxz    vfprintfend
  1212.     mov    dx,si
  1213.     inc    dx
  1214.     mov    bx,handle
  1215.     mov    ax,ss
  1216.     mov    ds,ax
  1217.     mov    ah,40h
  1218.     int    21h
  1219. vfprintfend:
  1220.     add    sp,FILE_BUFSIZE
  1221.     ret
  1222. tsk_vfprintf    endp
  1223. ;
  1224. ;
  1225. ; void tsk_sprintf (char far *dest, char far *format, ...)
  1226. ;
  1227. ;    Formatted output to string.
  1228. ;
  1229. CGlobalfunc tsk_sprintf,<uses ds si di, dest: far ptr, fmt: far ptr, varg: word>
  1230. ;
  1231.     mov    ax,ss
  1232.     mov    es,ax
  1233.     lds    bx,dest
  1234.     mov    dx,ds
  1235.     lds    si,fmt
  1236.     lea    di,varg
  1237.     mov    cx,offset @stringchar
  1238.     call    @disprintf
  1239.     sub    bx,word ptr(dest)
  1240.     mov    ax,bx
  1241.     ret
  1242. tsk_sprintf    endp
  1243. ;
  1244. ;
  1245. ; void tsk_vsprintf (char far *dest, char far *format, void far *arglist)
  1246. ;
  1247. ;    Formatted output to string.
  1248. ;
  1249. Globalfunc tsk_vsprintf,<uses ds si di, dest: far ptr, fmt: far ptr, varg: far ptr>
  1250. ;
  1251.     lds    bx,dest
  1252.     mov    dx,ds
  1253.     lds    si,fmt
  1254.     les    di,varg
  1255.     mov    cx,offset @stringchar
  1256.     call    @disprintf
  1257.     sub    bx,word ptr(dest)
  1258.     mov    ax,bx
  1259.     ret
  1260. tsk_vsprintf    endp
  1261. ;
  1262. ;
  1263. ; void tsk_rprintf (char far *format, ...)
  1264. ;
  1265. ;    Formatted output to regen buffer (second display).
  1266. ;
  1267. CGlobalfunc tsk_rprintf,<uses ds si di, fmt: far ptr, varg: word>
  1268. ;
  1269.     IFDEF    LOAD_DS
  1270.     mov    ds,cs:ctdataseg
  1271.     ENDIF
  1272.     mov    cx,sc_proc
  1273.     mov    ax,ss
  1274.     mov    es,ax
  1275.     lds    si,fmt
  1276.     lea    di,varg
  1277.     call    @disprintf
  1278.     ret
  1279. tsk_rprintf    endp
  1280. ;
  1281. ;
  1282. ; void tsk_vrprintf (char far *format, void far *arglist)
  1283. ;
  1284. ;    Formatted output to regen buffer (second display).
  1285. ;
  1286. Globalfunc tsk_vrprintf,<uses ds si di, fmt: far ptr, varg: far ptr>
  1287. ;
  1288.     IFDEF    LOAD_DS
  1289.     mov    ds,cs:ctdataseg
  1290.     ENDIF
  1291.     mov    cx,sc_proc
  1292.     lds    si,fmt
  1293.     les    di,varg
  1294.     call    @disprintf
  1295.     ret
  1296. tsk_vrprintf    endp
  1297. ;
  1298. ;
  1299. ; void tsk_putc (char c)
  1300. ;
  1301. ;    Output character to console.
  1302. ;    
  1303. Globalfunc tsk_putc,<chr: word>
  1304.     mov    ax,chr
  1305.     call    @dischar
  1306.     ret
  1307. tsk_putc    endp
  1308. ;
  1309. ;
  1310. ; void tsk_puts (char far *s)
  1311. ;
  1312. ;    Output string to console.
  1313. ;    
  1314. Globalfunc tsk_puts,<uses ds si, dstr: far ptr>
  1315. ;
  1316.     lds    si,dstr
  1317. putslp:
  1318.     lodsb
  1319.     or    al,al
  1320.     jz    putsend
  1321.     call    @dischar
  1322.     jmp    putslp
  1323. ;
  1324. putsend:
  1325.     mov    al,0dh
  1326.     call    @dischar
  1327.     mov    al,0ah
  1328.     call    @dischar
  1329.     ret
  1330. tsk_puts    endp
  1331. ;
  1332. ;
  1333. ; void tsk_rputc (char c)
  1334. ;
  1335. ;    Output character to regen buffer (second display).
  1336. ;    
  1337. Globalfunc tsk_rputc,<chr: word>
  1338. ;
  1339.     mov    ax,chr
  1340.     IFDEF    LOAD_DS
  1341.     push    ds
  1342.     mov    ds,cs:ctdataseg
  1343.     call    sc_proc
  1344.     pop    ds
  1345.     ELSE
  1346.     call    sc_proc
  1347.     ENDIF
  1348.     ret
  1349. tsk_rputc    endp
  1350. ;
  1351. ;
  1352. ; void tsk_rputs (char far *s)
  1353. ;
  1354. ;    Output string to regen buffer.
  1355. ;    
  1356. Globalfunc tsk_rputs,<uses si, dstr: far ptr>
  1357. ;
  1358.     IFDEF    LOAD_DS
  1359.     push    ds
  1360.     mov    ds,cs:ctdataseg
  1361.     ENDIF
  1362.     les    si,dstr
  1363. rputslp:
  1364.     lods    es:prflags
  1365.     or    al,al
  1366.     jz    rputsend
  1367.     call    sc_proc
  1368.     jmp    rputslp
  1369. ;
  1370. rputsend:
  1371.     mov    al,0dh
  1372.     call    sc_proc
  1373.     mov    al,0ah
  1374.     call    sc_proc
  1375.     IFDEF    LOAD_DS
  1376.     pop    ds
  1377.     ENDIF
  1378.     ret
  1379. tsk_rputs    endp
  1380. ;
  1381. ;
  1382. ; void tsk_setpos (int row, int col)
  1383. ;
  1384. ;    Set cursor position for regen output.
  1385. ;    First position on screen is (0, 0).
  1386. ;
  1387. Globalfunc tsk_setpos,<row: word, col: word>
  1388. ;
  1389.     IFDEF    LOAD_DS
  1390.     push    ds
  1391.     mov    ds,cs:ctdataseg
  1392.     ENDIF
  1393.     mov    ax,row
  1394.     mul    sc_cols
  1395.     add    ax,col
  1396.     add    ax,col
  1397.     mov    tsk_regen_o,ax
  1398.     call    @setcsr
  1399.     IFDEF    LOAD_DS
  1400.     pop    ds
  1401.     ENDIF
  1402.     ret
  1403. tsk_setpos    endp
  1404. ;
  1405. ;
  1406. ; void tsk_set_regen (int segment, int port, int rows, int cols)
  1407. ;
  1408. ;    Set regen buffer address and size, and display controller port.
  1409. ;    This routine can be used to force regen output to the
  1410. ;    primary screen for single-screen systems, and to modify
  1411. ;    the output parameters (number of rows and columns).
  1412. ;
  1413. Globalfunc tsk_set_regen,<reg: word, port: word, rows: word, cols: word>
  1414. ;
  1415.     IFDEF    LOAD_DS
  1416.     push    ds
  1417.     mov    ds,cs:ctdataseg
  1418.     ENDIF
  1419.     mov    ax,reg
  1420.     mov    tsk_regen_s,ax
  1421.     mov    ax,port
  1422.     mov    tsk_disport,ax
  1423.     mov    tsk_regen_o,0
  1424.     mov    ax,cols
  1425.     add    ax,ax
  1426.     mov    sc_cols,ax
  1427.     mul    rows
  1428.     mov    sc_end,ax
  1429.     mov    sc_proc,offset @disregen
  1430.     IFDEF    LOAD_DS
  1431.     pop    ds
  1432.     ENDIF
  1433.     ret
  1434. tsk_set_regen    endp
  1435. ;
  1436. ;
  1437. ; int tsk_set_dualdis (void)
  1438. ;
  1439. ;    Determine regen buffer address on second monitor.
  1440. ;    This routine first checks the current video mode. If it's
  1441. ;    mode 7, the regen buffer is set to B800 (the colour screen).
  1442. ;    For all other modes, the regen buffer is B000 (mono).
  1443. ;    Then a check is done to make sure that the secondary card
  1444. ;    exists. If it does, the regen output is initialized. Otherwise,
  1445. ;    any output through the regen routines will be discarded.
  1446. ;
  1447. ;    Returns 0 if there is no secondary monitor, else the
  1448. ;    regen buffer address.
  1449. ;
  1450. ;    No attempt is made to initialize the secondary monitor,
  1451. ;    the monitor must be in alpha mode.
  1452. ;
  1453. Globalfunc tsk_set_dualdis
  1454. ;
  1455.     IFDEF    LOAD_DS
  1456.     push    ds
  1457.     mov    ds,cs:ctdataseg
  1458.     ENDIF
  1459.     mov    ah,0fh
  1460.     push    bp
  1461.     int    10h        ; get video mode
  1462.     pop    bp
  1463.     mov    bx,0b800h    ; colour regen buffer
  1464.     mov    dx,3d4h        ; CGA 6845 I/O addr
  1465.     cmp    al,7        ; only mode 7 has regen at B000
  1466.     je    ddis_checks
  1467.     mov    bx,0b000h    ; mono regen buffer
  1468.     mov    dx,3b4h        ; mono 6845 I/O addr
  1469. ;
  1470. ddis_checks:
  1471.     mov    tsk_regen_s,bx
  1472.     mov    tsk_regen_o,0
  1473.     mov    tsk_disport,dx
  1474.     mov    sc_cols,80 * 2
  1475.     mov    sc_end,25 * 80 * 2
  1476.     mov    al,0fh
  1477.     out    dx,al
  1478.     inc    dx
  1479.     in    al,dx
  1480.     mov    ah,al
  1481.     mov    al,56h
  1482.     out    dx,al
  1483.     mov    cx,100h
  1484. ddis_wait:
  1485.     loop    ddis_wait
  1486.     in    al,dx
  1487.     xchg    ah,al
  1488.     out    dx,al
  1489.     cmp    ah,56h
  1490.     je    ddis_ok
  1491.     mov    sc_proc,offset @nodis
  1492.     xor    ax,ax
  1493.     mov    tsk_regen_s,ax
  1494.     jmp    short ddis_end
  1495. ;
  1496. ddis_ok:
  1497.     mov    sc_proc,offset @disregen
  1498.     mov    ax,bx
  1499. ;
  1500. ddis_end:
  1501.     IFDEF    LOAD_DS
  1502.     pop    ds
  1503.     ENDIF
  1504.     ret
  1505. ;
  1506. tsk_set_dualdis    endp
  1507. ;
  1508. ;
  1509. ; int tsk_set_currdis (void)
  1510. ;
  1511. ;    Determine regen buffer address on current monitor.
  1512. ;    This routine checks the current video mode. If it's
  1513. ;    mode 7, the regen buffer is set to B000 (the mono screen).
  1514. ;    For all other modes, the regen buffer is B800 (colour).
  1515. ;
  1516. ;    Returns the regen buffer address.
  1517. ;
  1518. ;    No attempt is made to initialize the monitor, or to check for
  1519. ;    special modes with different regen address. The monitor must 
  1520. ;    be in alpha mode.
  1521. ;
  1522. Globalfunc tsk_set_currdis
  1523. ;
  1524.     IFDEF    LOAD_DS
  1525.     push    ds
  1526.     mov    ds,cs:ctdataseg
  1527.     ENDIF
  1528.     mov    ah,0fh
  1529.     push    bp
  1530.     int    10h        ; get video mode
  1531.     pop    bp
  1532.     mov    bx,0b800h    ; colour regen buffer
  1533.     cmp    al,7        ; only mode 7 has regen at B000
  1534.     jne    curdis_ready
  1535.     mov    bx,0b000h    ; mono regen buffer
  1536. ;
  1537. curdis_ready:
  1538.     mov    tsk_regen_s,bx
  1539.     mov    tsk_regen_o,0
  1540.     mov    ax,SEG biosdata
  1541.     mov    es,ax
  1542.     assume    es:biosdata
  1543.     mov    ax,bios_chipad
  1544.     mov    tsk_disport,ax
  1545.     mov    ax,bios_cols
  1546.     add    ax,ax
  1547.     mov    sc_cols,ax
  1548.     mov    dl,bios_rows
  1549.     xor    dh,dh
  1550.     mul    dx
  1551.     mov    sc_end,ax
  1552.     mov    sc_proc,offset @disregen
  1553.     mov    ax,bx
  1554.     IFDEF    LOAD_DS
  1555.     pop    ds
  1556.     ENDIF
  1557.     ret
  1558. ;
  1559. tsk_set_currdis    endp
  1560. ;
  1561. ;
  1562. ; void tsk_set_colour (int rows, int cols)
  1563. ;
  1564. ;    Set regen buffer address to colour monitor.
  1565. ;
  1566. Globalfunc tsk_set_colour,<rows: word, cols: word>
  1567. ;
  1568.     IFDEF    LOAD_DS
  1569.     push    ds
  1570.     mov    ds,cs:ctdataseg
  1571.     ENDIF
  1572.     mov    tsk_regen_s,0b800h    ; colour regen buffer
  1573.     mov    tsk_regen_o,0
  1574.     mov    tsk_disport,3d4h    ; CGA 6845 I/O addr
  1575.     mov    ax,cols
  1576.     add    ax,ax
  1577.     mov    sc_cols,ax
  1578.     mul    rows
  1579.     mov    sc_end,ax
  1580.     mov    sc_proc,offset @disregen
  1581.     IFDEF    LOAD_DS
  1582.     pop    ds
  1583.     ENDIF
  1584.     ret
  1585. ;
  1586. tsk_set_colour    endp
  1587. ;
  1588. ;
  1589. ; void tsk_set_mono (int rows, int cols)
  1590. ;
  1591. ;    Set regen buffer address to monochrome monitor.
  1592. ;
  1593. Globalfunc tsk_set_mono,<rows: word, cols: word>
  1594. ;
  1595.     IFDEF    LOAD_DS
  1596.     push    ds
  1597.     mov    ds,cs:ctdataseg
  1598.     ENDIF
  1599.     mov    tsk_regen_s,0b000h    ; mono regen buffer
  1600.     mov    tsk_regen_o,0
  1601.     mov    tsk_disport,3b4h    ; mono 6845 I/O addr
  1602.     mov    ax,cols
  1603.     add    ax,ax
  1604.     mov    sc_cols,ax
  1605.     mul    rows
  1606.     mov    sc_end,ax
  1607.     mov    sc_proc,offset @disregen
  1608.     IFDEF    LOAD_DS
  1609.     pop    ds
  1610.     ENDIF
  1611.     ret
  1612. ;
  1613. tsk_set_mono    endp
  1614. ;
  1615. ;
  1616. ; void tsk_set_attr (int attr)
  1617. ;
  1618. ;    Set regen display attributes
  1619. ;
  1620. Globalfunc tsk_set_attr,<attr: word>
  1621. ;
  1622.     IFDEF    LOAD_DS
  1623.     push    ds
  1624.     mov    ds,cs:ctdataseg
  1625.     ENDIF
  1626.     mov    ax,attr
  1627.     mov    tsk_attrib,al
  1628.     IFDEF    LOAD_DS
  1629.     pop    ds
  1630.     ENDIF
  1631.     ret
  1632. ;
  1633. tsk_set_attr    endp
  1634. ;
  1635. ;
  1636. ; void tsk_set_clreol (int clr)
  1637. ;
  1638. ;    Set special handling of CR. If "clr" is nonzero, CR will clear
  1639. ;    to end of line before returning to the home position.
  1640. ;
  1641. Globalfunc tsk_set_clreol,<clr: word>
  1642. ;
  1643.     IFDEF    LOAD_DS
  1644.     push    ds
  1645.     mov    ds,cs:ctdataseg
  1646.     ENDIF
  1647.     mov    ax,clr
  1648.     mov    sc_clreol,al
  1649.     IFDEF    LOAD_DS
  1650.     pop    ds
  1651.     ENDIF
  1652.     ret
  1653. ;
  1654. tsk_set_clreol    endp
  1655. ;
  1656.     .tsk_ecode
  1657.     end
  1658.  
  1659.