home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / ansi / nnansi / nnansi_f.asm < prev    next >
Assembly Source File  |  1990-09-11  |  19KB  |  773 lines

  1.     page    60, 132
  2. ;----- nnansi_f.asm ---------------------------------------------
  3. ; The ANSI control subroutines.
  4. ; (C) 1986 Daniel Kegel, Pasadena, CA
  5. ; May be distributed for educational and personal use only
  6. ; Each routine is called with the following register usage:
  7. ;  AX = max(1, value of first parameter)
  8. ;  Z flag is set if first parameter is zero.
  9. ;  CX = number of paramters
  10. ;  SI = offset of second parameter from CS
  11. ;  DS = CS
  12. ;  ES:DI points to the current location on the memory-mapped screen.
  13. ;  DX is number of characters remaining on the current screen line.
  14. ; The control routine is free to trash AX, BX, CX, SI, and DS.
  15. ; It must preserve ES, and can alter DX and DI if it wants to move the
  16. ; cursor.
  17. ;
  18. ; Revisions:
  19. ;  19 Aug 85: Fixed horrible bug in insert/delete line.
  20. ;  26 Aug 85: Fixed simple limit-to-one-too-few-lines bug in ins/del line;
  21. ;  anyway, it inserts 24 lines when on line 2 now.  Whether it's fixed...
  22. ;  4 Sept 85: Fixed bug created on 26 Aug 85; when limiting ins/del line
  23. ;  count, we are clearing, not scrolling; fixed BIOS call to reflect this.
  24. ;  30 Jan 86: Added EGA cursor patch
  25. ;  31 Jan 86: Disabled insert/delete char in graphics modes
  26. ;          Implemented keyboard redefinition reset
  27. ;  1 Feb 86: added video_mode and max_x test after mode set
  28. ;  8 Jan 89:  Slight changes for compilation options
  29.  
  30. ; Also modified by Tom Almy, no restrictions.
  31. ; See nnansi.asm
  32.  
  33. ;----------------------------------------------------------------
  34.  
  35.     include nnansi_d.asm
  36.  
  37.     ; To nnansi_p.asm
  38.     public    ansi_fn_table
  39.  
  40.     ; From nnansi.asm
  41.  
  42. port_6845    equ    3d4h
  43.  
  44.     extrn    cur_coords:word, saved_coords:word
  45.     extrn    cur_x:byte, max_x:byte
  46.     extrn    cur_y:byte, max_y:byte
  47.     extrn    cur_attrib:byte, wrap_flag:byte
  48.     extrn    xy_to_regs:near
  49.     extrn    get_blank_attrib:near
  50.     extrn    move_back:near
  51.     extrn    cpr_esc:byte, cprseq:word
  52.     extrn    video_mode:byte
  53. if key_redef
  54.     extrn    lookup:near
  55. endif
  56.     extrn    gmode_flag:byte
  57.     extrn    gcursor:byte
  58.     extrn    fmode:byte
  59.     extrn    rev_flag:byte
  60.     extrn    param_buffer:word    ; used in keyboard programming
  61.     extrn    param_end:word
  62. if key_redef
  63.     extrn    redef_end:word
  64. endif
  65.  
  66.  
  67.     extrn    old_vid_bios:dword
  68.  
  69. call_video macro    ; call original video interrupt
  70.     pushf        ; push flags
  71.     call    dword ptr old_vid_bios    ; ds addresses cs in this module
  72. endm
  73.  
  74. keybuf    struc                ; used in making cpr sequence
  75. len    dw    ?
  76. adr    dw    ?
  77. keybuf    ends
  78.  
  79.  
  80. ABS40    segment at 40h
  81.     org    1ah
  82. buffer_head    dw    ?    ; Used in 'flush input buffer' dos call.
  83. buffer_tail    dw    ?
  84.  
  85.     org    49h
  86. crt_mode    db    ?
  87. crt_cols    dw    ?
  88. crt_len        dw    ?
  89. crt_start    dw    ?
  90. cursor_posn    dw    8 dup (?)
  91. cursor_mode    dw    ?
  92. active_page    db    ?
  93. addr_6845    dw    ?
  94. crt_mode_set    db    ?
  95. crt_palette    db    ?
  96.  
  97.     org    84h
  98. ega_rows    db    ?    ; #rows-1 on display
  99.  
  100. ABS40    ends
  101.  
  102. code    segment byte public 'CODE'
  103.     assume cs:code, ds:code
  104.  
  105. ;----- byteout ---------------------------------------------------
  106. ; Converts al to a decimal ASCII string (in 0..99),
  107. ; stores it at ES:DI++.     Returns DI pointing at byte after last digit.
  108. ; Destroys DL.
  109.  
  110. byteout proc    near
  111.     cmp    al, 100        ; check for >99 case TAA mod
  112.     jb    goodbyteout
  113.     push    ax
  114.     mov    al, '1'        ; assume value <200!
  115.     stosb
  116.     pop    ax
  117.     sub    ax, 100
  118. goodbyteout:
  119.     aam
  120.     add    ax, 3030h
  121.     xchg    ah, al
  122.     stosb
  123.     xchg    ah, al
  124.     stosb
  125.     ret
  126. byteout endp
  127.  
  128. ;----- ansi_fn_table -----------------------------------
  129. ; Table of offsets of terminal control subroutines in order of
  130. ; the character that invokes them, @..Z, a..z.    Exactly 53 entries.
  131. ; All the subroutines are defined below in this module.
  132. ansi_fn_table    label    word
  133.     dw    ic,  cup, cdn, cfw, cbk        ; @, A, B, C, D
  134.     dw    nul, nul, nul, hvp, nul        ; E, F, G, H, I
  135.     dw    eid, eil, il,  d_l, nul        ; J, K, L, M, N
  136.     dw    nul, dc,  nul, nul, nul        ; O, P, Q, R, S
  137.     dw    nul, nul, nul, nul, nul        ; T, U, V, W, X
  138.     dw    nul, nul            ; Y, Z
  139.     dw    nul, nul, nul, nul, nul        ; a, b, c, d, e
  140.     dw    hvp, nul, sm,  nul, nul        ; f, g, h, i, j
  141.     dw    nul, rm,  sgr, dsr, nul        ; k, l, m, n, o
  142. if key_redef
  143.     dw    key, nul, nul, scp, nul        ; p, q, r, s, t
  144. else
  145.     dw    nul, nul, nul, scp, nul        ; p, q, r, s, t
  146. endif
  147.     dw    rcp, nul, nul, nul, nul        ; u, v, w, x, y
  148.     dw    nul                ; z
  149.  
  150. ansi_functions    proc    near        ; set return type to NEAR
  151.  
  152. ;----- nul ---------------------------------------------
  153. ; No-action ansi sequence; called when unknown command given.
  154. nul:    ret
  155.  
  156. ;----- Cursor Motion -----------------------------------------------
  157.  
  158. ;-- cursor to y,x
  159. hvp:    or    al, al        ; First parameter is desired Y coordinate.
  160.     jz    hvp_yok
  161.     dec    ax        ; Convert to zero-based coordinates.
  162. hvp_yok:mov    cur_y, al
  163.     ; Get second parameter, if it is there, and set X with it.
  164.     xor    ax, ax
  165.     cmp    cx, 2        ; was there a second parameter?
  166.     jb    hvp_xok
  167.     lodsb            ; yes.
  168.     or    al, al
  169.     jz    hvp_xok
  170.     dec    ax        ; convert to zero-based coordinates.
  171. hvp_xok:mov    cur_x, al
  172.  
  173.     ; Clip to maximum coordinates.
  174. hvp_set:
  175.     mov    ax, cur_coords        ; al = x, ah = y
  176.     cmp    al, max_x
  177.     jbe    hvp_sxok
  178.         mov    al, max_x
  179.         mov    cur_x, al
  180. hvp_sxok:
  181.     cmp    ah, max_y
  182.     jbe    hvp_syok
  183.         mov    al, max_y
  184.         mov    cur_y, al
  185. hvp_syok:
  186.     ; Set values of DX and DI accordingly.
  187.     call    xy_to_regs
  188.     ret
  189.  
  190. ;-- cursor forward --
  191. cfw:    add    cur_x, al
  192.     jmp    hvp_set
  193.  
  194. ;-- cursor back -----
  195. cbk:    sub    cur_x, al
  196.     jae    cbk_ok
  197.         mov    cur_x, 0
  198. cbk_ok: jmp    hvp_set
  199.  
  200. ;-- cursor down -----
  201. cdn:    add    cur_y, al
  202.     jmp    hvp_set
  203.  
  204. ;-- cursor up -------
  205. cup:    sub    cur_y, al
  206.     jae    cup_ok
  207.         mov    cur_y, 0
  208. cup_ok: jmp    hvp_set
  209.  
  210. ;-- save cursor position --------------------------------------
  211. scp:    mov    ax, cur_coords
  212.     mov    saved_coords, ax
  213.     ret
  214.  
  215. ;-- restore cursor position -----------------------------------
  216. rcp:    mov    ax, saved_coords
  217.     mov    cur_coords, ax
  218.     jmp    hvp_set        ; Clip in case we have switched video modes.
  219.  
  220. ;-- set graphics rendition ------------------------------------
  221. ; Modifies the color in which new characters are written.
  222.  
  223.  
  224. sgr:    dec    si        ; get back pointer to first parameter
  225.     or    cx, cx        ; Did he give any parameters?
  226.     jnz    sgr_loop
  227.         mov    byte ptr [si], 0    ; no parameters, so fake
  228.         inc    cx            ; one with the default value.
  229.     ; For each parameter
  230. sgr_loop:
  231.         lodsb                ; al = next parameter
  232.         ; Search color table
  233.         push    cx
  234.  
  235.         cmp    al, 7            ; reverse video?
  236.         jz    sgr_rev
  237.         cmp    al, 27            ; unreverse video?
  238.         jz    sgr_unrev
  239.         cmp    al, 0            ; not reset?
  240.         jnz    sgr_continue
  241.         mov    rev_flag, 0
  242. sgr_continue:
  243.         mov    cx, colors
  244.         mov    bx, offset color_table-3
  245. sgr_search:
  246.             add    bx, 3
  247.             cmp    al, byte ptr [bx]
  248.             loopnz    sgr_search    ; until match found or done
  249.         jnz    sgr_loopx
  250.  
  251.         ; If parameter named a known color, set the current
  252.         ; color variable.
  253.  
  254.         cmp    rev_flag,0        ; not reverse video?
  255.         jz    sgr_1
  256.         call    sgr_flip        ; temporary unreverse
  257. sgr_1:
  258.         mov    ax, [bx+1]
  259.         and    cur_attrib, al
  260.         or    cur_attrib, ah
  261.         cmp    rev_flag,0        ; not reverse video?
  262.         jz    sgr_2
  263.         call    sgr_flip        ; reverse it 
  264. sgr_2:
  265. sgr_loopx:
  266.         pop    cx
  267.         loop    sgr_loop        ; until no more parameters.
  268.     ret
  269.  
  270. sgr_rev:    
  271.         cmp    rev_flag,0        ; already reverse?
  272.         jnz    sgr_loopx
  273.         inc    rev_flag        ; reverse things
  274.         call    sgr_flip
  275.         jmp    sgr_loopx
  276.  
  277. sgr_unrev:    cmp    rev_flag,0        ; already not-reverse?
  278.         jz    sgr_loopx
  279.         dec    rev_flag        ; unreverse things
  280.         call    sgr_flip
  281.         jmp    sgr_loopx
  282.  
  283. sgr_flip:
  284.         push    ax
  285.         mov    al, cur_attrib        ; get attribute
  286.         mov    ah, al            ; copy it
  287. if cheap_pc
  288.         ror    ah,1            ; swap nibbles
  289.         ror    ah,1
  290.         ror    ah,1
  291.         ror    ah,1
  292. else
  293.         ror    ah,4
  294. endif
  295.         and    ah,77h            ; get only color bits
  296.         and    al,88h            ; get only intens/blink bits
  297.         or    al,ah            ; join them
  298.         mov    cur_attrib,al        ; save flipped value
  299.         pop    ax
  300.         ret
  301.  
  302. ;-- erase in line ----------------------------------------
  303. ; Uses BIOS to scroll away a one-line rectangle
  304. eil:    push    dx
  305.     mov    cx, cur_coords
  306.     mov    dh, ch
  307.     jmp    short scrollem
  308.  
  309. ;-- erase in display -------------------------------------
  310. ; Uses BIOS to scroll away all of display
  311. eid:    
  312.     jz    eid_toend    ; first parms=0 -- erase to end
  313.     or    cx,cx        ; no args?
  314.     jz    eid_toend    ;  then erase to end
  315.     cmp    al, 1        ; erase to beginning?
  316.     jz    eid_tostart
  317.     cmp    al, 2
  318.     jnz    eid_ignore    ; param must be two
  319.     mov    cur_coords, 0
  320.     call    xy_to_regs
  321.     cmp    cs:fmode,0    ; see if running in fast mode
  322.     jz    eid_slow
  323.     xor    di, di    ; offset will be zero after clearing
  324. eid_slow:
  325.     push    dx
  326.     xor    cx, cx
  327.     mov    dh, max_y
  328. scrollem:
  329.     call    get_blank_attrib
  330.     mov    bh, ah
  331.     mov    dl, max_x
  332. eid_process:
  333.     mov    ax, 600h
  334.     int    10h        ; use int 10 so screen repositions itself
  335. ;    call_video          rather than "call_video"
  336. eid_done:
  337.     pop    dx
  338. eid_ignore:
  339.     ret
  340.  
  341. eid_toend:    ; erase following lines then go back and erase in line
  342.     push    dx
  343.     call    get_blank_attrib
  344.     mov    bh,ah
  345.     mov    ax, 600h
  346.     mov    dh, max_y
  347.     mov    dl, max_x
  348.     mov    ch, cur_y
  349.     inc    ch
  350.     cmp    ch, dh            ; don't erase if no following
  351.     ja    eid_nopost
  352.     xor    cl,cl
  353.     call_video
  354. eid_nopost:
  355.     mov    cx, cur_coords
  356.     mov    dh, ch
  357.     jmp    short scrollem
  358.  
  359.  
  360. eid_tostart:    ; erase preceeding lines then go back and erase in line
  361.     push    dx
  362.     call    get_blank_attrib
  363.     mov    bh,ah
  364.     mov    dh, cur_y
  365.     dec    dh
  366.     js    eid_nopre        ; don't erase if no preceeding
  367.     mov    ax,600h
  368.     xor    cx,cx
  369.     mov    dl, max_x
  370.     call_video
  371. eid_nopre:
  372.     mov    dx, cur_coords
  373.     dec    dl
  374.     js    eid_done
  375.     mov    ch, dh
  376.     xor    cl, cl
  377.     jmp    eid_process
  378.     
  379. ;-- device status report --------------------------------
  380. ; Stuffs an escape, a left bracket, current Y, semicolon, current X,
  381. ; a capital R, and a carriage return into input stream.
  382. ; The coordinates are 1 to 3 decimal digits each.
  383.  
  384. dsr:    push    di
  385.     push    dx
  386.     push    es
  387.     mov    ax, cs
  388.     mov    es, ax
  389.     std            ; Store string in reversed order for fun
  390.     mov    di, offset cpr_esc - 2
  391.     mov    al, cur_y
  392.     inc    al        ; convert to one-based coords
  393.     call    byteout        ; row
  394.     mov    al, ';'        ; ;
  395.     stosb
  396.     mov    al, cur_x
  397.     inc    al        ; convert to one-based coords
  398.     call    byteout        ; column
  399.     mov    al, 'R'        ; R ANSI function 'Cursor Position Report'
  400.     stosb
  401.     mov    al, 13
  402.     mov    word ptr cprseq.adr, di ; save pointer to last char in string
  403.     stosb                ; send a carriage return, too
  404.     mov    ax, offset cpr_esc
  405.     sub    ax, di            ; ax is # of characters in string
  406.     mov    word ptr cprseq.len, ax ; pass info to the getchar routine
  407.     cld
  408.     pop    es
  409.     pop    dx
  410.     pop    di
  411.     ret
  412. if key_redef
  413. ;-- keyboard reassignment -------------------------------
  414. ; Key reassignment buffer is between param_end and redef_end+2, exclusive.
  415. ; When it shrinks or grows, param_end is moved.
  416. ; Format of an entry is as follows:
  417. ;   highest address -> length:word (may be 0)
  418. ;               key to replace:word     (either hi or low byte is zero)
  419. ;               .
  420. ;               .    new key value, "length" bytes long
  421. ;               .
  422. ;   lowest address  -> next entry, or free space.
  423. ; If no arguments are given, keyboard is reset to default condition.
  424. ; Otherwise, first parameter (or first two, if first is zero) defines
  425. ; the key whose value is to be changed, and the following parameters
  426. ; define the key's new, possibly zero-length, value.
  427.  
  428. key:
  429.     ; Is this a reset?
  430.     or    cx, cx
  431.     jz    key_init
  432.     ; Get the first (or first two) parameters
  433.     cld
  434.     dec    si    ; point to first param
  435.     dec    cx    ; Assume it's a fn key, get two params
  436.     dec    cx
  437.     lodsw
  438.     or    al, al    ; Is it a function key?
  439.     jz    key_fnkey
  440.         ; It's not a function key- put second param back
  441.         inc    cx
  442.         dec    si
  443. key_fnkey:
  444.     ; Key to redefine now in AX.  If it's already redefined,
  445.     ; lookup will set Z, point SI to redef string, set CX to its length.
  446.     push    di
  447.     push    es
  448.     push    cx
  449.     push    si
  450.  
  451.     std            ; moving up, must move from top down
  452.     push    ds
  453.     pop    es        ; string move must have ES=DS
  454.     call    lookup        ; rets Z if redefined...
  455.     jnz    key_newkey
  456.     ; It's already defined.     Erase its old definition- i.e., move
  457.     ; region param_end+1..SI-1 upwards CX+4 bytes, add CX+4 to param_end.
  458.     add    cx, 4
  459.     mov    bp, param_end    ; save old value in bp...
  460.     add    param_end, cx
  461.     dec    si        ; start at (SI-1)
  462.     mov    di, si
  463.     add    di, cx        ; move to (start + CX+4)
  464.     mov    cx, si
  465.     sub    cx, bp        ; length of region old_param_end+1..start
  466.     rep    movsb
  467. key_newkey:
  468.     ; Key not redefined.  See if there's enough room to redefine it.
  469.     pop    si        ; get back pointer to redef string
  470.     pop    cx        ; get back number of bytes in redef string
  471.     mov    di, param_end    ; hi byte of new redef record, hi byte of len
  472.     sub    di, 4        ; hi byte of new data field
  473.     mov    bx, di
  474.     sub    bx, cx        ; hi byte of remaining buffer space
  475.     sub    bx, 16        ; better be at least 16 bytes room
  476.     cmp    bx, param_buffer
  477.     jb    key_popem    ; nope- forget it.
  478.     ; Nothing in the way now!
  479.     mov    [di+3], cx    ; save length field
  480.     mov    [di+1], ax    ; save name field
  481.     jcxz    key_nullstring
  482. key_saveloop:            ; save data field
  483.     movsb
  484.     add    si, 2        ; input string ascending, output descending
  485.     loop    key_saveloop
  486. key_nullstring:
  487.     mov    param_end, di    ; save adr of new hi byte of free area
  488. key_popem:
  489.     pop    es
  490.     pop    di
  491.  
  492. key_exit:
  493.     cld
  494.     ret
  495.  
  496. key_init:
  497.     ; Build the default redefinition table:
  498.     ;    control-printscreen -> control-P
  499.     push    es
  500.     push    ds
  501.     pop    es
  502.     std
  503.     mov    di, redef_end
  504.     mov    ax, 1
  505.     stosw
  506.     mov    ax, 7200h    ; control-printscreen
  507.     stosw
  508.     mov    al, 16        ; control P
  509.     stosb
  510.     mov    param_end, di    ; save new bottom of redef table
  511.     pop    es
  512.     jmp    key_exit
  513. endif
  514.  
  515.  
  516. ;---- Delete/Insert Lines -------------------------------
  517. ; AL is number of lines to delete/insert.
  518. ; Preserves DX, DI; does not move cursor.
  519.  
  520. d_l:    ; Delete lines.
  521.     mov    ah, 6            ; BIOS: scroll up
  522.     jmp    short il_open
  523.  
  524. il:    ; Insert lines.
  525.     mov    ah, 7            ; BIOS: scroll down
  526.  
  527. il_open:
  528.     ; Whether inserting or deleting, limit him to (max_y - cur_y) lines;
  529.     ; if above that, we're just clearing; set AL=0 so BIOS doesn't burp.
  530.     mov    bh, max_y
  531.     sub    bh, cur_y
  532.     cmp    al, bh
  533.     jbe    il_ok            ; DRK 9/4...
  534.         mov    al, 0        ; he tried to move too far
  535. il_ok:
  536.     push    ax
  537.     call    get_blank_attrib
  538.     mov    bh, ah            ; color to use on new blank areas
  539.     pop    ax            ; AL is number of lines to scroll.
  540.  
  541.     mov    cl, 0            ; upper-left-x of data to scroll
  542.     mov    ch, cur_y        ; upper-left-y of data to scroll
  543.     push    dx
  544.     mov    dl, max_x        ; lower-rite-x
  545.     mov    dh, max_y        ; lower-rite-y (zero based)
  546.     call_video            ; call BIOS to scroll a rectangle.
  547.     pop    dx
  548.     ret                ; done.
  549.  
  550. ;-- Insert / Delete Characters ----------------------------
  551. ; AL is number of characters to insert or delete.
  552. ; Preserves DX, DI; does not move cursor.
  553.  
  554. ic:    mov    ch, 1            ; 1 => swap dest & source below
  555.     jmp    short dc_ch
  556.  
  557. dc:    mov    ch, 0
  558.  
  559. dc_ch:
  560.     cmp    cs:gmode_flag,0
  561.     jnz    dc_ret            ; | if in graphics mode, ignore.
  562.  
  563.  
  564.     ; AL = number of chars to ins or del (guarenteed nonzero).
  565.     ; Limit him to # of chars left on line.
  566.     cmp    al, dl
  567.     jbe    dc_cok
  568.         mov    al, dl
  569. dc_cok:
  570.     push    di            ; DI is current address of cursor
  571.     xchg    ax, cx            ; CX gets # of chars to ins/del
  572.     mov    bp, cx            ; BP gets # of columns to clear.
  573.  
  574.     ; Set up source = destination + cx*2, count = dx - cx
  575.     mov    ch, 0            ; make it a word
  576.     mov    si, di
  577.     add    si, cx
  578.     add    si, cx
  579.     neg    cl
  580.     add    cl, dl
  581.     mov    ch, 0            ; CX = # of words to transfer
  582.     cld                ; REP increments si & di
  583.  
  584.     ; If this is an insert, then flip transfer around in both ways.
  585.     test    ah, 1
  586.     jz    dc_noswap
  587.         xchg    di, si        ; source <-> dest
  588.         std            ; up <-> down
  589.         mov    ax, cx        ; make move over same range
  590.         dec    ax
  591.         add    ax, ax        ; AX=dist from 1st to last byte.
  592.         add    di, ax        ; Start transfer at high end of block
  593.         add    si, ax        ;  instead of low end.
  594. dc_noswap:
  595.     ; Move those characters.
  596.     push    es
  597.     pop    ds
  598.     rep    movsw
  599.     mov    cx, bp
  600.     ; Figure out what color to make the new blanks.
  601.     call    get_blank_attrib
  602.     mov    al, ' '
  603.     ; Blank out vacated region.
  604.     rep    stosw
  605.  
  606.     ; All done.
  607.     cld                ; restore normal REP state and
  608.     pop    di            ;  cursor address.
  609. dc_ret: ret
  610.  
  611.  
  612. ;---- set / reset mode ---------------------------------------
  613. ; Sets graphics/text mode; also sets/resets "no wrap at eol" mode.
  614. ; also set/reset graphic cursor mode
  615. rm:    mov    cl, 0        ; reset
  616.     jmp    short sm_rs
  617.  
  618. sm:    mov    cl, 0ffh    ; set
  619. sm_rs:
  620.     ; Is it "wrap at eol" ?
  621.     cmp    al, 7
  622.     jnz    sm_notwrap
  623.         mov    wrap_flag, cl    ; true = wrap at EOL
  624.         ret
  625. sm_notwrap:
  626.     ; Is it set/reset graphic cursor mode?
  627.     cmp    al,99
  628.     jnz    sm_notgcursor
  629.         mov    gcursor, cl
  630.         ret
  631. sm_notgcursor:
  632.     ; Is it set/reset fast mode?
  633.     cmp    al,98
  634.     jnz    sm_notspeedy
  635.         mov    fmode, cl
  636.         cmp    cl,0        ; mode now fast?
  637.         jnz    sm_done
  638.         call    move_back
  639. sm_done:    ret
  640. sm_notspeedy:
  641.     ; we can now do 43 lines on a VGA display, if desired, as well as 50.
  642.     ; of course an EGA display will only do 43.
  643.     cmp    al, 43
  644. IF VGA
  645.     jnz    sm_not43
  646.     mov    ax, 1201H    ; set 350 lines on EGA
  647.     jmp    short is43or50
  648. sm_not43:
  649.     cmp    al,50            ; not 50 line (VGA)
  650.     jnz    sm_video        ; set to whatever it happens to be
  651.     mov    ax, 1202h        ; select 400 scan lines
  652. is43or50:
  653.     cmp    cs:gmode_flag,0        ; in a graphic mode?
  654.     jnz    sm_done            ; then quit
  655.     mov    bl,30h            ; this call ignored on EGA
  656.     call_video
  657.         
  658. ELSE
  659.     jnz    sm_video        ; set to whatever it happens to be
  660.     cmp    cs:gmode_flag,0        ; in a graphic mode?
  661.     jnz    sm_done            ; then quit
  662. ENDIF
  663.     mov    ah,0
  664.     mov    al, video_mode        ; select the video mode.
  665.     call_video
  666.         
  667.     mov    ax,1112h        ; Load 8x8 font
  668.     mov    bl,0            ; (instead of 8x14 or 8x16)
  669.     call_video
  670.  
  671.     mov    ax, 1200h        ; Load new printscreen
  672.     mov    bl, 20h
  673.     call_video
  674.  
  675. IF EGA    ; set the EGA cursor
  676.     mov    dx, port_6845        ; '6845' command reg
  677.     mov    ax, 070ah        ; start on line 7
  678.     out    dx, ax
  679.     mov    al, 0bh            ; end on line 7
  680.     out    dx, ax
  681. ENDIF
  682.     jmp    short sm_home
  683.  
  684.  
  685. sm_video:
  686.     ; It must be a video mode.  Call BIOS.
  687.     ; Save graphics mode flag
  688.     extrn    set_gmode:near
  689.     call    set_gmode    ; mode is in AL
  690. IF VGA
  691.     cmp    al, 3        ; On VGA, modes 2 or 3, set 400 scan lines
  692.     ja    no_scan_change
  693.     cmp    al, 1
  694.     jbe    no_scan_change
  695.     push    ax
  696.     mov    ax, 1202h        ; select 400 scan lines
  697.     mov    bl,30h            ; this call ignored on EGA
  698.     call_video
  699.     pop    ax
  700. no_scan_change:
  701. ENDIF    
  702.     mov    ah, 0        ; "set video mode"
  703.     or    al, 80h        ;  but don't erase screen, since colors wrong.
  704.     call_video
  705. sm_home:
  706.     ; Read the BIOS buffer address/cursor position variables.
  707.     mov    ax, ABS40
  708.     push    ds
  709.     mov    ds, ax
  710.     assume    ds:ABS40
  711.  
  712.     ; Find current video mode and screen size.
  713.     mov    ax,word ptr crt_mode    ; al = crt mode; ah = # of columns
  714.     mov    cl, ega_rows        ; cl = max row
  715.     pop    ds
  716.     assume    ds:code
  717.     mov    video_mode, al
  718.     dec    ah            ; ah = max column
  719.     mov    max_x, ah
  720.     mov    max_y, cl
  721.  
  722.     ; Since cursor may end up in illegal position, it's best to
  723.     ; just go home after switching video modes.
  724.     mov    cur_coords, 0
  725.     call    xy_to_regs
  726.  
  727.     jmp    eid_slow        ; then clear the screen
  728.  
  729. ansi_functions    endp    ; end dummy procedure block
  730.  
  731.  
  732.  
  733. ;-------- Color table -----------------------------------------
  734. ; Used in "set graphics rendition"
  735.  
  736. colors    equ    25            ; number of colors in table
  737.  
  738. color_table:
  739.     db    0, 000h,07h        ; all attribs off; normal.
  740.     db    1, 0ffh,08h        ; bold
  741.     db    2, 0f7h,00h        ; dim (not bold)
  742.     db    4, 0f8h,01h        ; underline (forces blue foreground)
  743.     db    5, 0ffh,80h        ; blink
  744. ;    db    8, 088h,00h        ; invisible    (original definition)
  745.     db    8, 080h,00h        ; invisible    (better definition)
  746.     
  747.     db    22,0f7h,00h        ; un-bold, un-dim
  748.     db    24,0f8h,7h        ; un-underline (forces white fground)
  749.     db    25,07fh,0h        ; un-blink
  750.  
  751.     db    30,0f8h,00h        ; black foreground
  752.     db    31,0f8h,04h        ; red
  753.     db    32,0f8h,02h        ; green
  754.     db    33,0f8h,06h        ; yellow
  755.     db    34,0f8h,01h        ; blue
  756.     db    35,0f8h,05h        ; magenta
  757.     db    36,0f8h,03h        ; cyan
  758.     db    37,0f8h,07h        ; white
  759.  
  760.     db    40,08fh,00h        ; black background
  761.     db    41,08fh,40h        ; red
  762.     db    42,08fh,20h        ; green
  763.     db    43,08fh,60h        ; yellow
  764.     db    44,08fh,10h        ; blue
  765.     db    45,08fh,50h        ; magenta
  766.     db    46,08fh,30h        ; cyan
  767.     db    47,08fh,70h        ; white
  768.  
  769.  
  770. code    ends
  771.     end                ; of nnansi_f.asm
  772.  
  773.