home *** CD-ROM | disk | FTP | other *** search
/ norge.freeshell.org (192.94.73.8) / 192.94.73.8.tar / 192.94.73.8 / pub / computers / pcjr / screen / ZANSI.LZH / ZANSI_F.ASM next >
Assembly Source File  |  1986-11-29  |  21KB  |  579 lines

  1. ;----- zansi_f.asm ---------------------------------------------
  2. ; Zephyr ANSI terminal driver.
  3. ;    Copyright (C) 1986, Thomas Hanlin III, Springfield VA.
  4. ;    Based on original code for NANSI by Daniel Kegel, Pasadena, CA.
  5. ;------------------------------------------------------------------------
  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.  
  19.         ; To zansi_p.asm
  20.         public  ansi_fn_table
  21.  
  22.         ; From zansi.asm
  23.         extrn   port_6845:word
  24.         extrn   cur_coords:word, saved_coords:word
  25.         extrn   cur_x:byte, max_x:byte
  26.         extrn   cur_y:byte, max_y:byte
  27.         extrn   cur_attrib:byte, wrap_flag:byte
  28.         extrn   xy_to_regs:near
  29.         extrn   get_blank_attrib:near
  30.         extrn   cpr_esc:byte, cprseq:word
  31.         extrn   video_mode:byte
  32.         extrn   lookup:near
  33.  
  34.         ; from zansi_p.asm
  35.         extrn   param_buffer:word       ; used in keyboard programming
  36.         extrn   param_end:word
  37.         extrn   redef_end:word
  38.  
  39. keybuf  struc                           ; used in making cpr sequence
  40. len     dw      ?
  41. adr     dw      ?
  42. keybuf  ends
  43.  
  44.  
  45. ABS40   segment at 40h
  46.         org     1ah
  47. buffer_head     dw      ?       ; Used in 'flush input buffer' dos call.
  48. buffer_tail     dw      ?
  49.  
  50.         org     49h
  51. crt_mode        db      ?
  52. crt_cols        dw      ?
  53. crt_len         dw      ?
  54. crt_start       dw      ?
  55. cursor_posn     dw      8 dup (?)
  56. cursor_mode     dw      ?
  57. active_page     db      ?
  58. addr_6845       dw      ?
  59. crt_mode_set    db      ?
  60. crt_palette     db      ?
  61.  
  62. ABS40   ends
  63.  
  64. code    segment byte public 'CODE'
  65.         assume cs:code, ds:code
  66.  
  67. ;----- byteout ---------------------------------------------------
  68. ; Converts al to a decimal ASCII string (in 0..99),
  69. ; stores it at ES:DI++.  Returns DI pointing at byte after last digit.
  70. ; Destroys DL.
  71.  
  72. byteout proc    near
  73.         aam
  74.         add     ax, 3030h
  75.         xchg    ah, al
  76.         stosb
  77.         xchg    ah, al
  78.         stosb
  79.         ret
  80. byteout endp
  81.  
  82. ;----- ansi_fn_table -----------------------------------
  83. ; Table of offsets of terminal control subroutines in order of
  84. ; the character that invokes them, @..Z, a..z.  Exactly 53 entries.
  85. ; All the subroutines are defined below in this module.
  86. ansi_fn_table   label   word
  87.         dw      ic,  cup, cdn, cfw, cbk         ; @, A, B, C, D
  88.         dw      nul, nul, nul, hvp, nul         ; E, F, G, H, I
  89.         dw      eid, eil, il,  d_l, nul         ; J, K, L, M, N
  90.         dw      nul, dc,  nul, nul, nul         ; O, P, Q, R, S
  91.         dw      nul, nul, nul, nul, nul         ; T, U, V, W, X
  92.         dw      nul, nul                        ; Y, Z
  93.         dw      nul, nul, nul, nul, nul         ; a, b, c, d, e
  94.         dw      hvp, nul, sm,  nul, nul         ; f, g, h, i, j
  95.         dw      nul, rm,  sgr, dsr, nul         ; k, l, m, n, o
  96.         dw      key, nul, nul, scp, nul         ; p, q, r, s, t
  97.         dw      rcp, nul, nul, nul, nul         ; u, v, w, x, y
  98.         dw      nul                             ; z
  99.  
  100. ansi_functions  proc    near            ; set return type to NEAR
  101.  
  102. ;----- nul ---------------------------------------------
  103. ; No-action ansi sequence; called when unknown command given.
  104. nul:    ret
  105.  
  106. ;----- Cursor Motion -----------------------------------------------
  107.  
  108. ;-- cursor to y,x
  109. hvp:    or      al,al           ; First parameter is desired Y coordinate.
  110.         jz      hvp_yok
  111.         dec     ax              ; Convert to zero-based coordinates.
  112. hvp_yok:mov     cur_y,al
  113.         ; Get second parameter, if it is there, and set X with it.
  114.         xor     ax,ax
  115.         cmp     cx,2            ; was there a second parameter?
  116.         jb      hvp_xok
  117.         lodsb                   ; yes.
  118.         or      al,al
  119.         jz      hvp_xok
  120.         dec     ax              ; convert to zero-based coordinates.
  121. hvp_xok:mov     cur_x,al
  122.  
  123.         ; Clip to maximum coordinates.
  124. hvp_set:
  125.         mov     ax, cur_coords          ; al = x, ah = y
  126.         cmp     al, max_x
  127.         jbe     hvp_sxok
  128.         mov     al, max_x
  129.         mov     cur_x, al
  130. hvp_sxok:
  131.         cmp     ah, max_y
  132.         jbe     hvp_syok
  133.         mov     al, max_y
  134.         mov     cur_y, al
  135. hvp_syok:
  136.         ; Set values of DX and DI accordingly.
  137.         call    xy_to_regs
  138.         ret
  139.  
  140. ;-- cursor forward --
  141. cfw:    add     cur_x, al
  142.         jmp     hvp_set
  143.  
  144. ;-- cursor back -----
  145. cbk:    sub     cur_x, al
  146.         jae     cbk_ok
  147.         mov     cur_x, 0
  148. cbk_ok: jmp     hvp_set
  149.  
  150. ;-- cursor down -----
  151. cdn:    add     cur_y, al
  152.         jmp     hvp_set
  153.  
  154. ;-- cursor up -------
  155. cup:    sub     cur_y, al
  156.         jae     cup_ok
  157.         mov     cur_y, 0
  158. cup_ok: jmp     hvp_set
  159.  
  160. ;-- save cursor position --------------------------------------
  161. scp:    mov     ax, cur_coords
  162.         mov     saved_coords, ax
  163.         ret
  164.  
  165. ;-- restore cursor position -----------------------------------
  166. rcp:    mov     ax, saved_coords
  167.         mov     cur_coords, ax
  168.         jmp     hvp_set         ; Clip in case we have switched video modes.
  169.  
  170. ;-- set graphics rendition ------------------------------------
  171. ; Modifies the color in which new characters are written.
  172.  
  173. sgr:    dec     si              ; get back pointer to first parameter
  174.         or      cx, cx          ; Did he give any parameters?
  175.         jnz     sgr_loop
  176.         mov     [si],cl         ; no parameters, so fake
  177.         inc     cx              ; one with the default value.
  178.  
  179. sgr_loop:                ; Handles each parameter
  180.         lodsb                   ; al = next parameter
  181.         push    cx
  182.         mov     cx,colors
  183.         mov     bx,offset color_table -3
  184. sgr_search:
  185.         add     bx,3
  186.         cmp     al,[bx]
  187.         loopne  sgr_search      ; until match found or done
  188.         jne     sgr_loopx
  189.  
  190.         ; If parameter named a known color, set the current color variable.
  191.         mov     bx,1[bx]
  192.         mov     al,cur_attrib
  193.         and     al,bl
  194.         or      al,bh
  195.         mov     cur_attrib,al
  196. sgr_loopx:
  197.         pop     cx
  198.         loop    sgr_loop                ; until no more parameters.
  199.         ret
  200.  
  201. ;-- erase in line ----------------------------------------
  202. ; Uses BIOS to scroll away a one-line rectangle
  203. eil:    push    dx
  204.         mov     cx, cur_coords
  205.         mov     dh, ch
  206.         jmp     short scrollem
  207.  
  208. ;-- erase in display -------------------------------------
  209. ; Uses BIOS to scroll away all of display
  210. eid:    cmp     al,2
  211.         jnz     eid_ignore      ; param must be two
  212.         xor     cx,cx
  213.         mov     cur_coords,cx
  214.         call    xy_to_regs      ; doesn't modify CX
  215.         push    dx
  216.         mov     dh,max_y
  217. scrollem:
  218.         call    get_blank_attrib
  219.         mov     bh,ah
  220.         mov     dl,max_x
  221.         mov     ax,600h
  222.         int     10h
  223.         pop     dx
  224. eid_ignore:
  225.         ret
  226.  
  227. ;-- device status report --------------------------------
  228. ; Stuffs an escape, a left bracket, current Y, semicolon, current X,
  229. ; a capital R, and a carriage return into input stream.
  230. ; The coordinates are 1 to 3 decimal digits each.
  231.  
  232. dsr:    push    di
  233.         push    dx
  234.         push    es
  235.         mov     ax,cs
  236.         mov     es,ax
  237.         std                     ; Store string in reversed order for fun
  238.         mov     di,offset cpr_esc - 2
  239.         mov     al,cur_y
  240.         inc     al              ; convert to one-based coords
  241.         call    byteout         ; row
  242.         mov     al,';'
  243.         stosb
  244.         mov     al,cur_x
  245.         inc     al              ; convert to one-based coords
  246.         call    byteout         ; column
  247.         mov     al,'R'          ; R ANSI function 'Cursor Position Report'
  248.         stosb
  249.         mov     al,13
  250.         mov     word ptr cprseq.adr, di ; save pointer to last char in string
  251.         stosb                           ; send a carriage return, too
  252.         mov     ax,offset cpr_esc
  253.         sub     ax,di                   ; ax is # of characters in string
  254.         mov     word ptr cprseq.len,ax  ; pass info to the getchar routine
  255.         cld
  256.         pop     es
  257.         pop     dx
  258.         pop     di
  259.         ret
  260.  
  261. ;-- keyboard reassignment -------------------------------
  262. ; Key reassignment buffer is between param_end and redef_end+2, exclusive.
  263. ; When it shrinks or grows, param_end is moved.
  264. ; Format of an entry is as follows:
  265. ;   highest address -> length:word (may be 0)
  266. ;                      key to replace:word     (either hi or low byte is zero)
  267. ;                          .
  268. ;                          .    new key value, "length" bytes long
  269. ;                          .
  270. ;   lowest address  -> next entry, or free space.
  271. ; If no arguments are given, keyboard is reset to default condition.
  272. ; Otherwise, first parameter (or first two, if first is zero) defines
  273. ; the key whose value is to be changed, and the following parameters
  274. ; define the key's new, possibly zero-length, value.
  275.  
  276. key:
  277.         ; Is this a reset?
  278.         jcxz    key_init
  279.         ; Get the first (or first two) parameters
  280.         cld
  281.         dec     si      ; point to first param
  282.         dec     cx      ; Assume it's a fn key, get two params
  283.         dec     cx
  284.         lodsw
  285.         or      al, al  ; Is it a function key?
  286.         jz      key_fnkey
  287.         inc     cx      ; It's not a function key- put second param back
  288.         dec     si
  289. key_fnkey:
  290.         ; Key to redefine now in AX.  If it's already redefined,
  291.         ; lookup will set Z, point SI to redef string, set CX to its length.
  292.         push    di
  293.         push    es
  294.         push    cx
  295.         push    si
  296.  
  297.         std                     ; moving up, must move from top down
  298.         push    ds
  299.         pop     es              ; string move must have ES=DS
  300.         call    lookup          ; rets Z if redefined...
  301.         jnz     key_newkey
  302.         ; It's already defined.  Erase its old definition- i.e., move
  303.         ; region param_end+1..SI-1 upwards CX+4 bytes, add CX+4 to param_end.
  304.         add     cx, 4
  305.         mov     bp, param_end   ; save old value in bp...
  306.         add     param_end, cx
  307.         dec     si              ; start at (SI-1)
  308.         mov     di, si
  309.         add     di, cx          ; move to (start + CX+4)
  310.         mov     cx, si
  311.         sub     cx, bp          ; length of region old_param_end+1..start
  312.         rep     movsb
  313. key_newkey:
  314.         ; Key not redefined.  See if there's enough room to redefine it.
  315.         pop     si              ; get back pointer to redef string
  316.         pop     cx              ; get back number of bytes in redef string
  317.         mov     di, param_end   ; hi byte of new redef record, hi byte of len
  318.         sub     di, 4           ; hi byte of new data field
  319.         mov     bx, di
  320.         sub     bx, cx          ; hi byte of remaining buffer space
  321.         sub     bx, 16          ; better be at least 16 bytes room
  322.         cmp     bx, param_buffer
  323.         jb      key_popem       ; nope- forget it.
  324.         ; Nothing in the way now!
  325.         mov     [di+3], cx      ; save length field
  326.         mov     [di+1], ax      ; save name field
  327.         jcxz    key_nullstring
  328. key_saveloop:                   ; save data field
  329.         movsb
  330.         add     si, 2           ; input string ascending, output descending
  331.         loop    key_saveloop
  332. key_nullstring:
  333.         mov     param_end, di   ; save adr of new hi byte of free area
  334. key_popem:
  335.         pop     es
  336.         pop     di
  337.  
  338. key_exit:
  339.         cld
  340.         ret
  341.  
  342. key_init:
  343.         ; Build the default redefinition table:
  344.         ;       control-printscreen -> control-P
  345.         push    es
  346.         push    ds
  347.         pop     es
  348.         std
  349.         mov     di, redef_end
  350.         mov     ax, 1
  351.         stosw
  352.         mov     ax, 7200h       ; control-printscreen
  353.         stosw
  354.         mov     al, 16          ; control P
  355.         stosb
  356.         mov     param_end, di   ; save new bottom of redef table
  357.         pop     es
  358.         jmp     key_exit
  359.  
  360. ;---- Delete/Insert Lines -------------------------------
  361. ; AL is number of lines to delete/insert.
  362. ; Preserves DX, DI; does not move cursor.
  363.  
  364. d_l:    ; Delete lines.
  365.         mov     ah, 6                   ; BIOS: scroll up
  366.         jmp     short il_open
  367.  
  368. il:     ; Insert lines.
  369.         mov     ah, 7                   ; BIOS: scroll down
  370.  
  371. il_open:
  372.         ; Whether inserting or deleting, limit him to (max_y - cur_y) lines;
  373.         ; if above that, we're just clearing; set AL=0 so BIOS doesn't burp.
  374.         mov     bh, max_y
  375.         sub     bh, cur_y
  376.         cmp     al, bh
  377.         jbe     il_ok                   ; DRK 9/4...
  378.         xor     al,al           ; he tried to move too far
  379. il_ok:
  380.         push    ax
  381.         call    get_blank_attrib
  382.         mov     bh, ah                  ; color to use on new blank areas
  383.         pop     ax                      ; AL is number of lines to scroll.
  384.  
  385.         xor     cl,cl                   ; upper-left-x of data to scroll
  386.         mov     ch, cur_y               ; upper-left-y of data to scroll
  387.         push    dx
  388.         mov     dl, max_x               ; lower-right-x
  389.         mov     dh, max_y               ; lower-right-y (zero based)
  390.         int     10h                     ; call BIOS to scroll a rectangle.
  391.         pop     dx
  392.         ret                             ; done.
  393.  
  394. ;-- Insert / Delete Characters ----------------------------
  395. ; AL is number of characters to insert or delete.
  396. ; Preserves DX, DI; does not move cursor.
  397.  
  398. ic:     mov     ch, 1                   ; 1 => swap dest & source below
  399.         jmp     short dc_ch
  400.  
  401. dc:     xor     cl,cl
  402.  
  403. dc_ch:
  404.         cmp     cs:video_mode, 4
  405.         jb      DC_CH_DO
  406.         cmp     cs:video_mode, 7
  407.         jnz     dc_ret                  ; | if in graphics mode, ignore.
  408. DC_CH_DO:
  409.         ; AL = number of chars to ins or del (guarenteed nonzero).
  410.         ; Limit him to # of chars left on line.
  411.         cmp     al, dl
  412.         jbe     dc_cok
  413.         mov     al, dl
  414. dc_cok:
  415.         push    di                      ; DI is current address of cursor
  416.         xchg    ax, cx                  ; CX gets # of chars to ins/del
  417.         mov     bp, cx                  ; BP gets # of columns to clear.
  418.  
  419.         ; Set up source = destination + cx*2, count = dx - cx
  420.         xor     ch,ch                   ; make it a word
  421.         mov     si, di
  422.         add     si, cx
  423.         add     si, cx
  424.         neg     cl
  425.         add     cl, dl
  426.         xor     ch,ch                   ; CX = # of words to transfer
  427.         cld                             ; REP increments si & di
  428.  
  429.         ; If this is an insert, then flip transfer around in both ways.
  430.         test    ah, 1
  431.         jz      dc_noswap
  432.         xchg    di,si           ; source <-> dest
  433.         std                     ; up <-> down
  434.         mov     ax,cx           ; make move over same range
  435.         dec     ax
  436.         shl     ax,1            ; AX=dist from 1st to last byte.
  437.         add     di,ax           ; Start transfer at high end of block
  438.         add     si,ax           ;  instead of low end.
  439. dc_noswap:
  440.         ; Move those characters.
  441.         push    es
  442.         pop     ds
  443.         rep     movsw
  444.         mov     cx,bp
  445.         ; Figure out what color to make the new blanks.
  446.         call    get_blank_attrib
  447.         mov     al,' '
  448.         ; Blank out vacated region.
  449.         rep     stosw
  450.  
  451.         ; All done.
  452.         cld                             ; restore normal REP state and
  453.         pop     di                      ;  cursor address.
  454. dc_ret: ret
  455.  
  456.  
  457. ;---- set / reset mode ---------------------------------------
  458. ; Sets graphics/text mode; also sets/resets "no wrap at eol" mode.
  459. sm:     mov     cl, 0ffh        ; set
  460. sm_rs:
  461.         ; Is it "wrap at eol" ?
  462.         cmp     al,7
  463.         jnz     sm_notwrap
  464.         mov     wrap_flag, cl   ; true = wrap at EOL
  465.         ret
  466. sm_notwrap:
  467.         ; Is it "set highest number of screen lines available"?
  468.         cmp     al, 43
  469.         jnz     sm_video
  470.         ; Only valid for the Enhanced Graphics Adaptor on
  471.         ; a monochrome display or an enhanced color display.
  472.         ; Test presence of EGA by calling BIOS fn 12h.10h.
  473.         mov     ah, 12h
  474.         mov     bx, 0ff10h
  475.         int     10h                     ; bh=0-1, bl=0-3 if EGA
  476.         test    bx, 0FEFCH
  477.         jnz     sm_done                 ; sorry, charlie
  478.         ; 43 line mode only allowed in text modes, for now.
  479.         cmp     cs:video_mode, 4
  480.         jb      DO_43L
  481.         cmp     cs:video_mode, 7
  482.         jnz     sm_done
  483.  
  484. DO_43L:
  485.         xor     ah,ah                   ; "Set video mode"
  486.         mov     al, video_mode          ; Re-init current mode
  487.         int     10h
  488.  
  489.         mov     ax,1112h                ; Load 8x8 font
  490.         xor     bl,bl                   ; (instead of 8x14)
  491.         int     10h
  492.  
  493.         mov     ax, 1200h               ; Load new printscreen
  494.         mov     bl,20h
  495.         int     10h
  496.  
  497.         mov     ah,1
  498.         mov     cx,0707h                ; (Load cursor scan lines)
  499.         int     10h
  500.         ; | Patch; this gotten by painful observation of
  501.         ; | IBM's professional editor.  I think there's a
  502.         ; | documented bug in Video Bios's "load cursor scan line"
  503.         ; | call; try looking in latter 1985 PC Tech Journal.
  504.         mov     dx, port_6845           ; '6845' command reg
  505.         mov     al, 10
  506.         out     dx, al
  507.         inc     dx
  508.         mov     al, 7
  509.         out     dx, al                  ; set cursor start line
  510.         ; Assume that gets us 43 lines.
  511.         mov     max_y, 42
  512.         jmp     short sm_home
  513. sm_video:
  514.         ; It must be a video mode.  Call BIOS.
  515.         xor     ah,ah           ; "set video mode"
  516.         int     10h
  517.         ; Assume that gets us 25 lines.
  518.         mov     max_y,24
  519. sm_home:
  520.         ; Read the BIOS buffer address/cursor position variables.
  521.         mov     ax,abs40
  522.         push    ds
  523.         mov     ds,ax
  524.         assume  ds:abs40
  525.         ; Find current video mode and screen size.
  526.         mov     ax,word ptr crt_mode    ; al = crt mode; ah = # of columns
  527.         pop     ds
  528.         mov     video_mode,al
  529.         dec     ah                      ; ah = max column
  530.         mov     max_x,ah
  531.  
  532.         ; Since cursor may end up in illegal position, it's best to
  533.         ; just go home after switching video modes.
  534.         mov     cur_coords,0
  535.         call    xy_to_regs
  536. sm_done:
  537.         ret
  538.  
  539. rm:     xor     cl,cl           ; reset
  540.         jmp     sm_rs
  541.  
  542.  
  543. ansi_functions  endp    ; end dummy procedure block
  544.  
  545.  
  546.  
  547. ;-------- Color table -----------------------------------------
  548. ; Used in "set graphics rendition"
  549. colors  equ     22                      ; number of colors in table
  550. color_table:
  551.         db      0, 000h,07h             ; all attribs off; normal.
  552.         db      1, 0ffh,08h             ; bold
  553.         db      4, 0f8h,01h             ; underline
  554.         db      5, 0ffh,80h             ; blink
  555.         db      7, 0f8h,70h             ; reverse
  556.         db      8, 088h,00h             ; invisible
  557.  
  558.         db      30,0f8h,00h             ; black foreground
  559.         db      31,0f8h,04h             ; red
  560.         db      32,0f8h,02h             ; green
  561.         db      33,0f8h,06h             ; yellow
  562.         db      34,0f8h,01h             ; blue
  563.         db      35,0f8h,05h             ; magenta
  564.         db      36,0f8h,03h             ; cyan
  565.         db      37,0f8h,07h             ; white
  566.  
  567.         db      40,08fh,00h             ; black background
  568.         db      41,08fh,40h             ; red
  569.         db      42,08fh,20h             ; green
  570.         db      43,08fh,60h             ; yellow
  571.         db      44,08fh,10h             ; blue
  572.         db      45,08fh,50h             ; magenta
  573.         db      46,08fh,30h             ; cyan
  574.         db      47,08fh,70h             ; white
  575.  
  576.  
  577. code    ends
  578.         end
  579.