home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0010 - 0019 / ibm0010-0019 / ibm0010.tar / ibm0010 / CDOSDSK5.ZIP / CDOSDSK5.TD0 / XIOS / PCTERM.A86 < prev    next >
Encoding:
Text File  |  1989-01-26  |  149.3 KB  |  5,795 lines

  1. ; PCTERM.A86
  2. title 'XIOS PC terminal emulator'
  3. pagesize 60+11
  4. ;********************************************************
  5. ;*                            *
  6. ;*     XIOS SERIAL CONSOLE PC TERMINAL EMULATOR     *
  7. ;*        CDOS 386 XIOS                *
  8. ;*                            *
  9. ;********************************************************
  10.  
  11. ; modifications
  12. ; V3.0
  13. ; 26 JAN 89 -- INT 10h char write goes straight to terminal    GMS
  14. ; 12 JAN 89 -- Set write protect on screen memory for IDLE    GMS
  15. ; 12 Dec 88 -- block ESC printer output                GMS
  16. ; 24 Nov 88 -- save ROS values during flush init        GMS
  17. ; 23 Nov 88 -- allow invisble attribute                GMS
  18. ; 22 Nov 88 -- Allow enhanced DEL_SCAN through GERMAN etc    GMS
  19. ; 21 Nov 88 -- Calls Statline.A86 for statline related calls    IJ
  20. ; 18 Nov 88 -- Dead key fix                    GMS
  21. ; 17 Nov 88 -- PCTerminal printers - return AH status too    IJ
  22. ; 16 Nov 88 -- correct local NUMLOCK state on arrow keys    IJ
  23. ;  8 Nov 88 -- map_top restores MONO+COLOR Screen/CRT ports    IJ
  24. ; 21 Oct 88 -- allow modes 2/3, CtrlAltF10 clears lock bits    IJ
  25. ; 10 OCT 88 -- allow CRTL/ALT dead keys                GMS
  26. ;  5 Oct 88 -- bug fixes for beta                IJ
  27. ;  3 Oct 88 -- int 10/9 null character check as per flush    IJ
  28. ; 29 Sep 88 -- fix bug when mixing Dumb/PC terminals        IJ
  29. ; 21 SEP 88 -- equates moved to PTERM.EQU            GMS
  30. ; 21 SEP 88 -- Exception handler code moved to V386.A86        GMS
  31. ; 19 SEP 88 -- Get all MX's on io_switch            GMS
  32. ; 25 AUG 88 -- Support background screen writes            GMS
  33. ; 12 Jul 88 -- Support for Aux/Printer port on Wyse        IJ
  34. ;  5 Jul 88 -- Ros cursor/mode support                IJ
  35. ; 22 JUN 88 -- fix for FRENCH & GERMAN enhanced keyboards    GMS
  36. ;  8 JUN 88 -- ctrl numpad scan code corrected            GMS
  37. ;
  38. ; 11 JAN 88 -- save_equip moved to pubdata            GMS
  39. ; 17 DEC 87 -- use PC2PORT_TABLE for port mapping        JW
  40. ; 18 NOV 87 -- test both bits for beeper            GMS
  41. ; 12 NOV 87 -- save ROS keyboard buffer on dispatch        GMS
  42. ; 11 NOV 87 -- Bug fix for national enhanced keyboards        GMS
  43. ; 10 NOV 87 -- always return 0fxh on reads from status port    GMS
  44. ;  9 NOV 87 -- return scan code for INSERT key            GMS
  45. ;  3 NOV 87 -- bug fix National keyboard support        GMS
  46. ;  3 NOV 87 -- ignore CTRL NUMLOCK i.e. PAUSE key        GMS
  47.  
  48. nolist
  49. include CDOS.EQU
  50. include XIOS.EQU
  51. include PCHW.EQU
  52. include ASCII.EQU
  53. include ROSDATA.EQU
  54. include NAT.EQU
  55. include PTERM.EQU
  56. list
  57. ; These have been included:
  58. ; include CDOS.EQU
  59. ; include XIOS.EQU
  60. ; include PCHW.EQU
  61. ; include ASCII.EQU
  62. ; include ROSDATA.EQU
  63. ; include NAT.EQU
  64. ; include PTERM.EQU
  65.  
  66.  
  67.  
  68.         CodeMacro    FLUSH_TLB
  69.         db    0FH
  70.         dw    0D822H        ; magic "flush TLB" command
  71.         EndM
  72.  
  73.         CodeMacro    OP_32
  74.         DB    66h
  75.         EndM
  76.  
  77. ; Stack frame for main pointers save area
  78. CON_number    equ    word ptr 4[bp]    ; Physical/virtual console numbers
  79. VC_pointer    equ    word ptr 2[bp]    ; VC_ structure pointer
  80. PC_pointer    equ    word ptr 0[bp]    ; PC_ structure pointer
  81.  
  82. ; System equates
  83. BDOS        equ    224
  84.  
  85. ; Local equates
  86.  
  87. MAX_VIR_CONS    equ    NUM_VIR_CONS + (NUM_AUX_PORTS*2)
  88.  
  89. IO_CONIN    equ    1
  90. IO_CONOUT    equ    2
  91. IO_LISTST    equ    3
  92. IO_LIST        equ    4
  93. IO_SWITCH    equ    7
  94. IO_STATLINE    equ    8
  95. PC_KBD        equ    32
  96. PC_SHIFTS    equ    33
  97. IO_DEVIO    equ    39
  98.  
  99. DELAY_COUNT    equ    10        ; tick delay count (get from SETUP ?)
  100.  
  101. CLNOFF        equ    1000h    ; offset of clean page
  102. IMGOFF        equ    4000h    ; offset of physical image
  103.  
  104. CRT_FULL    equ    100h * (CRT_ROWS_C - 1) + (CRT_COLS - 1)
  105.  
  106. CRT_SEG        equ    0B000h        ; monochrome display RAM
  107.  
  108. PG_ATTR        equ    es:byte ptr 0[di]
  109. PGA_DIRTY    equ    40h
  110. PGA_RW        equ    02h        ; write protect bit
  111.  
  112.  
  113.  
  114. eject
  115.  
  116. CGROUP    group    PCTERM_CODE
  117. DGROUP    group    PCTERM_DATA
  118.  
  119. PCTERM_CODE    cseg
  120.  
  121. public    io_flush_io@, pc_point_curs@, point_vc@, point_pc1@, test_pcterm@
  122. public    test_pcterm_printer@, print_lastchar@
  123. extrn    flagwait@: near                    ; in HEADER.A86
  124. extrn    proc_abort@:near                ; in WINDOWS1.A86
  125. extrn    sysdat$     :word
  126. public    get_kbd_flags@                    ; for KEYBOARD.A86
  127. extrn    update_vs_cursor_from_ros@: near        ; in PCVIDEO.A86
  128. extrn    point_vs@ :near                    ; in WINDOWS2.A86
  129. extrn    conout_serial_stat@ :near            ; in LISTAUX.A86
  130.  
  131. extrn    z_sl_off@ :near                    ; in STATLINE.A86
  132. extrn    z_sl_mono@ :near
  133. extrn    z_clk_off@ :near
  134. extrn    z_clk_on@ :near
  135.  
  136.     dseg
  137. public    active_vc$
  138. public    pc_kbd_save$
  139. extrn    next_flag$     :byte                ; in HEADER.A86
  140. extrn    func_tbl$    :word
  141. extrn    su_pfk_tbl$    :byte
  142. extrn    su_mu_vs$     :byte, mu_com_type$:byte
  143. extrn    ccb_list$    :word                ; in PUBDATA.A86
  144. extrn    save_equip$    :word, win_sized$ :byte
  145. extrn    sl_pc_flag$    :byte
  146. extrn    sl_crt_flag$    :byte
  147. extrn    save_kbdata$    :word                ; in KEYBOARD.A86
  148. extrn    kbd_imhere$    :byte
  149. extrn    switch_bits$    :byte
  150. extrn    pfk_code_tbl$    :byte                ; in CONIN.A86
  151. extrn    pfk_scan_list$    :word
  152. extrn    PFK_SCAN_LIST_SIZE :abs
  153. extrn    pc2port_table$:byte                ; in LISTAUX.A86
  154. extrn    port2pc_table$:byte                ; in LISTAUX.A86
  155.  
  156. extrn    NX_language$ :byte,    NX_kbd_type$ :byte    ; in NATDATA.A86
  157. extrn    NX_natnlmode$ :byte, NX_natnlstat$ :byte 
  158. extrn    NX_dead_key$ :byte, NX_ncasetbl$ :byte
  159. extrn    NX_n7to8tbl$ :byte, NX_n7to8chr$ :byte
  160. extrn   NX_deadtable$: word, NX_alt_table$ :byte, NX_dead_ascii$: word
  161. extrn    NX_alt_chars$: byte, NX_mode_table$ :byte
  162. extrn    NX_dkeyv$ :word, NX_dkeyx$ :word
  163. extrn    NX_last_dkey$ :word, NX_dkey_buff$ :byte
  164. extrn    NX_nasciitable$ :word, NX_nshifttable$ :word, NX_nctrltable$ :word
  165. extrn   NX_ctrlalt$ :word, NX_ctrlalt_shft$ :word
  166. extrn    NX_pc_ascii$ :word, NX_pc_shift$ :word, NX_pc_ctrl$ :word
  167. extrn    NX_pc_dead$ :word
  168. extrn    top_screen$ :byte            ; in WINDOWS3.A86
  169. extrn    video$ :byte                ; in WINDOWS1.A86
  170.  
  171. eject
  172.  
  173. PCTERM_CODE    cseg
  174.  
  175. ; Kill the Flush process if no PCTERM's SETUP
  176. kill_flush:
  177.  
  178.     sti
  179.     mov    bx,rlr$                ; terminate the running process
  180.     and    P_FLAG[bx],not (PF_KEEP + PF_TEMPKEEP)
  181.     mov    cx,P_TERM
  182.     mov    dx,0FFFFh
  183.     call    supif@                ; process is terminated
  184.     jmps    kill_flush
  185.  
  186.  
  187. supif@:
  188. ;------
  189.     push es
  190.     mov    bx,.68h
  191.     mov    es,10h[bx]
  192.     callf    dword ptr .0000h
  193.     pop    es
  194.     ret
  195.  
  196.  
  197. ; FLUSH PROCESS ENTRY - entered from flush process
  198. ; Entry :
  199. ;    DL = virtual console number
  200. ;    DS = sysdat
  201. ;
  202. io_flush_io@:
  203. ;------------
  204.     cli
  205.     mov    al,0ffh
  206.     xchg    al,intercept_install
  207.     test    al,0ffh
  208.     jnz    io_flush_io1        ; been here before
  209.     mov    bx,offset func_tbl$    ; pointer to XIOS function table
  210.     mov     si,offset xios_tbl    ; pointer to local entries
  211.     mov    cx,NUM_FUNCS        ; number of XIOS functions to install
  212. setup_entries:            ; install into XIOS entry table
  213.     mov    di,[si]            ; get function number
  214.     inc si ! inc si
  215.     mov    ax,cs:[bx+di]        ; get original
  216.     xchg    ax,[si]            ; swap
  217.     mov    cs:[bx+di],ax        ; store new
  218.     inc si ! inc si
  219.     loop    setup_entries
  220.  
  221.     mov    di,00D4h            ; dispatcher intercept
  222.     mov    0[di],offset disp_inter
  223.     mov    2[di],cs
  224.  
  225.     mov    al,sl_pc_flag$
  226.     mov    ah,sl_crt_flag$
  227.     mov    save_sl_flags,ax    ; save status line flags
  228.     mov    ax,PC_SEGMENT        ; point at ROS data
  229.     mov    es,ax
  230.     mov    al,es:crt_mode_40    ; save some state of PC terminal
  231.     mov    save_mode,al
  232.     mov    ax,es:crt_cols_40
  233.     mov    save_cols,al
  234.     mov    ax,es:cursor_posn_40    ; save cursor position
  235.     mov    save_cursor,ax
  236.     mov    ax,es:addr_6845_40    ; save CRT controller values
  237.     mov    save_6845,ax
  238.  
  239.  
  240. io_flush_io1:
  241.     cmp    npcons$,1
  242.     jne    io_flush_io2
  243.     jmp    kill_flush        ; no serial consoles
  244. io_flush_io2:
  245.     push    dx            ; save vs
  246.     call    get_ccb            ; di -> ccb
  247.     mov    dl,C_PC[di]        ; logical console number
  248.     call    test_pcterm@        ; test if emulation required
  249.     pop    dx
  250.     jnz    io_flush_cont
  251.     jmp    kill_flush        ; no PC emulation.. kill process
  252.  
  253. io_flush_cont:
  254.     call    point_vc@
  255.     and    VC_MODE,not MATCH_BIT    ; make top screen
  256.     call    point_pc        ; point to PC_ structure
  257.     mov    PC_TOP_SCREEN,dl    ; make us top
  258.     push    dx            ; save virtual/physical console number
  259.     push    bx            ; save VC_ pointer
  260.     push    si            ; save PC_ pointer
  261.     mov    bp,sp
  262.     call    esc_init        ; initilise escape handler
  263.     call    io_flush_init        ; initialise the flush routine
  264.  
  265. ; wait to be woken up
  266. io_flush_wait:
  267.     push    bp
  268.     mov    dx,DELAY_COUNT        ; wake up 6 times a second
  269.     mov    cl,P_DELAY
  270.     int    BDOS            ; Note:  we run at priority 196
  271.     pop    bp
  272.  
  273.     mov    bx,rlr$
  274.     mov    dl,P_CONS[bx]        ; get Flush process VC number may have
  275.     call    point_vc@        ; been changed by IO_SWITCH.
  276.     test    VC_UPDATE,UPDATE_SL    ; if so we update the status line
  277.      je    io_flush1
  278.     and    VC_UPDATE,not UPDATE_SL    ; we will do the update
  279.     pusha
  280.     call    get_ccb            ; get the CCB
  281.     mov    dl,C_PC[di]        ; hence the PCon number
  282.     xor    cx,cx            ; normal statline call
  283.     call    fl_io_statline        ; force statline update
  284.     popa
  285. io_flush1:
  286.     mov    VC_pointer,bx        ; save current VC-> in stack frame
  287. ; test if screen write occurred
  288.     mov    bx,v386_ptr$        ; get pointer to 386 specific table
  289.     mov    es,ptbl_seg        ; get page table segment
  290.     mov    di,(CRT_SEG/256*4)    ; get entry for screen segment
  291.     test    PG_ATTR,PGA_DIRTY    ; test if screen is clean
  292.      jz    flush_cursor        ; update physical cursor
  293.      call    flush_screen        ; update dirty screen
  294.     jmps    io_flush_wait        ; and return to sleep
  295.  
  296.  
  297. ; Update physical cursor if required
  298. flush_cursor:
  299.     mov    bx,VC_pointer        ; BX -> VC_ screen structure
  300.     mov    si,PC_pointer        ; SI -> PC_ screen structure
  301.     call    ser_mx            ; output mutual exclusion
  302.     test    VC_MODE,BEL_BIT
  303.     jz    no_bel
  304.     and    VC_MODE,not BEL_BIT
  305.     mov    al,BEL            ; output BELL
  306.     call    tmp_write
  307. no_bel:
  308.     test    VC_MODE,UPDATE_BIT    ; cursor on/off mode update
  309.     jz    no_update
  310.     and    VC_MODE,not UPDATE_BIT    ; reset update bit
  311.     test    VC_MODE,CURSOR_BIT
  312.     jz    update_off
  313.     mov    di,offset cur_on_seq
  314.     call    ser_write        ; make sure cursor turned on
  315.     jmps    no_update
  316. update_off:
  317.     mov    di,offset cur_off_seq
  318.     call    ser_write        ; or off
  319. no_update:
  320.     mov    ax,VC_CURSOR        ; get virtual cursor
  321.     call    set_pcursor        ; set physical cursor address
  322.     mov    PC_BUSY,0        ; release terminal
  323.     jmp    io_flush_wait        ;   and try again later
  324.  
  325.  
  326. ; Update the physical screen
  327. flush_screen:
  328.     and    PG_ATTR,not PGA_DIRTY    ; mark page as clean
  329.  
  330.     sub    si,si            ; start at the beginning
  331. scan_for_change:
  332.     mov    cx,CRT_ROWS_P*CRT_COLS    ; total screen size
  333.     mov    ax,si            ; AX = offset in buffer
  334.     shr    ax,1            ; AX = character count
  335.     sub    cx,ax            ; CX = characters remaining
  336.      jbe    flush_done        ; everything flushed
  337.     lea    di,IMGOFF[si]        ; DI = image address
  338.     mov    ax,CRT_SEG
  339.     mov    es,ax            ; ES:SI -> virtual screen
  340.     push    ds
  341.     mov    ds,ax            ; ES:DI -> physical image
  342.     repe    cmpsw            ; skip all matching data
  343.     pop    ds
  344.      je    flush_done
  345.     dec    si ! dec si        ; ES:SI -> screen buffer
  346.     lea    di,IMGOFF[si]        ; ES:DI -> image buffer
  347.     mov    ax,si
  348.     shr    ax,1            ; make it character index
  349.     mov    dl,CRT_COLS
  350.     div    dl
  351.     xchg    al,ah            ; AL = col, AH = row
  352.     xchg    ax,cx            ; CX = cursor
  353.     lods    es:ax            ; AX = character from image
  354.     scasw                ; compare with image
  355.      je    scan_for_change        ; scan further if match
  356.     mov    es:0-2[di],ax        ; update the image
  357.  
  358.     push    si            ; save image offset
  359.  
  360.     push    ax
  361.     mov    si,PC_pointer        ; PC_ ->
  362.     mov    bx,VC_pointer        ; BX -> VC_ screen structure
  363.     call    ser_mx            ; get serial semaphore
  364.     xchg    ax,cx            ; AX = cursor
  365.     call    set_pcursor        ; update physical cursor
  366.     pop    ax ! push ax
  367.     call    set_pattrib        ; set physical attribute
  368.     pop    ax
  369.     cmp    al,' '            ; check if character large enough
  370.      jae    go_ahead        ; go ahead if printable
  371.  
  372. if 0                    ; if 1: remap control codes to ASCII
  373.     push    bx
  374.     mov    bx,offset ctrl_xlat    ; else translate to ASCII
  375.     xlat    ctrl_xlat
  376.     pop    bx
  377. else                    ; this works on the Wyse 60:
  378.     cmp    al,00            ; if zero then display a space
  379.     jne    disp_ctrl
  380.     mov    al,' '
  381.     jmps    go_ahead
  382. disp_ctrl:
  383.     push    ax            ; convert 'xxH' to '1BH, xxH'
  384.     mov    al,ESC            ;   for terminal to recognize
  385.     mov    si,PC_pointer        ; PC_ ->
  386.     call    tmp_write        ;   sequence as illegal and to
  387.     pop    ax            ;   display the control code.
  388. endif
  389.  
  390. go_ahead:
  391.     mov    si,PC_pointer        ; PC_ ->
  392.     call    tmp_write        ; write out one character
  393.     inc    PC_CURCOL
  394.     mov    PC_BUSY,0        ; release serial semaphore
  395.  
  396.     pop    si            ; restore image offset
  397.     jmp    scan_for_change        ; scan for difference
  398.  
  399. flush_done:
  400.     mov    bx,v386_ptr$        ; get pointer to 386 specific table
  401.     mov    es,ptbl_seg        ; get page table segment
  402.     mov    di,(CRT_SEG/256)*4    ; get entry for screen segment
  403.     test    PG_ATTR,PGA_DIRTY    ; clean ?
  404.     jz    flush_ret
  405.     jmp    flush_screen        ; no do it again    
  406. flush_ret:
  407.     ret
  408.  
  409.  
  410. eject
  411.  
  412. ;    INIT
  413. ;    ----
  414.  
  415. ; Initilise all data structures and buffers
  416. ; Entry:
  417. ;    DL = virtual console number
  418. ;    DH = physical console number
  419. ;    SI =  -> pc_ structure
  420. io_flush_init:
  421. ;-------------
  422.     
  423.     cli                ; protect ourself against a dispatch
  424.     mov    al,0ffh
  425.     xchg    al,flush_install    ; has flush process been installed
  426.     test    al,0ffh
  427.     jz    alloc_mem
  428.     jmp    flush_installed        ; yes continue
  429.  
  430. ; Allocate memory for ALL virtual images
  431. alloc_mem:
  432.     mov    bx,v386_ptr$        ; get pointer to 386 specific table
  433.     mov    cx,npages        ; get number of pages
  434.     mov    es,mp_table
  435.     mov    si,offset mp_table_entries ; save area for memory allocs
  436.     mov    di,cx
  437.     shl    di,1            ; pointer to top of mp_table
  438.     sub    di,2            ; for backwards search
  439.     mov    al,nvcons$        ; total virtual consoles
  440.     sub    al,NUM_VIR_CONS        ; less master terminal
  441.     mov    ah,npcons$        ; total physical
  442.     dec    ah            ; less main console
  443.     add    al,ah
  444.     xor    ah,ah            ; AX = total 4k blocks required
  445.     mov    dl,4            ; calculate number of 16k blocks
  446.     div    dl            ; required
  447.     or    ah,ah            ; remainder ?
  448.     jz    init1
  449.     inc    al            ; extra 16k
  450. init1:
  451.     mov    dl,al            ; DL = no. 16k blocks
  452.  
  453. find_free_mem:
  454.     sub    ax,ax
  455.     std                ; scan from top of MP_TABLE
  456.     repne    scasw            ; for free 16k block
  457.     jz    got_mem
  458.     jmp    no_memory        ; no free mem
  459. got_mem:
  460.     push    di            ; save current position
  461.     push dx ! push cx        ; and counts
  462.     cld
  463.     add    di,2            ; point at free block
  464.     mov    es:word ptr[di],0ffffh    ; reserve it
  465.     shr    di,1
  466.     mov    ax,16*1024        ; size of one block
  467.     mul    di
  468.     or    al,7            ; set PRESENT,U/S and R/W bits
  469.     mov    cx,4            ; store 4 4k entries
  470.  
  471. save_mp_entries:
  472.     mov    [si],ax            ; store ax and dx
  473.     inc si ! inc si
  474.     mov    [si],dx
  475.     inc si ! inc si
  476.     add    ax,4096            ; next 4k block base address
  477.     adc    dx,0
  478.     loop    save_mp_entries
  479.     
  480.     pop cx ! pop dx            ; current counters
  481.     pop    di            ; mp_table pointer
  482.     dec    dl            ; number of 16k pages required
  483.     jnz    find_free_mem        ; get next 16k
  484.  
  485. ;
  486. ; install INT 10h entry 
  487.  
  488.     sub    di,di
  489.     mov    es,di
  490.     mov    ax,es:40h[di]        ; take over Interrupt 10h vector
  491.     mov    int10_off,ax
  492.     mov    ax,es:42h[di]
  493.     mov    int10_seg,ax
  494.     mov    es:40h[di],offset video_int
  495.     mov    es:42h[di],cs
  496.  
  497.  
  498.  
  499. ; INIT entry for every FLUSH process
  500.  
  501. flush_installed:
  502.     
  503.     push ds ! pop es
  504.     mov    bx,VC_pointer        ; current top screen
  505.     lea    di,VC_PAGE_SAVE        ; virtual screens save area
  506.     mov    si,mp_entry_ptr        ; pointer to next free 4k block
  507.  
  508.     lodsw                ; get first part of dword address
  509.     stosw                ; and save in VC_
  510.     xchg    ax,dx
  511.     lodsw                ; second part of dword address
  512.     stosw                ; and save in VC_
  513.     xchg    ax,dx            ; save same adress again for CLEAN page
  514.     stosw
  515.     xchg    ax,dx
  516.     stosw
  517.     
  518.     mov    cx,si            ; save current pointer for use 
  519.                     ; by second VC if exists
  520.     lodsw                ; get next 4k block address
  521.     stosw                ; for physical screen image
  522.     lodsw                ; and save in VC_
  523.     stosw
  524.     mov    mp_entry_ptr,si        ; update current pointer
  525.     
  526.     mov    dx,CON_number        ; get top vc number
  527.     xor    dh,dh
  528.     mov    di,dx
  529.     shl    di,1
  530.     mov    di,ccb_list$[di]    ; get CCB pointer
  531.     mov    di,C_LINK[di]        ; link to next
  532.     or    di,di
  533.     jz    no_more_vc        ; no more virtual consoles
  534.     
  535.     mov    dl,C_VC[di]        ; get next virtual console number
  536.     call    point_vc@        ;  and VC->
  537.     lea    di,VC_PAGE_SAVE        ; point to save area
  538.     
  539.     lodsw                ; next free 4k block address
  540.     stosw
  541.     xchg    ax,dx
  542.     lodsw
  543.     stosw
  544.     xchg    ax,dx
  545.     
  546.     stosw                ; store twice for CLEAN page
  547.     xchg    ax,dx
  548.     stosw
  549.     mov    mp_entry_ptr,si        ; update pointer to free blocks
  550.     mov    si,cx            ; get pointer to physical image block
  551.     lodsw
  552.     stosw                ; and store for second VC_
  553.     lodsw
  554.     stosw
  555.                 ; map in second vc area to clear images
  556.     push    bx
  557.     lea    si,VC_PAGE_SAVE        ; page save area for VC
  558.     mov    bx,v386_ptr$        ; get pointer to 386 specific table
  559.     mov    es,ptbl_seg        ; now enable page table for us
  560.     mov    di,(CRT_SEG/100h)*4
  561.     mov    cx,2*2
  562.     rep    movsw
  563.     add    di,4*2            ; physical image offset
  564.     mov    cx,1*2
  565.     rep    movsw
  566.  
  567.     FLUSH_TLB            ; discard TLB cache
  568.  
  569.     mov    ax,CRT_SEG
  570.     mov    es,ax
  571.     mov    cx,2*2048        ; clear two images
  572.     mov    ax,7*256+' '        ;   to all spaces
  573.     sub    di,di            ;
  574.     rep    stosw
  575.     pop    bx            ; get VC->
  576.     mov    VC_INSTALLED,0ffh    ; and enable VC output
  577.  
  578. no_more_vc:
  579.                 ; map in top screen images
  580.     mov    bx,VC_pointer        ; get top screen VC_ in BX
  581.     lea    si,VC_PAGE_SAVE        ; page save area for VC
  582.     mov    bx,v386_ptr$        ; get pointer to 386 specific table
  583.     mov    es,ptbl_seg        ; now enable page table for us
  584.     mov    di,(CRT_SEG/100h)*4
  585.     mov    cx,2*2
  586.     rep    movsw
  587.     add    di,4*2            ; physical image offset
  588.     mov    cx,1*2
  589.     rep    movsw
  590.     
  591.     FLUSH_TLB            ; discard TLB cache
  592.  
  593.  
  594.     mov    ax,CRT_SEG
  595.     mov    es,ax
  596.     mov    cx,2*2048        ; clear two images
  597.     mov    ax,7*256+' '        ;   to all spaces
  598.     sub    di,di
  599.     rep    stosw
  600.     add    di,4*2048        ; point to third image
  601.     mov    cx,1*2048        ; clear physical images
  602.     rep    stosw            ; and clear
  603.  
  604.     mov    bx,v386_ptr$        ; get pointer to 386 specific table
  605.     mov    es,ptbl_seg
  606.     mov    di,(CRT_SEG/100h)*4
  607.     and    PG_ATTR,not PGA_DIRTY    ; mark page as clean
  608.  
  609.     mov    dx,CON_number
  610.     mov    active_vc$,dl        ; VC number to active value
  611.     mov    sl_crt_flag$,SL_MONO_BIT ; force mono status line for terminals
  612.     mov    ax,PC_SEGMENT        ; point at ROS data
  613.     mov    es,ax
  614.     mov    es:word ptr cursor_posn_40,0000    ; force cursor position
  615.  
  616.     mov    bx,VC_pointer        ; restore VC_->
  617.     mov    VC_INSTALLED,0ffh
  618.     push    bp
  619.     mov    cl,P_PRIORITY
  620.     mov    dl,196            ; lower FLUSH priority
  621.     int    BDOS
  622.     pop    bp
  623.     sti
  624.     mov    si,PC_pointer        ; restore PC_->
  625.     call    ser_mx            ; get serial MX
  626.     mov    di,offset clear_seq    
  627.     call    ser_write        ; clear screen
  628.     mov    PC_BUSY,0        ; release MX    
  629.     call    NX_init            ; setup national support
  630.     ret
  631.  
  632. no_memory:
  633.     cld
  634.     jmp    kill_flush        ; not enough memory so kill flush 
  635.  
  636. int10_addr    rd    0        ; saved INT 10h address
  637. int10_off    rw    1        ;    "    offset
  638. int10_seg    rw    1        ;    "    segment
  639.  
  640.  
  641.  
  642.  
  643. ; Initilise Escape sequence table
  644. ; Entry : 
  645. ;    SI = PC_ structure
  646. esc_init:
  647.     push    es
  648.     push    si
  649.     push    ds ! pop es
  650.     xor    ch,ch
  651.     lea    di,PC_CURPOS
  652.     mov    si,offset cpos_seq    ; cursor positioning
  653.     lodsb
  654.     mov    cl,al            ; get count
  655.     stosb                ; store        
  656.     rep    movsb                
  657.     pop    si
  658.     push    si
  659.     lea    di,PC_ATTRIB
  660.     mov    si,offset attrib_seq    ; set attribute
  661.     lodsb
  662.     mov    cl,al            ; get count
  663.     stosb                ; and store
  664.     rep    movsb            ; store string
  665.  
  666.     pop    si
  667.     pop    es
  668.     ret
  669.  
  670. eject
  671.  
  672. ;    XIOS Function Handlers
  673. ;    ----------------------
  674.  
  675. ; Serial Console input - XIOS function 1
  676. ; Entry :
  677. ;    DL = physical console number
  678. fl_io_conin:
  679. ;-----------
  680.     cmp    dl,0            ; master console ?
  681.     jne    fl_conin_test
  682. conin_dumb:
  683.     jmp    io_conin
  684.  
  685. fl_conin_test:
  686.     call    test_pcterm@        ; test if emulation required
  687.     jz    conin_dumb        ; must be dumb terminal
  688.  
  689.  
  690. fl_conin:
  691. ;--------
  692.     mov    al,dl            ; physical console number to AL
  693.     call    point_pc1@        ; get pointer to PC_ structure in SI
  694.     sub    al, al            ; clear and test dead key buffer
  695.     xchg    al, PC_DKEY_BUFF    ; see if dead key character
  696.     test    al, al            ; is available
  697.     jz    test_pfk        ; no, just continue
  698.     mov    ah, PC_DKEY_SCAN    ; get scan code
  699.     jmps    ret_char        ; return dead key char
  700. test_pfk:
  701.     push    dx            ; DL only on entry
  702.     mov    dl,PC_TOP_SCREEN    ; current foreground console
  703.     call    point_vc@        ; get the screen structure
  704.     pop    dx
  705.     
  706.     test    VC_MODE,PCMODE_BIT    ; if a DOS program...
  707.     jnz    conin_wait        ;  no func. keys so jump
  708.  
  709.     cmp    VC_PFK_COUNT,0        ; if no PFKs waiting...
  710.     je    conin_wait        ;  then jump
  711.  
  712. ; Here if there are pending function key characters:
  713.     mov    di,VC_PFK_PTR        ; get the current pointer
  714.     mov    al,[di]            ; get the value
  715.     inc    di
  716.     test    al,al            ;  if valid then jump
  717.      jnz    conin_pfk
  718.     mov    VC_PFK_COUNT,al        ; else put 0 in the count
  719.     jmps    conin_wait        ;  and wait for a key
  720.  
  721. conin_pfk:
  722.     mov    VC_PFK_PTR,di            ; update the pointer
  723.     dec    VC_PFK_COUNT            ; and the count
  724.     mov    ah,0                ; char is in al
  725. ret_char:
  726.     ret
  727.  
  728.  
  729. conin_wait:
  730. ;----------
  731.     push    si            ; save PC_ ->
  732.     push    dx            ; save console number
  733.     call    io_conin        ; get input from standard serial conin
  734.     pop    dx
  735.     pop    si
  736.     mov    bl,al            ; char in AL and BL
  737.  
  738. ; Test for control break
  739. ; ----------------------
  740.     cmp    al,PC_SCROLL_KEY    ; ctrl-break scan ?
  741.     jne    conin_char
  742.     test    PC_KFLAG,CTRL_BIT
  743.     jz    conin_char
  744.     test    PC_KBD_TYPE,NX_enhanced ; is it enchanced keyboard version
  745.     jz    ctrl_brk        ; no break is valid
  746.     test    PC_KFLAG3,LC_E0        ; else check if last was hidden
  747.     jz    conin_char        ;  no control break if not
  748.     and    PC_KFLAG3,not LC_E0
  749. ctrl_brk:
  750.     mov    ax,0ae03h        ; cntl-c set top bit on SCAN
  751.     jmp    ci_return
  752.  
  753. conin_char:
  754.     cmp    al,HIDDEN_KEY
  755.     jne    test_live
  756.     or    PC_KFLAG3,LC_E0        ; set flag
  757.     jmp    conin_wait        ; and throw away
  758.     
  759. test_live:
  760.     push    ds ! pop es
  761.     mov    di,offset live_tbl    ; test if live key e.g. SHIFT etc.
  762.     mov    cx,live_tbl_len
  763.     and    al,7Fh
  764.     repne    scasb
  765.     je    ci_live
  766.     jmp    ci_notlive
  767. ci_live:
  768.     mov    cx,PC_SEGMENT        ; point ES at ROS data area
  769.     mov    es,cx
  770.  
  771.     cmp    PC_LANGUAGE,0        ;; U.S keyboard?
  772.     je    get_live
  773.     test    PC_NATNLSTAT,NX_nkbd_bit
  774.     jz    get_live
  775.     test    PC_ESHIFTLOCK,01h    ; is it FRENCH/GERMAN enhanced
  776.     jz    get_live
  777.     test    PC_KFLAG,CAPSLOCK_BIT    ; is CAPSLOCK already down
  778.     jz    get_live        ; no let ROS have it
  779.     cmp    al,CAPSLOCK        ; is it CAPSLOCK key
  780.     jne    test_eshift
  781.     jmp    live_ret        ; yes.. throw it away
  782.     
  783. test_eshift:                ; if CAPSLOCK on and SHIFT key
  784.     cmp    al,SHFT_RIGHT        ; then we must toggle CAPSLOCK off
  785.     je    tog_caps
  786.     cmp    al,SHFT_LEFT
  787.     jne    get_live
  788. tog_caps:
  789.     test    PC_KFLAG3,LC_E0        ; check if last was hidden
  790.     jnz    get_live        ; yes not real shift
  791.     and    PC_KFLAG,not CAPSLOCK_BIT ; lets pretend it was CAPSLOCK
  792.     jmp    live_ret
  793.  
  794. get_live:
  795.     sub    di,offset live_tbl+1
  796.     mov    ah,live_mask[di]
  797.  
  798.     cmp    al,ALT            ; is it toggle key
  799.     ja    toggle_key        ; yes
  800.  
  801. ; Live keys - SHIFT, CTRL etc
  802.     test    bl,bl
  803.     jns    ci_live_make        ; skip if not break
  804.     not    ah
  805.     and    PC_KFLAG,ah        ; update keyboard flag in PC_
  806.     cmp    ah,not CTRL_BIT        ; ALT or CTRL
  807.     ja    test_alt_input        ; no..
  808.     test    PC_KFLAG3,LC_E0        ; last char hidden
  809.     jz    not_enh            ; no..
  810.     and    PC_KFLAG3,ah        ; clear right ctrl and alt (alt_gr_bit)
  811.     jmps    not_enh1
  812. not_enh:
  813.     sar    ah,2
  814.     and    PC_KFLAG1,ah        ; reset left alt and ctrl
  815. not_enh1:
  816.     mov    ah,al
  817.     mov    al,PC_KFLAG3        ; get right alt and ctrl
  818.     shr    al,2
  819.     or    al,PC_KFLAG1        ; put in left alt and ctrl bits
  820.     shl    al,2
  821.     and     al,ALT_BIT+CTRL_BIT
  822.     or    PC_KFLAG,al        ; update real state
  823.     mov    al,ah            ; recover scan code
  824.  
  825. test_alt_input:
  826.     cmp    al,ALT            ; if ALT BREAK 
  827.     jne    not_alt_shft            
  828. ; ALT numpad
  829.     mov    al,PC_ALT_INPUT        ; check for ALT NUMPAD input
  830.     mov    ah,0
  831.     mov    PC_ALT_INPUT,ah        ; zero field
  832.     cmp    al,0
  833.     je    not_alt_shft        ; no ALT NUMPAD input
  834.     call    up_pc_flag        ; else update ROS flags
  835.     jmp    ci_return        ;  and return ALT NUMPAD value
  836. not_alt_shft:
  837.     jmps    live_ret        ; get next char input
  838.  
  839. ci_live_make:
  840.     or    PC_KFLAG,ah        ; update flag state in PC_
  841.     test    ah,CTRL_BIT + ALT_BIT    ; ALT or CTRL ?
  842.     jz    live_ret        ; no
  843.     test    PC_KFLAG3,LC_E0        ; last char hidden
  844.     jz    set_flag1        ; no..
  845.     or    PC_KFLAG3,ah        ; set right ctrl and alt (alt_gr_bit)
  846.     jmps    live_ret
  847. set_flag1:
  848.     shr    ah,2
  849.     or    PC_KFLAG1,ah        ; left ctrl and alt bits
  850. ci_live_done:
  851.     jmps    live_ret        ; get next input char
  852.  
  853.  
  854. ; Handle toggle keys - CAPSLOCK, NUMLOCK etc
  855. toggle_key:
  856.     test    bl,80h            
  857.     jnz    toggle_ret        ; ignore break
  858.     cmp    bl,INS_SCAN        ; insert key
  859.     jne    toggle1
  860. ; INSERT key
  861.     test    PC_KFLAG,ALT_BIT+CTRL_BIT
  862.     jnz    ci_notlive
  863.     test    PC_KFLAG,NUMLOCK_BIT
  864.     jnz    toggle_num
  865.     test    PC_KFLAG,SHFT_LEFT_BIT+SHFT_RIGHT_BIT
  866.     jnz    ci_notlive
  867.     jmps    toggle1a
  868. toggle_num:
  869.     test    PC_KFLAG,SHFT_LEFT_BIT+SHFT_RIGHT_BIT
  870.     jz    ci_notlive
  871. toggle1a:
  872.     xor    PC_KFLAG,ah        ; toggle state bit
  873.     and    PC_KFLAG3,not LC_E0    ; reset hidden
  874.     call    up_pc_flag
  875.     mov    ah,bl            ; scan code
  876.     mov    al,0            ; always a function key
  877.     jmp    ci_return        
  878.     
  879. toggle1:
  880.     cmp    bl,NUMLOCK        ; numlock scan code
  881.     jne    toggle2
  882.     test    PC_KFLAG,CTRL_BIT
  883.     jnz    toggle_ret        ; if CTRL NUMLOCK (i.e. PAUSE) ignore
  884. toggle2:
  885.     xor    PC_KFLAG,ah        ; toggle state bit
  886. toggle_ret:
  887. live_ret:
  888.     and    PC_KFLAG3,not LC_E0    ; reset hidden
  889.  
  890.     call    up_pc_flag
  891.     jmp    conin_wait
  892.  
  893. up_pc_flag:
  894.     cli                ; protect against dispatch or kbd
  895.     mov    cx,word ptr PC_KFLAG    ; get serial terminal flags
  896.     cmp    kbd_imhere$,0        ; in keyboard ISR ?
  897.     jne    ci_live_exit        ; yes
  898.     mov    es:word ptr kb_flag_40,cx ; and store in ROS data area
  899. ci_live_exit:
  900.     sti
  901.     ret
  902.  
  903.  
  904. ; CHARACTER input    
  905. ci_notlive:
  906.     test    PC_KFLAG3, LC_E0    ; was last hidden
  907.     jz    not_div
  908.     cmp    bl,DIV_SCAN
  909.     jne    not_div
  910.     and    PC_KFLAG3, not LC_E0    ; reset hidden flag
  911.     jmp    not_nat            ; make sure we don't translate
  912.  
  913. not_div:
  914.     cmp    bl,86
  915.      ja    conin_ret        ; get next char
  916.  
  917. ; Test for CTRL/ALT/F1 thru F5 function keys for national
  918.     mov    ah,PC_KFLAG        ; get keyboard state
  919.     and    ah,CTRL_BIT or ALT_BIT    ; check only those shift keys
  920.     cmp    ah,CTRL_BIT or ALT_BIT
  921.     jne    test_switch
  922.     cmp    al,F10_SCAN        ; Ctl Alt F10 resets the lock bits
  923.      jne    not_lights_reset    ; to get back in step with the terminal
  924.     test    PC_KFLAG,SHFT_LEFT_BIT or SHFT_RIGHT_BIT
  925.      jz    not_lights_reset    ; we want shift as well (for Falcoa)
  926.     and    PC_KFLAG,not(CAPSLOCK_BIT+NUMLOCK_BIT+SCROLL_BIT)
  927. not_lights_reset:
  928.     cmp    al,F1_SCAN        ; check if function key
  929.     jb    test_switch
  930.     cmp    al,F5_SCAN
  931.     ja    test_switch
  932.     sub    al,F1_SCAN        ; make it zero based
  933.     mov    PC_NATNLMODE,al        ; save current national mode
  934.     call    NX_update_mode
  935.     jmps    conin_ret        ; get next char
  936.  
  937. ; Test for screen switch keys
  938. test_switch:
  939.     test    PC_KFLAG3, LC_E0    ; was last hidden
  940.     jnz    test_alt_key
  941.     mov    ah,PC_KFLAG        ; get keyboard state
  942.     and    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT or CTRL_BIT or ALT_BIT ;;
  943.     cmp    ah,switch_bits$        ; same as keyboard switch bits
  944.     jnz    test_alt_key
  945.     cmp    al,END_SCAN        ; pad 1 key
  946.     jne    test_pad2
  947.     mov    ax,0ff00h        ; yes switch key
  948.     jmps    ret_switch
  949. test_pad2:
  950.     cmp    al,PAD2_SCAN        ; pad 2 key
  951.     jne    test_alt_key
  952.     mov    ax,0ff01h
  953. ret_switch:
  954.     and    PC_KFLAG3, not LC_E0    ; reset hidden flag
  955.     ret                ; return switch key
  956.  
  957.  
  958. ; Test for ALT key
  959. test_alt_key:
  960.     test    PC_KFLAG,ALT_BIT    ; test for ALT NUMPAD keys
  961.     jz    not_alt_numpad
  962. ; ALT numpad keys
  963.     push    ds ! pop es
  964.     mov    di,offset alt_intable
  965.     mov    cx,alt_intable_len
  966.     repne    scasb
  967.     jne    not_alt_numpad        ; not ALT numpad    
  968.     sub    di,offset alt_intable+1
  969.     mov    al,PC_ALT_INPUT        ; get last alt char
  970.     mov    ah,10
  971.     mul    ah
  972.     add    ax,di            ; add in latest entry
  973.     mov    PC_ALT_INPUT,al        ; save new char
  974. conin_ret:
  975.     and    PC_KFLAG3, not LC_E0    ; reset hidden flag
  976.     jmp    conin_wait        ; and get next char
  977.  
  978. not_alt_numpad:
  979.     mov    PC_ALT_INPUT,0        ; clear ALT numpad char
  980.     mov    ah,PC_KFLAG        ; get keyboard state
  981.  
  982. ; the following code is supposed to take care of the case where PC Terminals
  983. ; are out of step with the local copy of NUMLOCK, a situation which screws up
  984. ; the arrow keys on extended keyboards. It is based on the observation that
  985. ; if there is a hidden code before the numpad key then it must be one of the
  986. ; extended keys, and if so the PC terminal will have ensured that the shift
  987. ; state has been set to negate the NUMLOCK state. So we can reverse this and
  988. ; set the NUMLOCK state according to the shift one.
  989. ;
  990.     test    PC_KFLAG3,LC_E0        ; following a hidden key ?
  991.      jz    test_nat
  992.     cmp    al,47h            ; is it one affected by NUMLOCK ?
  993.      jb    test_nat
  994.     cmp    al,53h
  995.      ja    test_nat
  996.     and    ah, not NUMLOCK_BIT    ; assume numlock should be off
  997.     mov    PC_KFLAG,ah
  998.     test    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT
  999.      jz    test_nat        ; if either shift key down
  1000.     or    ah, NUMLOCK_BIT        ; numlock should be on
  1001.     mov    PC_KFLAG,ah
  1002. ; end of NUMLOCK fix
  1003.  
  1004. ; Test for national or U.S. keyboard
  1005. test_nat:
  1006.     test    PC_NAT,0ffh        ; U.S. or national
  1007.     jz    not_nat            ; standard US
  1008.     test    PC_NATNLSTAT$,NX_nkbd_bit ; U.S.
  1009.     jz    not_nat            
  1010.  
  1011. ; National Keyboard 
  1012.     cmp    al,PRTSC_SCAN
  1013.     je    not_nat            ; don't translate
  1014.     cmp    al,SCAN_102        ;; extra key - enhanced keyboard
  1015.     je    nat_jmp
  1016.     cmp    al,SPACE_SCAN        ;; let national have space key
  1017.     ja    test_pad        ;;  and all keys below
  1018. nat_jmp:
  1019.     and    PC_KFLAG3, not LC_E0    ; reset hidden flag
  1020.     jmp    nat_kbd
  1021.     
  1022. ; some keypad keys are translated in some languages
  1023. test_pad:
  1024.     cmp    al,DEL_SCAN        ; SHIFT DEL -> conv to ','
  1025.     jne    test_prt
  1026.     test    PC_KFLAG3, LC_E0    ; hidden flag
  1027.     jnz    not_nat
  1028.     test    ah,NUMLOCK_BIT
  1029.     jz    no_num
  1030.     test    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT
  1031.     jz    test_lang        ; NUMLOCK + no SHIFT
  1032.     jmps    not_nat            ; handle as normal
  1033. no_num:
  1034.     test    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT ; no NUMLOCK + SHIFT
  1035.     jz    not_nat            ; no handle normal
  1036.     
  1037. test_lang:
  1038.     cmp    PC_LANGUAGE,4        ; Danish
  1039.     je    conv_dot
  1040.     cmp    PC_LANGUAGE,5        ; Swedish
  1041.     je    conv_dot
  1042.     cmp    PC_LANGUAGE,8        ; Norwegian
  1043.     je    conv_dot
  1044.     test    PC_KBD_TYPE$,NX_enhanced ; is it enchanced keyboard version
  1045.     jz    not_nat            ; no
  1046.     cmp    PC_LANGUAGE,2        ; German enhanced ?
  1047.     je    conv_dot        ; yes
  1048.     jne    not_nat
  1049. conv_dot:
  1050.     mov    al,','            ; convert '.' to ','
  1051.     mov    ah,DEL_SCAN
  1052.     jmp    pc_ret            ; and return key
  1053.         
  1054. test_prt:
  1055.     cmp    PC_LANGUAGE,7        ; SPANISH ?
  1056.     jne    not_nat            ; no ..
  1057.     test    PC_KBD_TYPE$,NX_enhanced ; is it enchanced keyboard version
  1058.     jnz    not_nat            ; yes .. no translate
  1059.     cmp    al,PRTSC_SCAN        ; print screen key
  1060.     jne    not_nat
  1061.     mov    al,'^'            ; '*' converted to '^'
  1062.     mov    ah,PRTSC_SCAN
  1063.     jmp    pc_ret
  1064.  
  1065.  
  1066. ; Here for U.S. keyboard support
  1067. not_nat:
  1068.     and    PC_KFLAG3, not LC_E0    ; reset hidden flag
  1069.     mov    ah,al
  1070.     mov    di,offset key_table
  1071.     mov    bx,offset key_scan
  1072.     test    PC_KFLAG,NUMLOCK_BIT    ; test NUMLOCK on
  1073.     jz    test_shft
  1074.     cmp    al,HOME_SCAN        ; is it NUMPAD
  1075.     jb    test_shft        
  1076.     cmp    al,DEL_SCAN
  1077.     ja    test_shft        ; no....
  1078.     test    PC_KFLAG,SHFT_LEFT_BIT+SHFT_RIGHT_BIT
  1079.     jnz    ci_notshft        ; use normal table if NUMLOCK shift
  1080.     mov    di,offset shift_table    ; else use shift table
  1081.     mov    bx,offset shift_scan
  1082.  
  1083. test_shft:
  1084.     test    PC_KFLAG,SHFT_LEFT_BIT+SHFT_RIGHT_BIT
  1085.     jz    ci_notshft
  1086.     mov    di,offset shift_table
  1087.     mov    bx,offset shift_scan
  1088. ci_notshft:
  1089.     test    PC_KFLAG,CTRL_BIT
  1090.     jz    ci_notctrl
  1091.     mov    di,offset ctrl_table
  1092.     mov    bx,offset ctrl_scan
  1093. ci_notctrl:
  1094.     test    PC_KFLAG,ALT_BIT
  1095.     jz    ci_notalt
  1096.     mov    bx,offset alt_table
  1097.     xlat    al
  1098.     cmp    al,0FFh            ; legal char ?
  1099.     je    ci_ret1
  1100.     mov    ah,al
  1101.     mov    al,0            ; always a function key
  1102.     jmp    ci_return
  1103.  
  1104. ci_notalt:
  1105.     mov    ah,al
  1106.     xlat    al            ; get scan code
  1107.     xchg    ah,al            ; save it in high byte
  1108.     mov    bx,di
  1109.     xlat    al            ; get ASCII code
  1110.     cmp    al,0FFh            ; legal char ?
  1111.      je    ci_ret1
  1112.     test    PC_KFLAG,CAPSLOCK_BIT    ; test CAPSLOCK on
  1113.     jz    ci_ret2
  1114.     call    case_change 
  1115. ci_ret2:
  1116.      jmp    ci_return        ; yes return char
  1117. ci_ret1:
  1118.     jmp    conin_wait        ; else get next char
  1119.  
  1120.  
  1121.  
  1122. ;************************************************
  1123. ;*                        *
  1124. ;*    NATIONAL KEYBOARD SUPPORT        *
  1125. ;*                        *
  1126. ;************************************************
  1127.  
  1128. ;    DL = console number
  1129. ;     SI = PC_ structure
  1130. ;    AL = raw scan code
  1131. ;    AH = keyboard action state
  1132.  
  1133. nat_kbd:
  1134.     push    dx            ; lets save console number for retry
  1135.     
  1136.     mov    PC_KBD_SCAN,al
  1137.     mov    PC_SCAN_CODE,al        ; temp save scan code
  1138.     cmp    al,41            ; is it 1st key?
  1139.      je    pc_at_swap        ; yes, fix it
  1140.     cmp    al,43            ; is it 2nd key?
  1141.      jne    test_alt        ; others are OK
  1142. pc_at_swap:                ; swap the key codes
  1143.     xor    al,41 xor 43        ; 41 => 43, 43 => 41
  1144.     mov    PC_SCAN_CODE,al        ; save new value
  1145. test_alt:
  1146.     test    PC_KBD_TYPE$,NX_enhanced ; is it enchanced keyboard version
  1147.      jz    test_alt_norm        ; no .. normal keyboard
  1148.     test    PC_KFLAG3,ALT_GR_BIT    ; ALT GR key down ?
  1149.      jz    test_ctrl_alt
  1150.  
  1151.     test    PC_KFLAG1,L_ALT        ; is left ALT down
  1152.      jnz    test_ctrl_alt        ; yes.. ignore ALT GR
  1153.     and    ah,not ALT_BIT        ; else remove ALT bit from status
  1154.     test    ah,CTRL_BIT        ; yes.. is ctrl key down
  1155.      jnz    test_alt_norm        ; yes .. ignore ALT GR
  1156.     jmps    get_alt_gr        ; else do ALT GR translate
  1157. test_ctrl_alt:
  1158.     test    ah,ALT_BIT+CTRL_BIT
  1159.      jz    test_alt_norm
  1160. not_gr:
  1161.     mov    ch,ah
  1162.     and    ch,ALT_BIT+CTRL_BIT
  1163.     cmp    ch,ALT_BIT+CTRL_BIT
  1164.     jne    test_alt_norm
  1165.     
  1166. ; Get key from ALT GR - (CTRL\ALT) table
  1167. ; for national enhanced keyboards
  1168. get_alt_gr:
  1169.     mov    bx,offset NX_ctrlalt$        ; pointer to CTRL\ALT table
  1170.     test    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT
  1171.     jz    not_shift            ; leave it if not shifted
  1172.     mov    bx,offset NX_ctrlalt_shft$    ; use CTRL\ALT shift table
  1173. not_shift:
  1174.     mov    PC_TMP_US_FLG, TRUE        ; disable 7 to 8 temporarily
  1175.  
  1176.     mov    al,PC_SCAN_CODE        ; use this value in case translated
  1177.     cmp    PC_KBD_SCAN,29h
  1178.     jne    test_102
  1179.     mov    al,54            ; character position reserved for extra key
  1180. test_102:
  1181.     cmp    PC_KBD_SCAN,SCAN_102  ; extra key (102 keyboard)
  1182.     jne    just_xlat
  1183.     mov    al,2bh            ; key 102 uses old char 2bh scan code
  1184. just_xlat:
  1185.     cmp    al,SPACE_SCAN        ;; don't translate
  1186.     jne    do_xlat
  1187.     mov    al,' '            ;; space char
  1188.     jmp    key_scan_ok
  1189. do_xlat:
  1190.     xlat    bx            ; get ASCII char in AL
  1191.     cmp    al, 0ffh        ; is it undefined
  1192.     je    key_scan_nok        
  1193.     jmp    NX_test_2nd_dkey    ; no.....valid key
  1194.     jmp    key_scan_ok
  1195.  
  1196. key_scan_nok:
  1197.     mov    ch,ah
  1198.     and    ch,ALT_BIT + CTRL_BIT
  1199.     cmp    ch,ALT_BIT + CTRL_BIT
  1200.     je    test_alt_norm        ; if CTRL\ALT then treat normal
  1201.     jmp    key_scan_done        ; else .... ignore
  1202.  
  1203. ; Normal keyboard -    
  1204. test_alt_norm:
  1205.     test    ah,ALT_BIT 
  1206.     jnz    test_alt_down
  1207.     jmp    not_alt            ; not ALT key
  1208.  
  1209. ;    The following piece of code had to be added to support ALT/letter
  1210. ;    on international keyboards, where the location of some keys is
  1211. ;    different from the US keyboard. 
  1212. test_alt_down:
  1213.     test    ah,CTRL_BIT
  1214.     jz    not_ctrlalt        ; not CTRL\ALT
  1215. ;;    mov    al, pc_scan_code    ; restore scan code
  1216.     test    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT
  1217.     jz    not_shft_alt
  1218.     or    al, 80h            ; shift marked like this in ALT table
  1219. not_shft_alt:
  1220.     mov    cx, 0
  1221.     mov    cl, NX_alt_table$    ; get number of special ALT's (common)
  1222.     jcxz    not_ctrlalt        ; none of them
  1223.     push    es
  1224.     push    ds ! pop es        ; point ES to DS
  1225.     mov    di, offset NX_alt_table$+1    ; scan thru them
  1226.     cld
  1227.     repne    scasb
  1228.     pop    es
  1229.     jne    not_ctrlalt
  1230.  
  1231.     sub    di,offset NX_alt_table$ + 2    ; get number of scanned chars
  1232.     mov    al,NX_alt_chars$[di]        ; save the character
  1233.     mov    PC_TMP_US_FLG, TRUE    ; display as ascii (flag "CONOUT")
  1234.     jmp    save_with_msb
  1235.  
  1236.  
  1237. not_ctrlalt:
  1238.     mov    al, PC_SCAN_CODE    ; restore scan code
  1239.     cmp    al, 2            ; scan code of digit "1"
  1240.     jb    test_alt_letter        ; below, forget it
  1241.     cmp    al, 13            ; above "=", check if letter
  1242.     ja    test_alt_letter        ; check if ALT/letter
  1243.     add    PC_SCAN_CODE, 118    ; ALT/1 thru ALT/0 are 120,...
  1244.     jmp    turn_on_msb        ; now it's all right
  1245.  
  1246. test_alt_letter:
  1247.     mov    bx, PC_NASCIITABLE    ; see if letter on keyboard
  1248.     xlat    bx            ; lookup table
  1249.     cmp    al, 'a'            ; check lower boundary
  1250.     jb    not_alt_letter        ; too small
  1251.     cmp    al, 'z'            ; check upper boundary
  1252.     ja    not_alt_letter        ; too big
  1253.  
  1254.     push    es            ; save ES
  1255.     push    ds ! pop es        ; MOV DS,ES
  1256.     mov    di, offset key_table    ; scan through US key table
  1257.     mov    cx, 54            ; 54 chars at most
  1258.     cld                ; scan forward
  1259.     repne    scasb            ; find out location on US kbd
  1260.     sub    di, offset key_table+1    ; subtract base + overscan
  1261.     mov    ax, di            ; AL = scan code
  1262.     mov    PC_SCAN_CODE,al
  1263.     pop    es            ; restore extra segment
  1264.     jmp    turn_on_msb        ; return extended code for ALT
  1265.  
  1266.  
  1267. ;    test if this is an alt dead key.
  1268. ;    eat it up if it is one, continue if not.
  1269. ;    bit 7 in DEADTABLE contains shift bit,
  1270. ;    bit 6 in DEADTABLE contains alt bit
  1271. ;    (works fine because those codes are 1-59)
  1272. ;
  1273. not_alt_letter:
  1274.     cmp    PC_NATNLMODE, 1        ; 8 bit National mode ONLY
  1275.     jne    no_alt_dkey
  1276.     mov    cl, PC_SCAN_CODE    ; get key code
  1277.     test    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT
  1278.     jz    alt_dkey_noshift    ; no shift, leave it
  1279.     or    cl, 80h            ; turn on shift bit
  1280. alt_dkey_noshift:
  1281.     or    cl, 40h            ; turn on alt bit
  1282.     mov    di, PC_DEADTABLE    ; find out if alt dead key
  1283.     call    NX_scanstr        ; look for a match
  1284.     cmp    di,0FFFFh        ; no match
  1285.     je    no_alt_dkey        ; forget it
  1286.     mov    PC_LAST_DKEY, di    ; save dead key
  1287. no_alt_dkey:
  1288.     jmp    key_scan_done            ; eat up this code
  1289.  
  1290.  
  1291. ; CTRL, SHIFT or NORMAL ascii national key
  1292. not_alt:
  1293.     mov    bx, PC_NASCIITABLE    ; translation table for single keys
  1294.     test    ah,CTRL_BIT        ; is control key down ?
  1295.      jz    test_for_shift        ; no, try shift
  1296.  
  1297.     mov    bx, PC_CTRLTABLE    ; yes, point to control key table
  1298.     jmps    translate        ; and make control code
  1299.  
  1300. test_for_shift:
  1301.     cmp    PC_SHIFTLOCK,FALSE    ;; french keyboard flag
  1302.      jnz    test_caps        ;; true
  1303.     test    PC_ESHIFTLOCK,01h        ; is german/french capslock down
  1304.      jz    shift_test
  1305. test_caps:
  1306.     test    ah,CAPSLOCK_BIT
  1307.      jnz    shift_t            ; YES..
  1308. shift_test:
  1309.     test    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT
  1310.      jz    translate        ; not shifted
  1311. shift_t:
  1312.     mov    bx, PC_SHIFTTABLE
  1313. ;    jmps    translate        ;use shift table if numlock
  1314.  
  1315. translate:
  1316.     mov    al,PC_SCAN_CODE        ; use this value in case translated
  1317.  
  1318.     test    PC_KBD_TYPE,NX_enhanced    ; is it enhanced keyboard
  1319.      jz    just_xlat1        ; no..
  1320.     cmp    byte ptr PC_KBD_SCAN,29h ; original scan code
  1321.      jne    test_102_a
  1322.     mov    al,54            ; character position reserved for extra key
  1323. test_102_a:
  1324.     cmp    PC_KBD_SCAN,SCAN_102  ; extra key (102 keyboard)
  1325.      jne    just_xlat1
  1326.     mov    al,2bh            ; key 102 uses old char 2bh scan code
  1327. just_xlat1:
  1328.     cmp    al,SPACE_SCAN        ;; don't translate
  1329.     jne    translate1
  1330.     mov    al,' '            ;; space char
  1331.     jmps    key_scan_ok
  1332. translate1:
  1333.     xlat    bx            ; get ASCII char in AL
  1334.     cmp    al, 0ffh        ; is it undefined
  1335.     jne    key_scan_ok        ; no.....valid key
  1336.     jmp    key_scan_done        ; yes .... ignore
  1337.  
  1338. key_scan_ok:
  1339.     call    NX_isdkey        ; check if this is a dead key
  1340.     cmp    di, 0FFFFh        ; no match in table
  1341.     je    NX_test_2nd_dkey    ; character is not a dead key
  1342.     jmp    key_scan_done        ; just save it for later combination
  1343. NX_test_2nd_dkey:
  1344.     call    NX_chk_dkey        ; try to combine it with dead key
  1345.  
  1346.     test    ah,CAPSLOCK_BIT        ;test for caps lock
  1347.     jz    save_msb        ; no...
  1348.     cmp    PC_SHIFTLOCK,FALSE    ;; french keyboard flag
  1349.     jnz    test_french        ;; true
  1350.     test    PC_ESHIFTLOCK,01h    ; enhanced keyb shift lock supported ?
  1351.      jnz    save_with_msb        ; yes.. ignore CAPS translate
  1352.     test    PC_KFLAG3,ALT_GR_BIT    ; ALT GR key down ?
  1353.      jnz    save_msb        ; ignore case change
  1354.     call    NX_case_change        ; else check if case sensitive
  1355. save_msb:
  1356.     jmps    save_with_msb
  1357.     
  1358. ;; Special test for FRENCH keyboard support
  1359. ;; if CAPSLOCK numeric keys assume shift position
  1360. test_french:
  1361. ;;    test    alt_gr,ALT_GR_BIT    ; ALT GR key down ?
  1362. ;;     jnz    save_with_msb        ; yes.. no further translation
  1363.     
  1364.     cmp    PC_KBD_SCAN,2        ; numeric keys and '-' and '='
  1365.      jb    save_with_msb        ; ignore keys below 1
  1366.     
  1367.     cmp    PC_KBD_SCAN,13        ; and above '+'
  1368.     ja    save_with_msb    
  1369.     
  1370.     mov    al,PC_KBD_SCAN        ; restore the scan code
  1371.     mov    bx,PC_SHIFTTABLE    ; assume no shift key down
  1372.     test    ah,SHFT_LEFT_BIT or SHFT_RIGHT_BIT
  1373.     jz    caps_xlat
  1374.     mov    bx,PC_NASCIITABLE
  1375. caps_xlat:
  1376.     xlat    bx
  1377.     jmps    save_with_msb
  1378.  
  1379. turn_on_msb:
  1380.     mov    ah, PC_KBD_SCAN
  1381.     mov    al, PC_SCAN_CODE
  1382.     mov    PC_KBD_SCAN,al
  1383.     xor    al, al
  1384.     cmp    ah, 2
  1385.     jb    skip_alt_char
  1386.     cmp    ah, 14
  1387.     jb    save_with_msb        ;check for alt and 1234567890-= keys
  1388.     cmp    ah, 16 ! 
  1389.     jb    skip_alt_char
  1390.     cmp    ah, 26
  1391.     jb    save_with_msb        ;check for alt and qwertyuiop keys
  1392.     cmp    ah, 30
  1393.     jb    skip_alt_char
  1394.     cmp    ah, 39
  1395.     jb    save_with_msb        ;check for alt and asdfghjkl keys
  1396.     cmp    ah, 44
  1397.     jb    skip_alt_char
  1398.     cmp    ah, 51
  1399.     jb    save_with_msb        ;check for alt and zxcvbnm keys
  1400.  
  1401. skip_alt_char:
  1402.     jmp key_scan_done
  1403.  
  1404. save_with_msb:
  1405.     call    NX_conin_xlat        ; translate & check if valid
  1406.     jc    key_scan_done        ; eat it if invalid
  1407.  
  1408.     mov    ah,PC_KBD_SCAN        ; scan code value into AH
  1409.                     ; char in AL
  1410.     pop    dx            ; clean console number off stack
  1411.     jmps    ci_return
  1412.  
  1413. ;    Common exit if no character was detected
  1414. key_scan_done:
  1415.     pop    dx            ; restore console number
  1416.     jmp    fl_conin        ;  and wait for next char
  1417.  
  1418.  
  1419.  
  1420. ; --------------------------------------------
  1421. ; Keyboard input translated to Scan\Character. 
  1422. ci_return:
  1423.     push    dx            ; save dx on entry
  1424.     mov    dl,PC_TOP_SCREEN    ; get top vc screen
  1425.     call    point_vc@        ; VC_ structure
  1426.     pop    dx
  1427.     test    VC_MODE,PCMODE_BIT    ; if DOS pgrm.
  1428.     jnz    pc_ret            ;  return immediately
  1429.     or    al,al            ; extended? 
  1430.     jnz    conin_ret1        ; no, just ascii...jump.
  1431.  
  1432.     cmp    ah,TWO_SCAN        ;If cntl @, leave it as null
  1433.     je    conin_ret1
  1434.     cmp    ah,TAB_SCAN        ; if backtab, return FF
  1435.     jne    not_bt
  1436.     mov    al,FF            ; for COPYMENU
  1437.     jmps    conin_ret1
  1438. not_bt:
  1439.     cmp    ah,F1_SCAN        ; nothing below is programmable
  1440.     jb    conin_done        ; no key yet
  1441.     call    trans_pfk        ; maybe a special CPM
  1442.     jnz    conin_done
  1443.     cmp    VC_PFK_EXP,0        ; if expansion is turned off
  1444.     je    conin_done        ; then return unexpanded key
  1445.     xchg    ah,al            ; pfk index to ah
  1446.     call    point_pfk        ; a programmable
  1447.     jmp    fl_conin        ; get first
  1448. conin_done:
  1449.     or    al,al
  1450.     jmpz    ci_ret1            ; nothing, so wait more
  1451.  
  1452. conin_ret1:
  1453.     sub    ah,ah            ; cpm spec
  1454. pc_ret:
  1455.     ret
  1456.  
  1457. ;-------------------
  1458. ; CONIN subroutines
  1459. ;-------------------
  1460.  
  1461. case_change:    ; check if we need to change lower case <-> upper case
  1462. ;-----------
  1463.     cmp    al, 'z'            ; yes
  1464.      ja    case_ret        ; not alphabetic
  1465.     cmp    al, 'a'            ; is it lower case ?
  1466.      jae    do_case            ; yes $ switch case
  1467.     cmp    al, 'Z'
  1468.      ja    case_ret        ; not alphabetic
  1469.     cmp    al, 'A'            ; test for upper case
  1470.      jb    case_ret        ; not alphabetic
  1471. do_case:
  1472.     xor    al, 020h        ; switch the case
  1473. case_ret:
  1474.     ret
  1475.  
  1476.  
  1477. ; This routine takes an Extended scan code as returned from ROS and converts
  1478. ; it to it's unexpanded CPM equivalent.
  1479. ; USE COMMON TABLES FROM CONIN.A86 module.
  1480. ; Entry: ah = scan, al = 0
  1481. ; Exit:  ZF = set, ah=PFK index, al=translation (w/ hi bit set)
  1482. ;        if a CPM programmable
  1483. ;     ZF = reset, ax = preserved if not
  1484. trans_pfk:
  1485. ;---------
  1486.     push    es
  1487.      mov    cx,ds
  1488.      mov    es,cx                ; point es here
  1489.      xchg    al,ah
  1490.      mov    cx,PFK_SCAN_LIST_SIZE        ; how many to check
  1491.      cld
  1492.      mov    di,offset pfk_scan_list$
  1493.      repne    scasb                ; look for it
  1494.     pop    es
  1495.      jz    found_scan            ; found it
  1496.     xchg    al,ah
  1497.     ret                    ; return w/ ZF = 0 if no match
  1498.  
  1499. found_scan:
  1500.     dec    di
  1501.     sub    di,offset pfk_scan_list$
  1502.     mov    ax,di
  1503.     mov    ah,al
  1504.     mov    al,pfk_code_tbl$[di]        ; get the cpm code
  1505.     or    al,80h                ; set the high bit
  1506.     cmp    al,al                ; ZF = 1
  1507.     ret
  1508.  
  1509. point_pfk:
  1510. ;---------
  1511. ; Point to PFK table  --  fixed area in SETUP data
  1512. ; **** cannot be changed ****
  1513. ;  entry:    al = pfk table index
  1514. ;        bx -> vs_
  1515. ;  exit:    VC_PFK_PTR -> pfk value
  1516. ;        VC_PFK_COUNT = maximum char count
  1517.  
  1518.     sub    si,si                ; zero offset for low table
  1519.     mov    cl,PFK_L_SIZE            ; chars per low pfk
  1520.     cmp    al,LOW_PFKS            ; check for low table
  1521.      jb    point_pfk1            ; skip if unshifted F1-F10
  1522.     sub    al,LOW_PFKS            ; index into high table
  1523.     mov    si,PFK_L_SIZE * LOW_PFKS    ; offset for high table
  1524.     mov    cl,PFK_H_SIZE            ; chars per high pfk
  1525. point_pfk1:
  1526.     mul    cl                ; index into high table
  1527.     add    si,ax
  1528.     add    si,VC_PFK_TBL            ; add table offset
  1529.     mov    VC_PFK_PTR,si            ; set initial pointer
  1530.     mov    VC_PFK_COUNT,cl            ; and initial count
  1531.     cmp    ax,ax                ; set zero flag
  1532.     ret
  1533.  
  1534.  
  1535. ;****************************************
  1536. ;*     National keyboard subroutines
  1537. ;****************************************
  1538.  
  1539. NX_init:    ; initialize keyboard/screen/printer
  1540. ;=======    ; and PC structure
  1541.         ; Entry SI = PC_ ->    
  1542.     
  1543.     mov    al,NX_language$        ; get national language
  1544.     mov    PC_LANGUAGE,al
  1545.     mov    al,NX_natnlstat$
  1546.     mov    PC_NATNLSTAT,al
  1547.     mov    al,NX_natnlmode$
  1548.     mov    PC_NATNLMODE,al
  1549.     mov    dl,PC_CONS
  1550.     call    get_su_mu        ; get setup byte for console in AL
  1551.     test    al,ENHANCED        ; enhanced keyboard
  1552.     jz    not_e
  1553.     mov    PC_KBD_TYPE,NX_enhanced
  1554. not_e:
  1555.     and    al,NAT_MODE        ; mask national bit
  1556.     mov    PC_NAT,al
  1557.     
  1558.     test    PC_KBD_TYPE,NX_enhanced    ; enhanced serial ?
  1559.     jz    n2            ; no
  1560.     test    NX_kbd_type,NX_enhanced    ; enhanced main console ?
  1561.     jz    n3            ; no
  1562.     jmps    n1
  1563. n2:        
  1564.     test    NX_kbd_type,NX_enhanced ; enhanced main console 
  1565.     jnz    n3            ; yes
  1566. n1:    
  1567.     mov    bx,offset NX_nasciitable$
  1568.     mov    PC_NASCIITABLE,bx
  1569.     mov    bx,offset NX_nshifttable$
  1570.     mov    PC_SHIFTTABLE,bx
  1571.     mov    bx,offset NX_nctrltable$    
  1572.     mov    PC_CTRLTABLE,bx
  1573.     mov    bx,offset NX_deadtable$
  1574.     mov    PC_DEADTABLE,bx
  1575.     jmps    n4
  1576. n3:
  1577.     mov    bx,offset NX_pc_ascii$
  1578.     mov    PC_NASCIITABLE,bx
  1579.     mov    bx,offset NX_pc_shift$
  1580.     mov    PC_SHIFTTABLE,bx
  1581.     mov    bx,offset NX_pc_ctrl$    
  1582.     mov    PC_CTRLTABLE,bx
  1583.     mov    bx,offset NX_pc_dead$
  1584.     mov    PC_DEADTABLE,bx
  1585. n4:        
  1586.     mov    al, PC_NATNLMODE
  1587.  
  1588. NX_update_mode:
  1589.     cbw                ; make it a word value
  1590.     mov    bx, ax            ; put it into index register
  1591.     mov    al, NX_mode_table$[bx]    ; get desired mode bits
  1592.     mov    PC_NATNLSTAT, al    ; setup new mode bits
  1593.  
  1594. ;;; Handle the special case of FRENCH CAPSLOCK KEY which
  1595. ;;; acts as a SHIFTLOCK by translating all the keys on the keyboard 
  1596. ;;; and not just azerty keys.
  1597.  
  1598. NX_update_mode_done:
  1599.     mov    PC_SHIFTLOCK,FALSE    ; assume normal
  1600.     cmp    PC_LANGUAGE,1        ; is it FRENCH system
  1601.      jnz    NX_update_exit1
  1602.     test    al,NX_nkbd_bit        ; national keyboard support
  1603.      jz    NX_update_exit1
  1604.     mov    PC_SHIFTLOCK,TRUE
  1605. NX_update_exit1:
  1606.     test    PC_KBD_TYPE,NX_enhanced ; is it enchanced keyboard version
  1607.      jz    NX_update_exit        ; no .. normal keyboard
  1608.  
  1609. ;; Handle special case of CAPSLOCK key on 
  1610. ;; FRENCH and GERMAN enhanced keyboard
  1611.  
  1612.     cmp    PC_LANGUAGE,1        ; is it FRENCH system
  1613.      jnz    test_german
  1614.     or    PC_ESHIFTLOCK,01h
  1615. test_german:
  1616.     cmp    PC_LANGUAGE,2        ; is it GERMAN system
  1617.      jnz    NX_update_exit
  1618.     or    PC_ESHIFTLOCK,01h
  1619.  
  1620. NX_update_exit:
  1621.     ret
  1622.  
  1623.  
  1624. ;---------------
  1625. NX_conin_xlat:    ;translate 8 bit back to 7 bit if in 7 bit mode
  1626. ;---------------
  1627. ;    Input:    AL = char to translate
  1628. ;        SI = PC-> structure
  1629. ;    Output:    AL = translated character
  1630. ;
  1631.     cmp    PC_NATNLMODE,3        ;Ctrl/Alt/F4 or F5 mode?
  1632.     jb    NX_conin_xlat_done    ;nothing to do if not
  1633.  
  1634.     mov    bx,offset NX_n7to8chr$    ; scan thru 8 bit eqv chars
  1635. NX_conin_loop:
  1636.     cmp    byte ptr [bx], 0    ; see if end of translate tbl
  1637.     jz    NX_conin_xlat_ignore    ; yes, ignore if 8 bits
  1638.     cmp    al,[bx]            ; see if translation required
  1639.     jz    NX_conin_8to7        ; yes, one of those characters
  1640.     inc    bx            ; no, may be next time
  1641.     jmps    NX_conin_loop        ; give it another try
  1642.  
  1643. NX_conin_8to7:
  1644.     sub    bx,offset NX_n7to8chr$    ; see how many chars checked
  1645.     mov    al, NX_n7to8tbl$[bx]    ; substitute it
  1646.  
  1647. NX_conin_xlat_done:
  1648.     test    al, al            ; clear carry
  1649.     ret                ; back to keyboard interrupt routine
  1650.  
  1651. NX_conin_xlat_ignore:
  1652.     test    al, al            ; seven bits?
  1653.     jns    NX_conin_xlat_done    ; yes, return
  1654.     stc                ; set carry
  1655.     ret
  1656.  
  1657.  
  1658. NX_case_change:    ; check if we need to change lower case <-> upper case
  1659. ;----------------
  1660.     cmp    al, 'z'            ; yes
  1661.      ja    NX_case_test        ; not alphabetic
  1662.     cmp    al, 'a'            ; is it lower case ?
  1663.      jae    do_case_change        ; yes $ switch case
  1664.     cmp    al, 'Z'
  1665.      ja    NX_case_test        ; not alphabetic
  1666.     cmp    al, 'A'            ; test for upper case
  1667.      jb    NX_case_test        ; not alphabetic
  1668. do_case_change:
  1669.     xor    al, 020h        ; switch the case
  1670.     ret
  1671.  
  1672. NX_case_test:
  1673. ;--------------
  1674.     mov    cl, al
  1675.     mov    di, offset NX_ncasetbl$
  1676.     call    NX_scanstr
  1677.     cmp    di, 0FFFFh
  1678.      je    NX_no_case_change
  1679.     xor    di, 1            ; lower < --- > upper
  1680.     mov    al, NX_ncasetbl$[di]    ; pick up the other
  1681. NX_no_case_change:
  1682.     ret
  1683.  
  1684.  
  1685. NX_isdkey:    ; check if character is a dead key
  1686. ;-----------    ; AH = Shift state
  1687.         ; SI = PC->
  1688.     mov    di, -1            ; assume no dead key
  1689. ;    test    ah, CTRL_BIT+ALT_BIT
  1690. ;    jnz    NX_no_dkey
  1691.     cmp    PC_NATNLMODE, 1        ; Ctrl/Alt/F2 mode?
  1692.     jne    NX_no_dkey        ; (others don't support dead keys)
  1693.     cmp    al,'~'
  1694.     je    is_dead
  1695.     mov    cl,al
  1696.     mov    di,offset NX_dead_ascii$
  1697.     call    NX_scanstr
  1698.     cmp    di, -1
  1699.     je    NX_no_dkey
  1700. is_dead:    
  1701.     mov    cl, PC_KBD_SCAN
  1702.     test    PC_ESHIFTLOCK,01h        ; is german/french capslock down
  1703.     jz    shift_test3
  1704.     test    ah,CAPSLOCK_BIT
  1705.     jnz    shift_t3        ; YES..
  1706. shift_test3:
  1707.     test    ah, SHFT_LEFT_BIT or SHFT_RIGHT_BIT
  1708.      jz    NX_isdkey_noshift
  1709. shift_t3:
  1710.     or    cl, 80H
  1711. NX_isdkey_noshift:
  1712.     mov    di, PC_DEADTABLE
  1713.     call    NX_scanstr
  1714.     cmp    di, -1
  1715.      je    NX_no_dkey
  1716.     mov    PC_LAST_DKEY, di
  1717.     mov    cl,PC_KBD_SCAN
  1718.     mov    PC_DKEY_SCAN,cl
  1719. NX_no_dkey:
  1720.     ret
  1721.  
  1722.  
  1723. NX_chk_dkey:
  1724. ;-------------
  1725. ;    entry:    al = character to combine with previous dead key
  1726. ;        SI = PC->
  1727. ;    exit:    al = combined character
  1728.  
  1729.     mov    di, PC_LAST_DKEY
  1730.     cmp    di, -1
  1731.      je    NX_chk_dkey_done
  1732.     mov    cl, al
  1733.     shl    di, 1
  1734.     mov    di, NX_dkeyv$[di]
  1735.     call    NX_scanstr
  1736.     cmp    di, -1
  1737.      je    NX_bad_dkey
  1738.  
  1739.     mov    bx, PC_LAST_DKEY
  1740.     shl    bx, 1
  1741.     mov    bx, NX_dkeyx$[bx]
  1742.     mov    al, [bx+di]
  1743.     jmps    NX_chk_dkey_done
  1744.  
  1745. NX_bad_dkey:
  1746.     mov    cl,PC_DKEY_SCAN        ; swap old and new scan codes
  1747.     xchg    cl,PC_KBD_SCAN
  1748.     mov    PC_DKEY_SCAN,cl
  1749.     mov    di,PC_LAST_DKEY
  1750.     cmp    al, ' '            ; DEADKEY + ' ' --> DEAD
  1751.     je    NX_dkey_blank        ; don't return 2nd char if blank
  1752.     mov    PC_DKEY_BUFF,al        ; else save second character
  1753. NX_dkey_blank:
  1754.     test    di, di            ; (has index zero)
  1755.     jnz    NX_chk_space            
  1756.     mov    al,0f9h                ; insert IBM decimal point char
  1757.     jmps    NX_chk_dkey_done
  1758. NX_chk_space:
  1759.     mov    al, NX_dead_key$[di]
  1760. NX_chk_dkey_done:
  1761.     mov    PC_LAST_DKEY, -1
  1762.     ret
  1763.  
  1764.  
  1765.  
  1766. NX_xlt_7to8:        ; translate 7 to 8 bit code
  1767. ;-------------
  1768. ;    entry:    cl = character to translate
  1769. ;        SI = PC->
  1770. ;    exit:    cl = translated character
  1771.  
  1772.     push    bx                ; keep every register safe
  1773.     cmp    PC_NATNLMODE,3            ; 7 bit, nat scn, nat kbd?
  1774.     jne    NX_xlt78_not_xlt        ; not Ctrl/Alt/F4 mode
  1775.  
  1776.     mov    bx,offset NX_n7to8tbl$        ; scan thru 7 bit eqv chars
  1777. NX_xlt78_loop:
  1778.     cmp    byte ptr [bx],0            ; see if end of translate tbl
  1779.     jz    NX_xlt78_not_xlt        ; yes, check for paragraph
  1780.     cmp    cl,[bx]                ; see if translation required
  1781.     jz    NX_xlt78_7to8            ; yes, one of those characters
  1782.     inc    bx                ; no, may be next time
  1783.     jmps    NX_xlt78_loop            ; give it another try
  1784.  
  1785. NX_xlt78_7to8:
  1786.     sub    bx,offset NX_n7to8tbl$        ; see how many chars checked
  1787.     mov    cl,NX_n7to8chr$[bx]        ; get substitution
  1788.  
  1789. NX_xlt78_not_xlt:
  1790.     pop    bx
  1791.     ret
  1792.  
  1793.  
  1794. NX_scanstr:        ; search for a character in a table
  1795. ;------------
  1796. ;    entry:    cl = character to look for
  1797. ;        di = address of string to search
  1798. ;    exit:    cl = unmodified
  1799. ;        di = relative position of cl in string if match
  1800. ;        di = 0xffff if no match
  1801.  
  1802.     push    ax                ; save our scratch register
  1803.     mov    ax, di                ; save table in ax
  1804. NX_scanstr_loop:
  1805.     cmp    byte ptr [di], 0        ; end of string?
  1806.     je    NX_scanstr_nomatch        ; yes, definitly no match
  1807.     cmp    cl, [di]            ; match with character
  1808.     je    NX_scanstr_match        ; yes, found it
  1809.     inc    di                ; no, next character
  1810.     jmps    NX_scanstr_loop        ; another try...
  1811.  
  1812. NX_scanstr_nomatch:
  1813.     mov    di, 0ffffh            ; get failure code
  1814.     jmps    NX_scanstr_done        ; return it
  1815. NX_scanstr_match:
  1816.     sub    di, ax                ; offset to start of string
  1817. NX_scanstr_done:                ; return code
  1818.     pop    ax                ; restore scratch register
  1819.     ret
  1820.  
  1821.  
  1822. ;----------------
  1823. NX_conout_xlat:
  1824. ;----------------
  1825. ;    Input:    AL = character to translate
  1826. ;        SI = PC->
  1827. ;    Output:    AL = translated character
  1828. ;        all others maintained
  1829.  
  1830.     push    bx                ; keep every register safe
  1831.     cmp    PC_NATNLMODE, 3            ; 7 bit, nat scn, nat kbd?
  1832.     jne    NX_conout_not_xlt        ; not Ctrl/Alt/F4 mode
  1833.     cmp    PC_TMP_US_FLG, 0        ; temparaily 7/8 xlt off
  1834.     mov    PC_TMP_US_FLG, 0        ; reset temporary US display
  1835.     jnz    NX_conout_not_xlt        ; leap if disabled
  1836.  
  1837.     mov    bx, offset NX_n7to8tbl$    ; scan thru 7 bit eqv chars
  1838. NX_conout_loop:
  1839.     cmp    byte ptr [bx], 0        ; see if end of translate tbl
  1840.      jz    NX_conout_not_xlt        ; yes, check for paragraph
  1841.     cmp    al, [bx]            ; see if translation required
  1842.      jz    NX_conout_7to8        ; yes, one of those characters
  1843.     inc    bx                ; no, may be next time
  1844.     jmps    NX_conout_loop        ; give it another try
  1845.  
  1846. NX_conout_7to8:
  1847.     sub    bx, offset NX_n7to8tbl$    ; see how many chars checked
  1848.     mov    al, NX_n7to8chr$[bx]        ; get substitution
  1849.  
  1850. NX_conout_not_xlt:
  1851.     cmp    al, 236                ; this is how we store para
  1852.      jne    NX_conout_not_para        ; not paragraph char
  1853.     mov    al, 21                ; IBM sez: paragraph = Ctrl/U
  1854. NX_conout_not_para:
  1855.     pop    bx
  1856.     ret                    ; back to display routine
  1857.  
  1858.  
  1859.  
  1860. eject
  1861.  
  1862. ; Serial Console output - XIOS function 2
  1863. ; Entry :
  1864. ;    DL = virtual console number
  1865. ;    CL = output char
  1866. fl_io_conout:
  1867. ;------------
  1868.     cmp    dl,NUM_VIR_CONS        ; master console ?
  1869.     jb    do_conout
  1870.     cmp    dl,MAX_VIR_CONS        ; is it legal ?
  1871.     jb    fl_conout_test
  1872. do_conout:
  1873.     jmp    io_conout
  1874.  
  1875. dumb_conout:
  1876. ; we used to call io_conout with the virtual console number. This only
  1877. ; worked when previous serial terminals had only one virtual per physical.
  1878. ; (Windows1.A86 calculates the AUX device by subtracting NUM_VIR_CONS-1).
  1879. ; NB. Will screw up with SR when we combine because we test for Sunriver
  1880. ; station using the VCon number, which is now wrong.
  1881.     add    al,NUM_VIR_CONS-1    ; 
  1882.     mov    dl,al            ; VC number for dumb terminals
  1883.     jmp    io_conout
  1884.  
  1885. fl_conout_test:
  1886.     push    dx            ; save vs
  1887.     call    get_ccb            ; di -> ccb
  1888.     mov    dl,C_PC[di]        ; logical console number
  1889.     call    test_pcterm@        ; test if emulation required
  1890.     mov    al,dl            ; save logical physical number
  1891.     pop    dx
  1892.     jz    dumb_conout        ; must be dumb terminal
  1893.  
  1894. fl_conout:
  1895. ;---------
  1896.     call    point_vc@        ; BX -> screen structure
  1897.     test    VC_INSTALLED,0ffh    ; flush installed yet
  1898.     jnz    fl_conout1
  1899.     cmp    active_vc$,dl
  1900.     je    fl_conout1
  1901.  
  1902.     push dx ! push cx
  1903.     call    delay1            ; no wait...
  1904.     pop cx ! pop dx
  1905.     jmps    fl_conout
  1906.  
  1907. fl_conout1:
  1908.     call    get_mx            ; make sure we get the MX
  1909.     push    es
  1910.     mov    dx,PC_SEGMENT        ; make sure cursor reflects ROS value
  1911.     mov    es,dx
  1912.     mov    dx,es:cursor_posn_40    ; assume page zero
  1913.     pop    es
  1914.     call    pc_point_curs@
  1915.     mov    VC_OFFSET,ax
  1916.     mov    VC_CURSOR,dx        ; cursor row, column
  1917.     mov    al,cl            ; AL, CL = character
  1918.     push    bx
  1919.     call    VC_VECTOR
  1920.     pop    bx
  1921.     push    es
  1922.     mov    ax,PC_SEGMENT        ; make sure cursor reflects ROS value
  1923.     mov    es,ax
  1924.     mov    ax,VC_CURSOR        ; finally update ROS values
  1925.     mov    es:cursor_posn_40,ax    ; assume page zero
  1926.     pop    es
  1927.     mov    VC_MX,0            ; release semaphore
  1928.     ret
  1929.  
  1930.  
  1931.  
  1932. eject
  1933.  
  1934. ; List output status - XIOS function 2
  1935. ; Entry :
  1936. ;    DL = list device number
  1937. ; Exit :
  1938. ;    AL = output status
  1939. fl_io_listst:
  1940. ;------------
  1941.     call    test_pcterm_printer@    ; is it a PC terminal ?
  1942.     jnz    fl_listst        ; yes, handle differently
  1943.     jmp    io_listst
  1944.  
  1945. fl_listst:
  1946.     mov    bl,dl
  1947.     mov    bh,0            ; BX = list device #
  1948.     sub    bx,3            ; BX = serial port
  1949.     mov    dl,port2pc_table$[bx]    ; DL = logical physical console number
  1950.     call    conout_serial_stat@    ; get output status of the serial port
  1951.     mov    ah,10h            ; assume not ready
  1952.     test    al,al
  1953.      jz    fl_listst1
  1954.     mov    ah,90h            ; device ready, PC Style
  1955. fl_listst1:
  1956.     ret 
  1957.  
  1958. eject
  1959.  
  1960. ; List output - XIOS function 4
  1961. ; Entry :
  1962. ;    DL = list device number
  1963. ;    CL = output char
  1964. fl_io_list:
  1965. ;------------
  1966.     call    test_pcterm_printer@    ; is it a PC terminal ?
  1967.     jnz    fl_list            ; yes, handle specially
  1968.     jmp    io_list
  1969.  
  1970. fl_list:
  1971. ;    entry:    CL = character to write
  1972. ;        DL = list device number
  1973. ; send the character to the aux port of the PC Terminal using an Escape
  1974. ; sequence.
  1975. ; NOTE:-
  1976. ; ESCAPE chars are blocked into pairs because of problem on Wyse 60's
  1977. ; Still potential problem printing string:-  1Bh,61h  
  1978.  
  1979.     push    cx
  1980.     mov    bl,dl
  1981.     mov    bh,0            ; BX = list device #
  1982.     sub    bx,3            ; BX = serial port
  1983.     mov    dl,port2pc_table$[bx]    ; DL = logical physical console number
  1984. fl_list1:
  1985.     push    dx
  1986.     call    conout_serial_stat@    ; get output status of the serial port
  1987.     pop    dx
  1988.     test    al,al            ; is it ready ?
  1989.      jnz    fl_list2
  1990.     push    dx
  1991.     mov    cx,P_DELAY        ; delay until it is
  1992.     mov    dx,1
  1993.     call    supif@
  1994.     pop    dx
  1995.      jmps    fl_list1
  1996. fl_list2:
  1997.     mov    al,dl            ; AL = logical physical console number
  1998.     call    point_pc1@        ; get pointer to PC_ structure in SI
  1999.     pop    cx
  2000.     cmp    cl,ESC            ; lets block up escape sequences
  2001.     jne    send_on
  2002.     xchg    cl,PC_LASTCHAR
  2003.     cmp    cl,0
  2004.     jne    send_on            ; CL=ESC
  2005.     ret
  2006.     
  2007. send_on:
  2008.     push    cx            ; save the char
  2009.     call    ser_mx            ; get serial semaphore
  2010.     mov    di, offset printer_on    ; turn on printer
  2011.     call    ser_write
  2012.  
  2013.     mov    al,PC_LASTCHAR
  2014.     mov    PC_LASTCHAR,0        ; clear ESCAPE flag
  2015.     cmp    al,0
  2016.     je    ship_1
  2017.     call    tmp_write        ; write out ESCAPE char in AL
  2018.     pop    ax            ; get original character
  2019.  
  2020.     push    ax            ; and re-save
  2021.     mov    di, offset printer_off    ; turn off printer
  2022.     cmp    al,2[di]        ; is it OFF escape sequence
  2023.     jne    ship_1
  2024.     call    ser_write        ; yes - turn printer off
  2025.     mov    di, offset printer_on    ; and then back on
  2026.     call    ser_write
  2027.  
  2028. ship_1:
  2029.     pop    ax            ; recover character to write in AX
  2030.     call    tmp_write        ; write out one character
  2031.     mov    di, offset printer_off    ; turn off printer
  2032.     call    ser_write
  2033.     mov    PC_BUSY,0        ; release serial semaphore
  2034.     mov    cl,P_DISPATCH        ; dispatch to give the screen a chance
  2035.     jmp    supif@
  2036.  
  2037. ; Print last caharcter if one outstanding
  2038. ; Called from io_close
  2039. ; Enter DL = LIST device number
  2040. print_lastchar@:
  2041. ;---------------
  2042.     mov    bl,dl
  2043.     mov    bh,0            ; BX = list device #
  2044.     sub    bx,3            ; BX = serial port
  2045.     mov    dl,port2pc_table$[bx]    ; DL = logical physical console number
  2046.     mov    al,dl            ; AL = logical physical console number
  2047.     call    point_pc1@        ; get pointer to PC_ structure in SI
  2048.     xor    al,al
  2049.     xchg    al,PC_LASTCHAR
  2050.     cmp    al,0
  2051.     je    print_exit
  2052.     push    ax            ; save last char
  2053.     push    si
  2054. print1:
  2055.     push    dx
  2056.     call    conout_serial_stat@    ; get output status of the serial port
  2057.     pop    dx
  2058.     test    al,al            ; is it ready ?
  2059.      jnz    print2
  2060.     push    dx
  2061.     mov    cx,P_DELAY        ; delay until it is
  2062.     mov    dx,1
  2063.     call    supif@
  2064.     pop    dx
  2065.      jmps    print1
  2066. print2:
  2067.     pop    si
  2068.     call    ser_mx            ; get serial semaphore
  2069.     mov    di, offset printer_on    ; turn on printer
  2070.     call    ser_write
  2071.  
  2072.     pop    ax            ; recover character to write in AX
  2073.     call    tmp_write        ; write out one character
  2074.     mov    di, offset printer_off    ; turn off printer
  2075.     call    ser_write
  2076.     mov    di, offset printer_off    ; turn off printer twice "Wyse 60"
  2077.     call    ser_write
  2078.     mov    PC_BUSY,0        ; release serial semaphore
  2079. print_exit:
  2080.     ret
  2081.  
  2082.  
  2083. ; Enter DL = LIST device number
  2084. test_pcterm_printer@:
  2085. ;-------------------
  2086.     push    cx            ; save char
  2087.     push    dx            ; and device
  2088.     mov    bl,dl
  2089.     mov    bh,0            ; BX = list device #
  2090.     sub    bx,3            ; BX = serial port number
  2091.     test    mu_com_type$[bx],01    ; is it set up for terminal
  2092.     jz    is_print
  2093.     mov    al,su_mu_vs$[bx]    ; get setup byte for serial port
  2094.     test    al,PCTERM_EMU        ; test setup bit for installed port
  2095. is_print:
  2096.     pop    dx
  2097.     pop    cx
  2098.     ret                ;  to see if pcterm emulation required
  2099.  
  2100.  
  2101.  
  2102.  
  2103. ; Screen switch - XIOS function 7
  2104. ; Entry: 
  2105. ;    DL = virtual console to switch to
  2106. fl_io_switch:
  2107. ;------------
  2108.     cmp    dl,NUM_VIR_CONS        ; master console ?    
  2109.     jae    fl_switch
  2110.     jmp    io_switch        ; yes .. go to standard routine
  2111.  
  2112.  
  2113. fl_switch:
  2114. ;---------
  2115.     call    point_pc        ; get PC_ structure
  2116.     mov    bl,PC_TOP_SCREEN    ; get current top VC
  2117.     xor    bh,bh
  2118.     shl    bx,1
  2119.     mov    bx,ccb_list$[bx]    ; get top screen ccb
  2120.     test    C_STATE[bx],CSM_NOSWITCH ; switch allowed ?
  2121.     jnz    no_switch        ; no...
  2122.     push    dx
  2123.     push    si
  2124.     call    get_all_mxs        ; block all updates
  2125.     pop    si
  2126.     pop    dx
  2127.     call    point_vc@        ; new vc's VC_ structure
  2128.     and    VC_MODE,not MATCH_BIT    ; full screen on top
  2129.     xchg    dl,PC_TOP_SCREEN    ; new top screen
  2130.     call    point_vc@        ; old VC_ structure
  2131.     or    VC_MODE,MATCH_BIT    ; background old screen
  2132.     cli                ; stop Flush being dispatched in
  2133.     push    si
  2134.     mov    al,PC_TOP_SCREEN    ; new vc number to AL
  2135.     call    find_flush_pin        ; find flush and PIN pd's and patch
  2136.     pop    si            ;  vc number
  2137.     mov    dl,PC_TOP_SCREEN    ; new vc number
  2138.     
  2139.     call    point_vc@        ; new VC_
  2140.     or    VC_UPDATE,UPDATE_SL    ; we will want a statline update
  2141.     test    VC_MODE,CURSOR_BIT
  2142.     jz    switch_cursor_off
  2143.     call    cursor_on        ; make sure cursor turned on
  2144.     jmps    switch1
  2145. switch_cursor_off:
  2146.     call    cursor_off        ; or off
  2147. switch1:    
  2148.     lea    di,VC_PAGE_SAVE        ; get saved entry for screen segment
  2149.     or    ds:PG_ATTR,PGA_DIRTY    ; set it to dirty - FLUSH will 
  2150.                     ; then update our screen for us
  2151.     mov    bx,v386_ptr$        ; get pointer to 386 specific table
  2152.     mov    es,ptbl_seg        ; get page table segment
  2153.     mov    di,(CRT_SEG/256*4)    ; get entry for screen segment
  2154.     or    PG_ATTR,PGA_DIRTY    ; make sure screen is set dirty
  2155.                     ; when it next gets dispatched
  2156.     sti
  2157.     call    free_all_mxs
  2158. no_switch:
  2159.     ret
  2160.  
  2161. ; Find current vc's FLUSH and PIN process descriptors
  2162. ;  and patch VC number to new VC
  2163. ; Entry:    
  2164. ;    DL = VC of current flush
  2165. ;    AL = new VC number
  2166. ; Exit:
  2167. ;    BX = PD of flush rsp
  2168. find_flush_pin:
  2169. ;--------------
  2170.     push    es
  2171.     mov    ah,2            ; for PIN and FLUSH search
  2172.     mov    bx,thrdrt$        ; search through thread list
  2173.     push ds ! pop es        ; for FLUSH process
  2174. find_flush1:
  2175.     cmp    dl,P_CONS[bx]        ; is process same VC number
  2176.     jne    get_next
  2177.     lea    di,P_NAME[bx]        ; point to process name
  2178.     mov    si,offset flushstr
  2179.     mov    cx,5
  2180.     repe    cmpsb            ; is it 'Flush'
  2181.     jne    not_flush        ; no .. try PIN
  2182.     mov    P_CONS[bx],al        ; change flush rsps' vc number
  2183.     dec    ah
  2184.     jz    found_both
  2185. not_flush:
  2186.     lea    di,P_NAME[bx]        ; point to process name
  2187.     mov    si,offset PINstr
  2188.     mov    cx,3
  2189.     repe    cmpsb            ; is it 'PIN'
  2190.     jne    get_next        ; no try next
  2191.     mov    P_CONS[bx],al        ; change flush rsps' vc number
  2192.     dec    ah
  2193.     jz    found_both
  2194. get_next:
  2195.     mov    bx,P_THREAD[bx]        ; link to next PD
  2196.     or    bx,bx
  2197.     jnz    find_flush1        ; keep searching
  2198. found_both:
  2199.     pop    es
  2200.     ret
  2201.  
  2202.  
  2203.  
  2204. ; Status line update - XIOS function 8
  2205. fl_io_statline:
  2206. ;--------------
  2207.     push    cx
  2208.     push    dx
  2209.     mov    bx,rlr$            ; get pd
  2210.     mov    dl,P_CONS[bx]        ; get process VC number
  2211.     call    get_ccb            ; di -> ccb
  2212.     mov    dl,C_PC[di]        ; logical console number
  2213.     cmp    dl,0            ; main screen
  2214.      je    fl_statline_norm
  2215.     call    test_pcterm@        ; test if emulation required
  2216.      jz    fl_statline_dumb    ; must be dumb terminal
  2217.  
  2218. fl_statline_norm:
  2219.     pop    dx
  2220.     pop    cx
  2221.     jmp    io_statline        ;  else call master statline
  2222.  
  2223. fl_statline_dumb:
  2224. ;---------------
  2225.     pop    dx
  2226.     pop    cx
  2227.     sub    ax,ax        ; status update - do nothing for now
  2228.     mov    bx,ax
  2229.     ret
  2230.  
  2231.  
  2232. ; Keyboard mode switch - XIOS function 32
  2233. ;  entry:    dl = vcons number
  2234. ;        cl = following Bits used
  2235. ;             Bit 0 : = set when DOS program executes
  2236. ;                   reset on termination
  2237. ;             Bit 1 : = process requires 25 lines
  2238. ;             Bit 2 : = process uses ANSI escape sequences
  2239. ;             Bit 3 : = process uses Ros INT 10h
  2240. ;             Bit 4 : = process accesses PC video hardware
  2241. ;
  2242.  
  2243. fl_pc_kbd:
  2244. ;---------
  2245.     cmp    dl,NUM_VIR_CONS    ; master console ?
  2246.     jae    fl_pckbd_test
  2247. pc_kbd_dumb:
  2248.     jmp    pc_kbd
  2249.  
  2250. fl_pckbd_test:
  2251.     push    dx            ; save vs
  2252.     call    get_ccb            ; di -> ccb
  2253.     mov    dl,C_PC[di]        ; logical console number
  2254.     call    test_pcterm@        ; test if emulation required
  2255.     pop    dx
  2256.     jz    pc_kbd_dumb        ; must be dumb terminal
  2257.  
  2258.  
  2259. fl_pckbd:
  2260. ;--------
  2261.     call    point_vc@        ; BX -> screen structure
  2262.     test    cl,1            ; PC mode or CP/M mode?
  2263.      jnz    keybd_pc        ; skip if switching into DOS
  2264.     call    get_mx            ; make sure we get the MX
  2265.     mov    dx,VC_CURSOR
  2266.     call    vc_out_lf@        ; do a line feed
  2267.     mov    dx,VC_CURSOR
  2268.     call    z_up@            ; back up again
  2269.     mov    dx,VC_CURSOR
  2270.     call    z_erase_eos@        ; erase end of screen
  2271.     mov    VC_CRT_ROWS,CRT_ROWS_C    ; back to 24 lines
  2272.     and    VC_MODE,not PCMODE_BIT    ; turn off PC mode bit
  2273.     mov    VC_CUR_TYPE,MONO_CURSOR
  2274.     or    VC_MODE,CURSOR_BIT
  2275.     call    cursor_on        ; make sure cursor turned on
  2276.     mov    VC_MX,0            ; release the MX
  2277.     mov    sl_pc_flag$,0ffh    ; turn on the status
  2278.     jmps    keybdf_ret
  2279.  
  2280. keybd_pc:                ; switch into DOS mode
  2281.     or    VC_MODE,PCMODE_BIT
  2282.     mov    al,CRT_ROWS_C        ; assume 24 lines
  2283.     test    cl,CA_25LINES        ; do we require 25 line mode
  2284.     jz    set_lines        ; no 
  2285.     mov    sl_pc_flag$,0h        ; turn off status
  2286.     push    VC_CURSOR        ; save the current cursor position
  2287.     mov    dx,CRT_ROWS_C*256    ; start of bottom line
  2288.     call    pc_point_curs@
  2289.     mov    VC_OFFSET,ax        ; set cursor position there
  2290.     mov    VC_CURSOR,dx
  2291.     call    z_erase_eos@        ; erase end of screen
  2292.     pop    dx            ; now restore cursor
  2293.     call    pc_point_curs@
  2294.     mov    VC_OFFSET,ax        ; remember offset too
  2295.     mov    VC_CURSOR,dx
  2296.     mov    al,CRT_ROWS_P        ; set 25 lines
  2297. set_lines:
  2298.     mov    VC_CRT_ROWS,al
  2299.  
  2300. keybdf_ret:
  2301.     sub    ax,ax
  2302.     ret
  2303.  
  2304.  
  2305. ; Return keyboard shift status - XIOS function 33
  2306. ;  entry:    dl = vcons number
  2307. ;  exit:    SI = PC_ pointer for VC
  2308. ; *** SI returned for utility purposes ***
  2309. ; Returns shift byte in AL:
  2310. ; extended keyboard shift status in AH 
  2311.  
  2312. fl_pc_shifts:
  2313. ;------------
  2314.     cmp    dl,NUM_VIR_CONS    ; master console ?
  2315.     jae    fl_shifts_test
  2316. pc_shifts_dumb:
  2317.     jmp    pc_shifts
  2318.  
  2319. fl_shifts_test:
  2320.     call    get_ccb            ; di -> ccb
  2321.     mov    dl,C_PC[di]        ; logical console number
  2322.     call    test_pcterm@        ; test if emulation required
  2323.     jz    pc_shifts_dumb        ; must be dumb terminal
  2324.     mov    al,dl            ; logical console number
  2325.     call    point_pc1@        ; get PC_ ->
  2326.  
  2327.     mov    ch,0
  2328.     test    PC_NATNLSTAT,NX_nkbd_bit ; is it US keyboard
  2329.     jz    norm_kbd        ; yes...
  2330.     test    PC_KBD_TYPE,NX_enhanced ; international enchanced keyboard
  2331.     jz    norm_kbd        ; no .. normal keyboard
  2332.     mov    ch,1
  2333. norm_kbd:
  2334.     mov    ah,PC_KFLAG1
  2335.     and    ah,SYS_SHIFT
  2336.     mov    cl,5
  2337.     shl    ah,cl
  2338.     mov    al,PC_KFLAG1
  2339.     and    al,73h            ; get rid of sys_shift,hold and insert
  2340.     or    ah,al            ; mash into AH
  2341.     mov    al,PC_KFLAG3        ; get extended status bits
  2342.     and    al,0ch            ; remove hidden flag bits
  2343.     or    ah,al            ; and merge
  2344.     
  2345.     mov    al,PC_KFLAG        ; get normal status bits into al
  2346.     or    ch,ch
  2347.     jz    norm_kbd1
  2348.     test    PC_KFLAG1,L_ALT        ; is left ALT down
  2349.     jnz    norm_kbd1        ; yes
  2350.     and    al,not ALT_BIT        ; else make sure no ALT status
  2351. norm_kbd1:                ; bit from Right ALT key
  2352.     ret
  2353.  
  2354.  
  2355.  
  2356.  
  2357. ; XIOS function 39:  Device Block Read/Write
  2358. ; Entry:    DH = device type:
  2359. ;            0 = console output
  2360. ;            1 = printer output
  2361. ;            2 = aux. input
  2362. ;            3 = aux. output
  2363. ;        DL = device number:
  2364. ;        CX = number of characters
  2365.  
  2366. ;        Param. block at SP + 6:
  2367. ;            word ptr 6[bp] = buffer offset
  2368. ;            word ptr 8[bp] = buffer segment
  2369. ;            word ptr 10[bp] = same as CX
  2370. ;            word ptr 12[bp] = same as DX
  2371.  
  2372. ; Exit:        AX = number of characters transferred (at least 1)
  2373. ;        Updated Param. block on stack 
  2374. ;         buff. off. = last char + 1
  2375. ;         buff. seg. = unchanged
  2376. ;         count = # remaining in block (usually 0)
  2377. ;         dev. info = unchanged
  2378.  
  2379.  
  2380. fl_io_devio:
  2381. ;-----------
  2382.     cmp    dh,0        ; console output
  2383.     jne    fl_io_devio1    ; no..
  2384.     cmp    dl,NUM_VIR_CONS    ; master console ?
  2385.     jae    fl_devio_test    ; no must be serial
  2386. fl_io_devio1:
  2387.     cmp    dh,1
  2388.     je    fl_devio_list
  2389.     jmp    io_devio
  2390.  
  2391. fl_io_devio_dumb:
  2392. ; we used to call io_conout with the virtual console number. This only
  2393. ; worked when previous serial terminals had only one virtual per physical.
  2394. ; (Windows1.A86 calculates the AUX device by subtracting NUM_VIR_CONS-1).
  2395. ; NB. Will screw up with SR when we combine because we test for Sunriver
  2396. ; station using the VCon number, which is now wrong.
  2397.     add    al,NUM_VIR_CONS-1    ; 
  2398.     mov    dl,al            ; logical console number for dumb terms
  2399.     jmp    io_devio
  2400.  
  2401. fl_devio_test:
  2402.     push    dx            ; save vs
  2403.     call    get_ccb            ; di -> ccb
  2404.     mov    dl,C_PC[di]        ; logical console number
  2405.     call    test_pcterm@        ; test if emulation required
  2406.     mov    al,dl            ; save logical physical number
  2407.     pop    dx
  2408.     jz    fl_io_devio_dumb    ; must be dumb terminal
  2409.  
  2410. fl_devio:
  2411. ;--------
  2412.     mov    bp,sp
  2413.     cmp    word ptr 10[bp],0
  2414.      je    devio_ret
  2415.     push    ds
  2416.     lds    si,6[bp]        ; get output buffer address
  2417.     lodsb
  2418.     pop    ds
  2419.     mov    6[bp],si        ; update buffer offset
  2420.     dec    word ptr 10[bp]        ; decrement char output count
  2421.     mov    cl,al            ; char to CL
  2422.     push    dx            ; save VC number
  2423.     call    fl_conout        ; output char
  2424.     pop    dx
  2425.     jmps    fl_devio
  2426. devio_ret:
  2427.     ret
  2428.  
  2429. fl_devio_list:
  2430. ;----------------
  2431.     mov    bp,sp
  2432.     cmp    word ptr 10[bp],0
  2433.      je    devio_ret
  2434.     push    ds
  2435.     lds    si,6[bp]        ; get output buffer address
  2436.     lodsb
  2437.     pop    ds
  2438.     mov    6[bp],si        ; update buffer offset
  2439.     dec    word ptr 10[bp]        ; decrement char output count
  2440.     mov    cl,al            ; char to CL
  2441.     push    dx            ; save device number
  2442.     call    fl_io_list            ; output char
  2443.     pop    dx
  2444.     jmps    fl_devio_list
  2445.  
  2446. eject
  2447.  
  2448.  
  2449. ; This function handles Int 10h calls from PC DOS applications.
  2450. video_int:
  2451. ;---------
  2452.     sti
  2453.     push    ds
  2454.     mov    ds,cs:sysdat$
  2455.     push    di
  2456.     mov    di,rlr$
  2457.     cmp    P_CONS[di],NUM_VIR_CONS
  2458.      jae    vid_int1_test        ; filter out serial consoles
  2459. vid_int_dumb:
  2460.     pop    di
  2461.     pop    ds
  2462.     jmpf    cs:dword ptr int10_addr    ; go to standard XIOS handler
  2463.  
  2464. vid_int1_test:
  2465.     push    dx            ; save dx
  2466.     mov    dl,P_CONS[di]        ; get VC number
  2467.     call    get_ccb            ; di -> ccb
  2468.     mov    dl,C_PC[di]        ; logical console number
  2469.     call    test_pcterm@        ; test if emulation required
  2470.     pop    dx
  2471.     jz    vid_int_dumb        ; must be dumb terminal
  2472.  
  2473.  
  2474. vid_int1:
  2475.     cld
  2476.     push    si 
  2477.     push    bx            ; extra for temp store
  2478.     push    es
  2479.     push    bp ! push bp
  2480.     push    dx ! push cx ! push bx ! push ax
  2481.     mov    bp,sp
  2482.  
  2483.     mov    di,rlr$            ; get calling process
  2484.     mov    dl,P_CONS[di]        ; get its virtual console #
  2485.     mov    VID_VCONS[bp],dl    ; set virtual console
  2486.  
  2487.     call    point_vc@        ; get virtual console structure
  2488.     call    get_mx            ; get screen semaphore
  2489.     mov    ax,PC_SEGMENT        ; make sure cursor reflects ROS value
  2490.     mov    es,ax
  2491.     mov    ax,es:cursor_posn_40    ; assume page zero
  2492.     mov    VC_CURSOR,ax        ; cursor row, column
  2493.     mov    al,VID_AH[bp]        ; get video function
  2494.     cmp    al,15            ; supported range
  2495.      ja    v_i_exit        ; ignore if above
  2496.  
  2497.     cbw                ; make it a word
  2498.     mov    di,ax            ; DI = sub function #
  2499.     shl    di,1            ; entry into word table
  2500.     call    v_i_table[di]        ; invoke subfunction
  2501.  
  2502. v_i_exit:
  2503.     mov    ax,PC_SEGMENT        ; make sure cursor reflects ROS value
  2504.     mov    es,ax
  2505.     mov    ax,VC_CURSOR        ; finally update ROS values
  2506.     mov    es:cursor_posn_40,ax    ; assume page zero
  2507.     mov    VC_MX,0            ; release semaphore
  2508.  
  2509.     pop    ax ! pop bx ! pop cx ! pop dx
  2510.     pop    bp ! pop bp        ; restore all registers
  2511.     pop    es 
  2512.     pop    bx            ; temp store
  2513.     pop    si ! pop di
  2514.  
  2515.     pop    ds            ; back to user data segment
  2516.     iret
  2517.  
  2518.  
  2519. v_i_table    dw    v_i_smode        ; 0 set video mode
  2520.         dw    v_i_cursortype        ; 1 set cursor type
  2521.         dw    v_i_setcursor        ; 2 set cursor position
  2522.         dw    v_i_getcursor        ; 3 get cursor position
  2523.         dw    v_i_lpen        ; 4 read light pen
  2524.         dw    v_i_spage        ; 5 select display page
  2525.         dw    v_i_scroll_up        ; 6 scroll window up
  2526.         dw    v_i_scroll_down        ; 7 scroll window down
  2527.         dw    v_i_read        ; 8 get attr/char at cursor
  2528.         dw    v_i_write_attr        ; 9 set attr/char at cursor
  2529.         dw    v_i_write_char@        ; 10 set char (curr.attr) @ cur
  2530.         dw    v_i_ignore        ; 11 pallette / border control
  2531.         dw    v_i_ignore        ; 12 graphics pix write
  2532.         dw    v_i_ignore        ; 13 graphics pix read
  2533.         dw    v_i_write_tty        ; 14 write char stream as a tty
  2534.         dw    v_i_gmode        ; 15 current video state
  2535.  
  2536. v_i_ignore:
  2537. ;----------
  2538.     ret
  2539.  
  2540. v_i_smode:        ; 0 set video mode
  2541. ;---------
  2542. ;    Entry:    VID_AL = new video mode
  2543. ;
  2544. ;    Modes:    0, 1:    40x25 16 color        (CGA, EGA, MCGA, VGA)
  2545. ;        2, 3:    80x25 16 color        (CGA, EGA, MCGA, VGA)
  2546. ;        4, 5:    320x200 4 color        (CGA, EGA, MCGA, VGA)
  2547. ;        6:    640x200 2 color        (CGA, EGA, MCGA, VGA)
  2548. ;        7:    80x25 monochrome    (MDA, EGA, VGA)
  2549. ;        8-C:    -not supported-        (-PC jr only-)
  2550. ;        D:    320x200 16 color    (EGA, VGA)
  2551. ;        E:    640x200 16 color    (EGA, VGA)
  2552. ;        F:    640x350 monochrome    (EGA, CGA)
  2553. ;        10:    640x350 16 color    (EGA, VGA)
  2554. ;        11:    640x480 monochrome    (EGA, CGA)
  2555. ;        12:    640x480 16 color    (EGA, VGA)
  2556. ;        13:    320x200 256 color    (MCGA, VGA)
  2557. ;        40:    640x400 2 color        (Olivetti M24/M28)
  2558. ;        48:    640x400 2 color        (Olivetti M24/M28)
  2559. ;
  2560.  
  2561.     mov    al,VID_AL[bp]        ; get video mode
  2562.     cmp    al,7
  2563.      je    v_i_smode1        ; is it an 80x25 mode
  2564.     cmp    al,2            ; if so force a switch to
  2565.      je    v_i_smode1        ; mode 7 (80x25 monochrome)
  2566.     cmp    al,3
  2567.      je    v_i_smode1
  2568.     mov    VC_MX,0            ; release semaphore
  2569.     mov    ax,offset bad_mode_msg
  2570.     mov    cx,BAD_MODE_MSG_LEN
  2571.     jmp    proc_abort@        ; terminate with an error msg
  2572.     
  2573. v_i_smode1:
  2574.     mov    VID_AL[bp],7        ; force to mode 7
  2575.     or    VC_BLINK,20h        ; always re-enable blink attribute
  2576.     sub    di,di
  2577.     mov    cx,CRT_ROWS_P*CRT_COLS
  2578.     mov    ax,' '+(7 shl 8)
  2579.     jmp    put_crt_s@
  2580.  
  2581. v_i_cursortype:        ; 1 set cursor type
  2582. ;--------------
  2583. ;    Entry:    VID_CH, VID_CL = cursor type
  2584.  
  2585.     mov    cx,VID_CX[bp]        ; get new cursor type
  2586.     mov    VC_CUR_TYPE,cx        ; save the new cursor
  2587.     test    ch,60h            ; setting bits 5 or 6 turns cursor off
  2588.     jnz    v_i_off
  2589.     and    ch,0fh            ; mask start cursor line
  2590.     and    cl,0fh            ; and end
  2591.     cmp    ch,cl            ; if start > end
  2592.     ja    v_i_off            ; then turn cursor off
  2593.     jmp    z_cursor_on        ; else make sure cursor ON
  2594. v_i_off:
  2595.     jmp    z_cursor_off
  2596.  
  2597. v_i_setcursor:        ; 2 set cursor position
  2598. ;-------------
  2599. ;    Entry:    VID_DH, _DL = row, column
  2600. ;        VID_BH = page number (ignored by us)
  2601.  
  2602.     mov    dx,VID_DX[bp]
  2603.     cmp    dh,VC_CRT_ROWS
  2604.      jb    pc_v_row_ok            ; if row is too big
  2605.     mov    dh,VC_CRT_ROWS            ;   then clip it
  2606.     dec    dh
  2607. pc_v_row_ok:
  2608.     cmp    dl,VC_WIDTH
  2609.      jb    pc_v_col_ok            ; if column is too big
  2610.     mov    dl,VC_WIDTH            ;   then clip it
  2611.     dec    dl
  2612. pc_v_col_ok:
  2613.  
  2614.     call    pc_point_curs@
  2615.     mov    VC_OFFSET,ax
  2616.     mov    VC_CURSOR,dx
  2617.     ret
  2618. ;;    jmp    put_cursor@            ; (updates VC_CURSOR as well)
  2619.  
  2620. v_i_getcursor:        ; 3 get cursor position
  2621. ;-------------
  2622. ;    Entry:    VID_BH = page number (ignored by us)
  2623. ;    Exit:    VID_DH, VID_DL = cursor row, column
  2624. ;        VID_CH, VID_CL = current cursor type
  2625.  
  2626.     mov    ax,VC_CURSOR
  2627.     mov    VID_DX[bp],ax
  2628.     mov    ax,VC_CUR_TYPE
  2629.     mov    VID_CX[bp],ax
  2630.     ret
  2631.  
  2632. v_i_lpen:        ; 4 - read light pen position
  2633. ;--------
  2634. ;    Exit:    VID_AH = 0
  2635.  
  2636.     mov    VID_AH[bp],0        ; say light pen not triggered
  2637.     ret
  2638.  
  2639.  
  2640. v_i_spage:        ; 5 - select active page
  2641. ;---------
  2642. ;    Entry:    VID_AL = new display page
  2643.  
  2644.     ret                ; -not supported-
  2645.  
  2646.  
  2647. v_i_scroll_up:        ; 6 scroll rectangle up
  2648. ;-------------
  2649. ;    Entry:    VID_AL = # of lines to scroll
  2650. ;             0 = clear entire rectangle
  2651. ;        VID_CH, VID_CL = top left corner of rectangle
  2652. ;        VID_DH, VID_DL = bottom right corner of rectangle
  2653. ;        VID_BH = attribute for spaces scrolled in
  2654.  
  2655.     mov    dx,VID_CX[bp]            ; top left corner to start
  2656.     call    pc_point_curs@            ; di -> top left corner
  2657.     call    pc_video_count            ; move, erase and column counts
  2658.      jc    pc_v_scroll_exit        ; quit on illegal box
  2659.  
  2660.     mov    al,VC_WIDTH            ; next row down
  2661.     cbw  !    shl ax,1
  2662.     jmps    pc_v_move_erase            ; shared routine from here
  2663.  
  2664. v_i_scroll_down:    ; 7 scroll window down
  2665. ;---------------
  2666. ;    Entry:    VID_AL = # of lines to scroll
  2667. ;             0 = clear entire rectangle
  2668. ;        VID_CH, VID_CL = top left corner of rectangle
  2669. ;        VID_DH, VID_DL = bottom right corner of rectangle
  2670. ;        VID_BH = attribute for spaces scrolled in
  2671.  
  2672.     mov    dh,VID_DH[bp]            ; bottom row
  2673.     mov    dl,VID_CL[bp]            ; left column
  2674.     call    pc_point_curs@            ; di -> bottom left corner
  2675.     call    pc_video_count            ; move, erase and column counts
  2676.      jc    pc_v_scroll_exit        ; quit on illegal box
  2677.  
  2678.     mov    al,VC_WIDTH            ; next row down
  2679.     cbw ! shl ax,1 ! neg ax
  2680. ;    jmps    pc_v_move_erase            ; shared routine from here
  2681.  
  2682. pc_v_move_erase:
  2683. ; Shared code for scroll up and down:
  2684. ;  entry:    ax = + or - chars per crt row
  2685.  
  2686.     push    ax                ; save row increment
  2687.     imul    VID_DX[bp]            ; ax = move offset
  2688.     mov    si,di
  2689.     add    si,ax                ; si -> move source
  2690.     pop    dx                ; dx = row increment
  2691.  
  2692.     cmp    VID_CX[bp],0            ; if no moves to do
  2693.      jz    pc_v_erase_loop            ;   then just erase
  2694.  
  2695. pc_v_move_loop:
  2696.     mov    cx,VID_AX[bp]            ; get column count
  2697.     push si ! push di            ; save line pointers
  2698.     call    z_movsw@            ; move one screen line
  2699.     pop di ! pop si
  2700.     add    si,dx                ; next source line
  2701.     add    di,dx                ;   and next destination
  2702.     dec    VID_CX[bp]            ; move countdown
  2703.      jnz    pc_v_move_loop
  2704.  
  2705. pc_v_erase_loop:
  2706.     mov    cx,VID_AX[bp]            ; get column count
  2707.     mov    al,' '                ; erase to a blank
  2708.     mov    ah,VID_BH[bp]            ; pick up the attribute
  2709.     push dx ! push di
  2710.     call    erase_pc@            ; erase one line
  2711.     pop di ! pop dx
  2712.     add    di,dx                ; next line to erase
  2713.     dec    VID_DX[bp]            ; erase countdown
  2714.      jnz    pc_v_erase_loop
  2715.  
  2716. pc_v_scroll_exit:
  2717.     ret
  2718.  
  2719.  
  2720. pc_video_count:
  2721. ;--------------
  2722. ; calculate move, erase and column counts
  2723. ;  exit:    VID_DX[bp] = erase count
  2724. ;        VID_CX[bp] = move count
  2725. ;        VID_AX[bp] = column count
  2726. ;              -    or -
  2727. ;        cf set on illegal box
  2728.  
  2729.     mov    al,VID_DH[bp]            ; bottom row
  2730.     sub    al,VID_CH[bp]            ; minus top row
  2731.      jc    pc_count_exit            ; if negative, forget it
  2732.  
  2733.     cbw  !  inc ax                ; ax = # of rows in box
  2734.     mov    dx,ax                ; dx = default erase count
  2735.     sub    cx,cx                ; default move count = 0
  2736.     sub    al,VID_AL[bp]            ; subtract lines to scroll
  2737.      jbe    pc_count_erase            ; if too much, just erase
  2738.     cmp    VID_AL[bp],0            ; if al = 0, just erase
  2739.      jz    pc_count_erase
  2740.  
  2741.     mov    cx,ax                ; cx = move count
  2742.     sub    dx,ax                ; dx = erase count
  2743. pc_count_erase:
  2744.     mov    al,VID_DL[bp]            ; right column
  2745.     sub    al,VID_CL[bp]            ; minus left column
  2746.      jc    pc_count_exit            ; if negative, forget it
  2747.  
  2748.     cbw  !    inc ax                ; ax = column count
  2749.     mov    VID_DX[bp],dx            ; save the move count
  2750.     mov    VID_CX[bp],cx            ;   the erase count and
  2751.     mov    VID_AX[bp],ax            ;   column count in the stack
  2752.     clc                    ; all is well
  2753. pc_count_exit:
  2754.     ret
  2755.  
  2756.  
  2757.  
  2758. pc_video_ret:
  2759.     ret
  2760.  
  2761.  
  2762. v_i_read:        ; 8 get attr/char at cursor
  2763. ;--------
  2764. ;    Entry:    VID_BH = page number (ignored by us)
  2765. ;    Exit:    VID_AL = character read
  2766. ;        VID_AH = attribute read (undefined if graphics)
  2767.  
  2768.     mov    dx,VC_CURSOR
  2769.     call    get_char_attr            ; call into common routine
  2770.     jmps    ret_char_attr
  2771.  
  2772. get_char_attr:                ; entry point from subfunction 14
  2773.                     ; to get current attribute
  2774.     call    pc_point_curs@        ; di -> cursor dest
  2775.     push    es
  2776.     mov    es,VC_CRT_SEG
  2777.     mov    ax,es:[di]        ; no hurry here
  2778.     pop    es
  2779. ret_char_attr:
  2780.     mov    VID_AX[bp],ax
  2781.     ret
  2782.     
  2783.     
  2784.  
  2785. v_i_write_attr:        ; 9 set attr/char at cursor
  2786. ;--------------
  2787. ;    Entry:    VID_BH = page number (ignored by us)
  2788. ;        VID_AL = character to write
  2789. ;        VID_BL = attribute (text)/xor flag (graphics)
  2790. ;        VID_CX = repeat count
  2791.  
  2792.     test    VC_MODE,MATCH_BIT    ; top screen ?
  2793.     jnz    v_i_wr_at1        ; no
  2794.     call    wait_sync        ; wait for synchronized screen
  2795.     call    get_point_pc        ; get pointer to physical screen struc.
  2796.     call    ser_mx            ; lock out serial I/O
  2797.     mov    ax,VC_CURSOR
  2798.     call    set_pcursor        ; make sure cursor in right place
  2799.     mov    cx,VID_CX[bp]        ; get repeat count
  2800.     mov    ah,VID_BL[bp]        ; get attribute
  2801.  
  2802. v_i_wr_at_loop:
  2803.     push    ax
  2804.     call    do_char_attrib        ; output character attribute
  2805.     pop    ax
  2806.     loop    v_i_wr_at_loop
  2807.     mov    PC_BUSY,00h        ; release serial semaphore
  2808.  
  2809. v_i_wr_at1:
  2810.     sub    si,si            ; call the following
  2811.     call    xlat_esc        ;   code w/o setting dirty bit
  2812.     mov    al,VID_AL[bp]        ; get character
  2813.     mov    ah,VID_BL[bp]        ; get attribute
  2814.     mov    cx,VID_CX[bp]        ; get character count
  2815.  
  2816. pc_ch_wr_a:
  2817. ; Entry from EGA write_string:
  2818.     push    ax            ; save attr/char
  2819.     mov    dx,VC_CURSOR
  2820.     call    pc_point_curs@        ; di -> cursor dest
  2821.     pop    ax            ; restor attr/char
  2822.     jmp    put_crt_s@        ; go right to physical
  2823.  
  2824.  
  2825.  
  2826. v_i_write_char@:    ; 10 set char @ cur
  2827. ;---------------
  2828. ;    Entry:    VID_BH = page number (ignored by us)
  2829. ;        VID_AL = character to write
  2830. ;        VID_CX = repeat count
  2831. ;
  2832. ;    Note:    attributes are not modified
  2833.  
  2834.     mov    al,VID_AL[bp]            ; recover character
  2835.     mov    cx,VID_CX[bp]            ; repeat count
  2836.  
  2837. pc_v_write:
  2838. ; Write cx attr/chars at current cursor:
  2839.  
  2840.     test    VC_MODE,MATCH_BIT    ; top screen ?
  2841.     jnz    pc_ch_wr_at1        ; no
  2842.     call    wait_sync        ; wait for synchronized screen
  2843.     call    get_point_pc        ; get pointer to physical screen struc.
  2844.     call    ser_mx            ; lock out serial I/O
  2845.     mov    ax,VC_CURSOR
  2846.     call    set_pcursor        ; make sure cursor in right place
  2847.  
  2848.     mov    cx,VID_CX[bp]        ; get repeat count
  2849.     mov    dx,VC_CURSOR
  2850.     call    pc_point_curs@        ; di -> cursor dest
  2851. pc_ch_wr_at_loop:
  2852.     inc    di            ; skip char
  2853.     mov    es,VC_CRT_SEG        ; get screen segment
  2854.     mov    ah,es:[di]        ; get attribute
  2855.     push    di
  2856.     call    do_char_attrib
  2857.     pop    di
  2858.     inc    di            ; next char
  2859.     loop    pc_ch_wr_at_loop
  2860.     mov    PC_BUSY,00h        ; release serial semaphore
  2861.  
  2862. pc_ch_wr_at1:
  2863.     sub    si,si            ; call the following
  2864.     call    xlat_esc        ;   code w/o setting dirty bit
  2865.     mov    al,VID_AL[bp]        ; get character
  2866.     mov    cx,VID_CX[bp]        ; get character count
  2867.  
  2868.     push    ax            ; save attr/char
  2869.     mov    dx,VC_CURSOR
  2870.     call    pc_point_curs@        ; di -> cursor dest
  2871.     pop    ax            ; restor attr/char
  2872.     mov    es,VC_CRT_SEG        ; get screen segment
  2873. pc_ch_wr1:
  2874.     stosb                ; write character only
  2875.     inc    di            ; skip attribute
  2876.     loop    pc_ch_wr1
  2877.     ret
  2878.  
  2879.  
  2880. ; Enter : AH = attribute
  2881. ;      VID_AL = char
  2882.  
  2883. do_char_attrib:
  2884.     push    cx
  2885.     call    set_pattrib        ; set physical attribute
  2886.     mov    al,VID_AL[bp]        ; get character
  2887.     cmp    al,' '            ; check if character large enough
  2888.     jae    go_pc_ch_wr        ; go ahead if printable
  2889. if 0                    ; if 1: remap control codes to ASCII
  2890.     push    bx
  2891.     mov    bx,offset ctrl_xlat    ; else translate to ASCII
  2892.     xlat    ctrl_xlat
  2893.     pop    bx
  2894. else                    ; this works on the Wyse 60:
  2895.     cmp    al,00            ; if zero then display a space
  2896.      jne    go_pc_ch_wr_control    ; no, send as ESC seq
  2897.     mov    al,' '            ; null = ' '
  2898.      jmps    go_pc_ch_wr        ; go ahead as printable
  2899. go_pc_ch_wr_control:
  2900.     push     ax            ; else output ESC
  2901.     mov    al,ESC            ;   for terminal to recognize
  2902.     call    tmp_write        ;   sequence as illegal and to
  2903.     pop    ax            ; and print control char
  2904. endif
  2905. go_pc_ch_wr:
  2906.     call    tmp_write        ; write character AL
  2907.     inc    PC_CURCOL        ; next cursor column
  2908.     cmp    PC_CURCOL,CRT_COLS
  2909.      jne    pc_ch_wr_at_lp1        ; skip if no wrap
  2910.     mov    ah,PC_CURROW        ; get current row
  2911.     inc    ah
  2912.     mov    al,0            ; next line, first column
  2913.     call    set_pcursor        ; set cursor address
  2914. pc_ch_wr_at_lp1:
  2915.     pop    cx
  2916.     ret
  2917.  
  2918.  
  2919. v_i_set_color:        ; 11 pallette / border control
  2920. ;-------------
  2921. ;    Entry:    VID_BH = color ID to set
  2922. ;        VID_BL = color value to set
  2923.  
  2924.     ret
  2925.  
  2926.  
  2927.  
  2928. v_i_write_tty:        ; 14 write char stream as a tty
  2929. ;-------------
  2930. ;    Entry:    VID_AL = character to write
  2931. ;        VID_BL = color in graphics mode
  2932.  
  2933.     mov    cl,VID_AL[bp]
  2934.     mov    dx,VC_CURSOR
  2935.     cmp    cl,' '            ; check if any control code
  2936.      jae    pc_not_bell
  2937.  
  2938.     cmp    cl,BS            ; backspace?
  2939.      jne    pc_not_bs
  2940.     jmp    vc_out_bs@
  2941.  
  2942. pc_not_bs:
  2943.     cmp    cl,CR            ; cr?
  2944.      jne    pc_not_cr
  2945.     jmp    vc_out_cr@
  2946.  
  2947. pc_not_cr:
  2948.     cmp    cl,LF            ; lf
  2949.      jne    pc_not_lf
  2950.     jmp    vc_out_lf@
  2951.  
  2952. pc_not_lf:
  2953.     cmp    cl,BEL            ; bell?
  2954.     jne    pc_not_bell
  2955.     jmp    vc_out_bel@
  2956.  
  2957. pc_not_bell:
  2958.     push    cx            ; save character
  2959.     call    get_char_attr        ; find attr on current char
  2960.     pop    cx
  2961.     push    word ptr VC_ATTRIB    ; save default
  2962.     mov    VC_ATTRIB,ah        ; temp change attribute
  2963.     call    vc_out@
  2964.     pop    word ptr VC_ATTRIB
  2965.     ret
  2966.  
  2967.  
  2968.  
  2969. v_i_gmode:        ; 15 current video state
  2970. ;---------
  2971. ;    Exit:    VID_AL = current video mode (see v_i_smode:)
  2972. ;        VID_AH = # of columns per line
  2973. ;        VID_BH = current screen page (always 0 in CDOS)
  2974.  
  2975.     mov    al,VC_VMODE        ; get current ROS video mode
  2976.     mov    ah,VC_WIDTH        ; get screen width (40 / 80 cols)
  2977.     mov    VID_AX[bp],ax
  2978.     mov    VID_BH[bp],0        ; always in page 0
  2979.     ret
  2980.     
  2981.     
  2982. eject
  2983.     
  2984. ; Dispatcher intercept vector
  2985. ;    entry:    DS:BX = SYSDAT:PD address
  2986. ;        ES = UDA segment
  2987. ;    exit:    DS, ES preserved
  2988. disp_inter:
  2989. ;----------
  2990.     pushf
  2991.     cli
  2992.     cld
  2993.     mov    dl,P_CONS[bx]        ; VC number of new process
  2994.     cmp    dl,MAX_VIR_CONS
  2995.     ja    no_disp
  2996.     cmp    dl,active_vc$        ; same console as last time?
  2997.     jne    disp_1     
  2998. no_disp:
  2999.     jmp    disp_retf        ; yes, don't do anything
  3000. disp_1:
  3001.     cmp    dl,NUM_VIR_CONS        ; check console
  3002.     jae    disp_2
  3003.      jmp    dsp_int1        ; skip if not serial console
  3004. disp_2:
  3005.     push    dx            ; save vs
  3006.     call    get_ccb            ; di -> ccb
  3007.     mov    dl,C_PC[di]        ; logical console number
  3008.     call    test_pcterm@        ; test if emulation required
  3009.     pop    dx
  3010.     jz    no_disp            ; must be dumb terminal so ignore
  3011.     
  3012.     push es    ! push bx        ; swap in serial terminal
  3013.     call    point_vc@        ; get VC_ in BX
  3014.     xchg    active_vc$,dl
  3015.     cmp    dl,NUM_VIR_CONS        ; serial process active before?
  3016.      jb    disp_inter1        ; no, don't save page entries
  3017.  
  3018. ; Swapping to serial from serial
  3019.     test    VC_INSTALLED,0ffh    ; has flush been installed for VC
  3020.     jnz    disp_3
  3021.     jmp    disp1            ; no leave
  3022. disp_3:
  3023.     push    bx            ; save new VC->
  3024.     push    ds            ; save old page entries
  3025.     push ds ! pop es        ; our DS to ES
  3026.     call    point_vc@        ; get old VC_ in BX
  3027.     mov    al,sl_pc_flag$
  3028.     mov    ah,sl_crt_flag$
  3029.     mov    VC_SL_FLAGS,ax        ; save status line flags
  3030.     mov    ax,PC_SEGMENT        ; we will be working with ROS data
  3031.     mov    ds,ax            
  3032.     mov    ax,cursor_posn_40    ; assume active page zero
  3033.     mov    es:VC_ROS_CURSOR,ax    ; and save the ROS cursor posn
  3034. disp_4:
  3035.     lea    di,es:VC_PAGE_SAVE    ; page save area for VC
  3036.     mov    bx,es:v386_ptr$        ; get pointer to 386 specific table
  3037.     mov    ds,es:ptbl_seg        ; get page table 
  3038.     mov    si,(CRT_SEG/100h)*4    ; save page table contents
  3039.     mov    cx,2*2            ; in VC_ structure
  3040.     rep    movsw
  3041.     add    si,4*2            ; point to physical image
  3042.     movsw
  3043.     movsw
  3044.     pop    ds            ; restore sysdat
  3045.     pop    bx
  3046.     jmps    disp_inter2
  3047.  
  3048. ; Swapping to serial from PC terminal
  3049. disp_inter1:
  3050.     xchg    dl,active_vc$
  3051.     push    dx
  3052.     push    bx
  3053.     call    map_top            ; restore mapping
  3054.     pop    bx
  3055.     pop    dx
  3056.     xchg    dl,active_vc$
  3057.     push    ds
  3058.     push ds ! pop es
  3059.     mov    al,sl_pc_flag$
  3060.     mov    ah,sl_crt_flag$
  3061.     mov    save_sl_flags,ax    ; save status line flags
  3062.     mov    ax,PC_SEGMENT        ; point at ROS data
  3063.     mov    ds,ax
  3064.     mov    al,crt_mode_40        ; save some state of PC terminal
  3065.     mov    es:save_mode,al
  3066.     mov    ax,crt_cols_40
  3067.     mov    es:save_cols,al
  3068.     mov    ax,cursor_posn_40    ; assume active page zero
  3069.     mov    es:save_cursor,ax
  3070.     mov    ax,equip_flag_40    ; get ROS value
  3071.     xchg    ax,es:save_equip$    ; get saved value
  3072.     or    al,00110000b        ; make default console b/w
  3073.     mov    equip_flag_40,ax
  3074.     mov    ax,MONO_PORT
  3075.     xchg    ax,addr_6845_40        ; swap CRT controller values
  3076.     mov    es:save_6845,ax
  3077.     
  3078.     cmp    es:kbd_imhere$,0    ; in keyboard ISR ?
  3079.     je    disp_inter1a
  3080.     pop    ds
  3081.     jmps    disp_inter4
  3082. disp_inter1a:
  3083.     mov    si,offset kb_flag_40     ; keyboard data area
  3084.     mov    di,offset save_kbdata$    ; save area
  3085.     mov    cx,39
  3086.     rep    movsb            ; save kbd flags and buffer
  3087.     pop    ds
  3088.  
  3089. ; swap serial in
  3090. disp_inter2:
  3091.     test    VC_INSTALLED,0ffh    ; has flush been installed for VC
  3092.     jnz    disp_inter3
  3093.     jmp    disp1            ; no leave
  3094. disp_inter3:
  3095.     cmp    kbd_imhere$,0        ; in keyboard ISR ?
  3096.     jne    disp_inter4        ; yes leave alone
  3097.     call    get_kbd_flags@        ; get active_vc save area offset in SI
  3098.     mov    ax,PC_SEGMENT
  3099.     mov    es,ax
  3100.     mov    di,offset kb_flag_40    ; ROS keyboard data area offset
  3101.     mov    cx,39            ; flags and buffer
  3102.     rep    movsb            ; put new values into ROS
  3103.  
  3104. disp_inter4:
  3105.     push    es            ; save ES and BX
  3106.     mov    ax,VC_SL_FLAGS        ; restore status line flags
  3107.     mov    sl_pc_flag$,al
  3108.     mov    sl_crt_flag$,ah
  3109.     mov    ax,PC_SEGMENT        ; we will be working with ROS data
  3110.     mov    es,ax            
  3111.     mov    al,VC_VMODE        ; store values from new console
  3112.     mov    es:crt_mode_40,al
  3113.     mov    al,VC_WIDTH
  3114.     xor    ah,ah
  3115.     mov    es:crt_cols_40,ax
  3116.     mov    ax,VC_ROS_CURSOR
  3117.     mov    es:cursor_posn_40,ax    ; assume active page zero
  3118.     pop    es 
  3119.     lea    si,VC_PAGE_SAVE        ; page save area for VC
  3120.     mov    bx,v386_ptr$        ; get pointer to 386 specific table
  3121.     mov    es,ptbl_seg        ; enable page table for us
  3122.     push    si
  3123.     mov    di,(CRT_SEG/100h)*4
  3124.     mov    cx,3
  3125.     lodsw
  3126.     and    al,not PGA_RW        ; set write protect attribute
  3127.     stosw                ; for IDLE detection
  3128.     rep    movsw
  3129.  
  3130.     add    di,4*2            ; physical image
  3131.     movsw
  3132.     movsw
  3133.     pop    si
  3134.     mov    di,(COLOR_SEG/100h)*4    ; make sure something mapped at B800h
  3135. ;    mov    cx,2*2
  3136. ;    rep    movsw
  3137.  
  3138.     mov    ax,0f067h        ; AX/DX = physical memory base
  3139.     mov    dx,0ffffh
  3140.  
  3141.     stosw
  3142.     xchg    ax,dx
  3143.     stosw    
  3144.     xchg    ax,dx
  3145.         
  3146.  
  3147.     mov    bx,v386_ptr$        ; get pointer to 386 specific table
  3148.     mov    es,tss_seg        ; get TSS segment address
  3149.     or    es:word ptr .0DEh,8530h    ; disable ports 3BFh, 3B4h, 3B5h, 
  3150.                     ; 3BAh, 3B8h
  3151.     or    es:byte ptr .074h,02h    ; trap port 61h - set beeper
  3152. disp1:
  3153.     pop bx ! pop es
  3154. disp_retf:
  3155.     popf
  3156.     FLUSH_TLB            ; discard TLB cache
  3157.     retf
  3158.  
  3159. ; Swapping to MAIN terminal
  3160. ; -----------------------
  3161. dsp_int1:
  3162.     xchg    dl,active_vc$        ; mark new active console
  3163.     cmp    dl,NUM_VIR_CONS        ; serial process active before?
  3164.      jae    dsp_int1a        ; yes..
  3165.     xchg    dl,active_vc$
  3166.     push    dx
  3167.     call    map_top            ; restore mapping
  3168.     pop    dx
  3169.     xchg    dl,active_vc$
  3170.     call    map_top            ; map in top screen
  3171.     jmps    disp_retf
  3172.  
  3173. dsp_int1a:     
  3174.  
  3175. ; -- from serial terminal
  3176. ; -----------------------
  3177.     push    bx ! push es
  3178.     mov    ax,PC_SEGMENT        ; point to ROS data area
  3179.     mov    es,ax
  3180.  
  3181.     mov    ax,save_equip$        ; get saved value
  3182.     mov    es:equip_flag_40,ax    ;  and store in ROS
  3183.     mov    ax,save_6845
  3184.     mov    es:addr_6845_40,ax    ; swap CRT controller values
  3185.  
  3186.     cmp    kbd_imhere$,0        ; in keyboard ISR ?
  3187.     jne    dsp_int2        ; yes..
  3188.     mov    si,offset save_kbdata$    ; get saved data offset
  3189.     mov    di,offset kb_flag_40    ; and store in ROS data area
  3190.     mov    cx,39            ; keyboard flags and buffer
  3191.     rep     movsb
  3192.     
  3193. dsp_int2:    
  3194.     call    point_vc@        ; get VC_ in BX
  3195.     mov    al,sl_pc_flag$
  3196.     mov    ah,sl_crt_flag$
  3197.     mov    VC_SL_FLAGS,ax        ; save status line flags
  3198.     mov    ax,es:cursor_posn_40    ; assume active page zero
  3199.     mov    VC_ROS_CURSOR, ax        ; and save ros cursor position
  3200. dsp_int3:
  3201.     mov    al,save_mode
  3202.     mov    es:crt_mode_40,al    ; restore state of PC terminal
  3203.     mov    al,save_cols
  3204.     xor    ah,ah
  3205.     mov    es:crt_cols_40,ax
  3206.     mov    ax,save_cursor
  3207.     mov    es:cursor_posn_40,ax    ; assume active page zero
  3208.     mov    ax,save_sl_flags    ; restore status line flag
  3209.     mov    sl_pc_flag$,al
  3210.     mov    sl_crt_flag$,ah
  3211.     test    VC_INSTALLED,0ffh    
  3212.     jz    disp_retf1
  3213.     push    ds
  3214.     push ds ! pop es        ; our DS to ES
  3215.     lea    di,VC_PAGE_SAVE        ; page save area for VC
  3216.     mov    bx,v386_ptr$        ; get pointer to 386 specific table
  3217.     mov    ds,ptbl_seg        ; get page table 
  3218.     mov    si,(CRT_SEG/100h)*4    ; save page table contents
  3219.     mov    cx,2*2            ; in VC_ structure
  3220.     rep    movsw
  3221.     add    si,4*2            ; point to physical image
  3222.     movsw
  3223.     movsw
  3224.     pop    ds            ; restore sysdat
  3225.  
  3226.     mov    di,(CRT_SEG/100h)*4    ; now swap in physical memory
  3227.     mov    es,ptbl_seg        ; ES:DI -> page table
  3228.     mov    ax,(CRT_SEG*16)+67h    ; AX/DX = physical memory base
  3229.     mov    dx,(CRT_SEG/4096)
  3230.  
  3231.     stosw
  3232.     xchg    ax,dx
  3233.     stosw    
  3234.     xchg    ax,dx
  3235.  
  3236.     add    ax,1000h        ; replace clean image
  3237.     stosw
  3238.     xchg    ax,dx
  3239.     stosw    
  3240.     xchg    ax,dx
  3241.  
  3242.     add    di,4*2
  3243.     add    ax,3000h        ; replace physical image
  3244.     stosw
  3245.     xchg    ax,dx
  3246.     stosw    
  3247.  
  3248.     mov    bx,v386_ptr$        ; get pointer to 386 specific table
  3249.     mov    es,tss_seg            ; get TSS segment address
  3250.     and    es:word ptr .0DEh,not 8530h    ; enable 3BFh, 3B4h, 3B5h, 
  3251.                         ; 3bAh, 3B8h
  3252.     and    es:byte ptr .074h,not 02h    ; enable port 61h - beeper
  3253.     call    map_top            ; 
  3254. disp_retf1:
  3255.     pop    es ! pop bx
  3256.     popf
  3257.     FLUSH_TLB            ; discard TLB cache
  3258.     retf
  3259.  
  3260. ; Map in current top console
  3261. map_top:
  3262.     mov    dl,active_vc$
  3263.     cmp    dl,active_top
  3264.     je    is_foreg1a        ; current vc is top
  3265.  
  3266.     call    map_current_vc        ; else map vc buffer in screen memory
  3267.  
  3268.     mov    bx,v386_ptr$        ; get pointer to 386 specific table
  3269.     mov    es,tss_seg            ; get TSS segment address
  3270.     or    es:word ptr .0DEh,8530h        ; trap 3BFh, 3B4h, 3B5h, 
  3271.                         ; 3BAh, 3B8h
  3272.     or    es:word ptr .0E2h,8530h        ; trap 3DFh, 3D4h, 3D5h, 
  3273.                         ; 3DAh, 3D8h
  3274.     jmps    is_foreg2a
  3275.  
  3276. is_foreg1a:
  3277.     call    map_current_screen    ; re-map screen memory
  3278.  
  3279.     mov    bx,v386_ptr$        ; get pointer to 386 specific table
  3280.     mov    es,tss_seg            ; get TSS segment address
  3281.     and    es:word ptr .0DEh,not 8530h    ; enable 3BFh, 3B4h, 3B5h, 
  3282.                         ; 3bAh, 3B8h
  3283.     and    es:word ptr .0E2h,not 8530h    ; enable 3DFh, 3D4h, 3D5h, 
  3284.                         ; 3DAh, 3D8h
  3285. is_foreg2a:
  3286.     mov    dl,top_screen$        ; keep note of top_screen$ for next
  3287.     mov    active_top,dl        ; time thru in
  3288.     ret
  3289.  
  3290.  
  3291. ; Map Current Virtual console buffer into screen memory area
  3292. ; Enter : DL = active vc
  3293. ; N.B. FLUSH_TLB must be done on return
  3294. map_current_vc:
  3295.     push    ds
  3296.     push    bx
  3297.     call    point_vs@
  3298.     mov    di,VS_CRT_SEG        ; screen seg address
  3299.     cmp    di,EGA_SEG        ; graphics ?
  3300.     je    map_exit
  3301.     mov    si,VS_VC_SEG        ; VC seg address
  3302.  
  3303.     mov    VS_CRT_SEG,si        ; swap VS_CRT_SEG and VS_VC_SEG
  3304.     mov    VS_VC_SEG,di        ; pointers over
  3305.     shr    di,6            ; / 100h *4 = page table entry(screen)
  3306.     shr    si,6            ;          page table entry(VC buff)
  3307.     mov    bx,v386_ptr
  3308.     mov    es,ptbl_seg        ; page table
  3309.     mov    ds,ptbl_seg
  3310. OP_32 !    mov    ax,[si]            ; now swap over the mappings as well
  3311.     and    al,not PGA_RW        ; set write protect attribute
  3312. OP_32 !    xchg    ax,[di]
  3313.     and    al,not PGA_RW        ; set write protect attribute
  3314. OP_32 !    mov    [si],ax
  3315. map_exit:
  3316.     pop    bx
  3317.     pop    ds
  3318.     ret
  3319.  
  3320. ;Re-Map screen memory area
  3321. ; Enter : DL = active vc
  3322. ; N.B. FLUSH_TLB must be done on return
  3323. map_current_screen:
  3324.     call    point_vs@
  3325.     mov    dh,VS_SCREEN_MODE    ; get current mode
  3326.     mov    di,MONO_SEG
  3327.  OP_32 ! xor    ax,ax            ; clear EAX
  3328.     mov    ax,di
  3329.     shr    di,6            ; / 100h *4 = page table entry(screen)
  3330.     mov    bx,v386_ptr
  3331.     mov    es,ptbl_seg        ; page table
  3332.  OP_32 ! shl    ax,4
  3333.     xor    al,al            ; ** set write protect **
  3334.     cmp    dh,07            ; MONO mode
  3335.     je    is_mono
  3336.     mov    al,67h            ; allow read/write
  3337. is_mono:
  3338.  OP_32 ! stosw
  3339.     mov    di,COLOR_SEG
  3340.  OP_32 ! xor    ax,ax            ; clear EAX
  3341.     mov    ax,di
  3342.     shr    di,6            ; / 100h *4 = page table entry(screen)
  3343.     mov    bx,v386_ptr
  3344.     mov    es,ptbl_seg        ; page table
  3345.  OP_32 ! shl    ax,4
  3346.     xor    al,al            ; ** set write protect **
  3347.     cmp    dh,07            ; MONO mode
  3348.     jne    is_color
  3349.     mov    al,67h            ; allow read/write
  3350. is_color:
  3351.  OP_32 ! stosw
  3352.     ret
  3353.  
  3354.  
  3355. eject
  3356. ;    Subroutines
  3357. ;    -----------
  3358.  
  3359.  
  3360. get_point_pc:
  3361. ;------------
  3362. ; Get pointer to physical screen structure
  3363. ;  entry:    BX -> pointer to VC structure
  3364. ;  exit:     SI -> pointer to PC structure
  3365.     
  3366.     mov    dl,VC_NUMBER        ; get virtual console number
  3367. ;    jmps    point_pc
  3368.     
  3369.     
  3370.  
  3371. point_pc:
  3372. ;--------
  3373. ; Point to physical console structure:
  3374. ;  entry:    dl = virtual console number
  3375. ;  exit:    SI -> pc_
  3376. ;        DH = physical console number
  3377. ; point_pc1@ - entry 
  3378. ;        AL = physical console
  3379.  
  3380.     xor    dh,dh
  3381.     mov    si,dx
  3382.     shl    si,1
  3383.     mov    si,ccb_list$[si]    ; get ccb pointer for VC
  3384.     mov    al,C_PC[si]        ; get physical console number
  3385.     mov    dh,al            ; and store in DH
  3386. point_pc1@:
  3387.     dec    al            ; physical 0 is master console
  3388.     xor    ah,ah
  3389.     mov    si,ax
  3390.     shl    si,1
  3391.     mov    si,pc_table[si]        ; pointer to PC_ structure
  3392.     ret
  3393.  
  3394. ; Point to virtual console structure:
  3395. ;  entry:    dl = virtual console number
  3396. ;  exit:    BX = vc_
  3397. point_vc@:
  3398. ;--------
  3399.     
  3400.     xor    dh,dh
  3401.     mov    bx,dx
  3402.     sub    bx,NUM_VIR_CONS        ; make 0 relative
  3403.     shl    bx,1
  3404.     mov    bx,vc_table[bx]        ; get virtual console table
  3405.     ret
  3406.  
  3407. ; get ccb structure for virtual console
  3408. ;  entry:    dl=virtual console number
  3409. ;  exit:    di=ccb address
  3410. get_ccb:
  3411. ;-------
  3412.     xor    dh,dh
  3413.     mov    di,dx
  3414.     shl    di,1
  3415.     mov    di,ccb_list$[di]    ; get ccb pointer for VC
  3416.     ret
  3417.  
  3418.  
  3419. ; get ROS keyboard data for active_vc
  3420. ; include flags, buffer pointers and buffer
  3421. ;  exit:    SI = offset ROS keyboard data
  3422. ;    all regs preserved
  3423. get_kbd_flags@:
  3424. ;-------------
  3425.     push    dx
  3426.     mov    dl,active_vc$        ; top vc_
  3427.     cmp    dl,NUM_VIR_CONS
  3428.     jae    is_ser
  3429.     mov    si,offset save_kbdata$    ; get main console save area
  3430.     jmps    kbd_flags_ret
  3431. is_ser:
  3432.     call    point_pc        ; get PC_ structure
  3433.     mov    ax,word ptr PC_KFLAG
  3434.     mov    si,offset pc_kbd_save    ; PC terminals save area
  3435.     mov    [si],ax            ; insert flags at start
  3436. kbd_flags_ret:
  3437.     pop    dx
  3438.     ret    
  3439.  
  3440.  
  3441. ; test if serial console is setup for PCTERM emulation
  3442. ;  entry:    dl = logical physical console number
  3443. ;  exit:    ZF reset if PCTERM
  3444. test_pcterm@:
  3445. ;-----------
  3446.     push    ax
  3447.     call    get_su_mu
  3448.     test    al,PCTERM_EMU        ; test setup bit for installed port
  3449.     pop    ax
  3450.     ret                ;  to see if pcterm emulation required
  3451.  
  3452. ; return setup byte in AL
  3453. get_su_mu:
  3454.     push    bx
  3455.     mov    bl,dl
  3456.     mov    bh,0            ; BX = physical console #
  3457.     mov    bl,pc2port_table$[bx]    ; BX = serial port number
  3458.     mov    al,su_mu_vs$[bx]    ; get setup byte for serial port
  3459.     pop    bx
  3460.     ret
  3461.  
  3462.  
  3463. ; virtual console mutual exclusion
  3464. ; Enter : BX=VS_ ->
  3465. get_mx:
  3466. ;------
  3467.     mov    al,0FFh
  3468.     xchg    al,VC_MX
  3469.     test    al,al
  3470.      jz    got_mx
  3471.     push bx ! push cx ! push dx
  3472.     call    delay1
  3473.     pop    dx ! pop cx ! pop bx
  3474.     jmps    get_mx
  3475. got_mx:
  3476.     ret
  3477.  
  3478. ; Get MX's for all VS on physical console
  3479. get_all_mxs:
  3480. ;-----------
  3481.     mov    di,rlr$            ; get running proc
  3482.     mov    dl,P_CONS[di]        ; get process's vc number
  3483.     xor    dh,dh
  3484.     mov    di,dx
  3485.     shl    di,1
  3486.     mov    di,ccb_list$[di]    ; get ccb pointer for VC
  3487.     mov    al,C_PC[di]        ; get physical console number
  3488.                     
  3489.     mov    di,offset ccb_list$    ; search for first VC on this physical
  3490. search_ccb:
  3491.     mov    si,[di]            ; ccb pointer
  3492.     inc di ! inc di
  3493.     cmp    al,C_PC[si]        ; our ccb
  3494.     jne    search_ccb        ; no get next
  3495.  
  3496. next_mx:
  3497.     mov    dl,C_VC[si]        ; get VS number
  3498.     push    si
  3499.     call    point_vc@
  3500.     call    get_mx
  3501.     pop    si
  3502.     mov    si,C_LINK[si]        ; link to next
  3503.     cmp    si,0000h        ; end link ?
  3504.     jne    next_mx
  3505.     ret
  3506.  
  3507. ; Free MX's for all VS on physical console
  3508. free_all_mxs:
  3509. ;------------
  3510.     mov    di,rlr$            ; get running proc
  3511.     mov    dl,P_CONS[di]        ; get process's vc number
  3512.     xor    dh,dh
  3513.     mov    di,dx
  3514.     shl    di,1
  3515.     mov    di,ccb_list$[di]    ; get ccb pointer for VC
  3516.     mov    al,C_PC[di]        ; get physical console number
  3517.                     
  3518.     mov    di,offset ccb_list$    ; search for first VC on this physical
  3519. search_ccb1:
  3520.     mov    si,[di]            ; ccb pointer
  3521.     inc di ! inc di
  3522.     cmp    al,C_PC[si]        ; our ccb
  3523.     jne    search_ccb1        ; no get next
  3524.  
  3525. next_mx1:
  3526.     mov    dl,C_VC[si]        ; get VS number
  3527.     call    point_vc@
  3528.     mov    VC_MX,0            ; release semaphore
  3529.     mov    si,C_LINK[si]        ; link to next
  3530.     cmp    si,0000h        ; end link ?
  3531.     jne    next_mx1
  3532.     ret
  3533.  
  3534. ; Serial console output mutual exclusion
  3535. ;  Entry :    SI -> PC_ structure
  3536. ser_mx:
  3537. ;------
  3538.     mov    al,0FFh
  3539.     xchg    al,PC_BUSY
  3540.     test    al,al
  3541.      jz    ser_mx1
  3542.     push bx ! push cx ! push dx ! push si
  3543.     call    delay1
  3544.     pop  si ! pop dx ! pop cx ! pop bx
  3545.     jmps    ser_mx
  3546. ser_mx1:
  3547.     ret
  3548.  
  3549. delay1:
  3550. ;-----
  3551.     push    bp
  3552.     mov    cx,P_DELAY
  3553.     mov    dx,1
  3554.     call    supif@            ; delay by one tick
  3555.     pop    bp
  3556.     ret
  3557.  
  3558.  
  3559.  
  3560. wait_sync:
  3561. ;---------
  3562. ;    SI preserved
  3563.  
  3564.     push    es ! push bx ! push si
  3565. wt_sync1:
  3566.     mov    bx,v386_ptr$
  3567.     mov    es,ptbl_seg        ; get page table segment
  3568.     mov    di,(CRT_SEG/256*4)    ; get entry for screen segment
  3569.     test    PG_ATTR,PGA_DIRTY    ; test if screen is clean
  3570.      jz    wt_sync2        ; continue if screen is clean
  3571.     call    delay1
  3572.     jmps    wt_sync1
  3573. wt_sync2:
  3574.     pop si ! pop bx ! pop es
  3575.     ret
  3576.  
  3577.  
  3578. ; update Physical cursor
  3579. ;    entry:    AX = desired cursor address
  3580. ;        BX -> VC_ structure
  3581. ;        SI -> PC_ structure
  3582. ;        SI,BP preserved
  3583. set_pcursor:
  3584. ;-----------
  3585.     cmp    ax,PC_CURSOR        ; same as physical cursor?
  3586.      je    set_pcurs_ret        ; yes, leave it alone
  3587.     mov    PC_CURSOR,ax        ; else update it first
  3588.     xchg    al,ah            ; AL = row, AH = col
  3589.     add    ax,2020h        ; add in row/column bias
  3590.     lea    di,PC_CURPOS        ; get address of ESC sequence
  3591.     mov    3[di],ax        ; set row/column in sequence
  3592.     call    ser_write        ; send ESC sequence to terminal
  3593. set_pcurs_ret:
  3594.     ret
  3595.  
  3596.  
  3597. ; Turn physical cursor off
  3598. ; Entry: BX -> VC_
  3599. cursor_off:
  3600. ;----------
  3601.     test    VC_MODE,MATCH_BIT
  3602.     jnz    no_off            ; background
  3603.     call    get_point_pc        ; get PC_ ->
  3604.     call    ser_mx            ; mutual exclusion
  3605.     mov    di,offset cur_off_seq
  3606.     call    ser_write
  3607.     mov    PC_BUSY,00h        ; release semaphore
  3608. no_off:
  3609.     ret
  3610.  
  3611. ; Turn physical cursor on
  3612. ; Entry: BX -> VC_
  3613. cursor_on:
  3614. ;---------
  3615.     test    VC_MODE,MATCH_BIT
  3616.     jnz    no_on            ; background
  3617.     call    get_point_pc        ; get PC_ ->
  3618.     call    ser_mx            ; mutual exclusion
  3619.     mov    di,offset cur_on_seq
  3620.     call    ser_write
  3621.     mov    PC_BUSY,00h        ; release semaphore
  3622. no_on:
  3623.     ret
  3624.  
  3625. set_pattrib:
  3626. ;-----------
  3627. ;    entry:    AH = new screen attribute
  3628. ;        BX = VC ->
  3629. ;        SI = PC ->
  3630. ;        SI,BP preserved
  3631.  
  3632.     cmp    ah,PC_ATTR
  3633.      jne    new_pattr
  3634.     ret
  3635. new_pattr:
  3636.     mov    PC_ATTR,ah        ; save as new attribute
  3637.     mov    al,0011$0001b        ; invisble attribute
  3638.     cmp    ah,00h
  3639.     je    pattr4
  3640.  
  3641.     mov    al,0111$0000b        ; assume normal attribute (dim)
  3642.     cmp    ah,07h
  3643.     je    pattr4
  3644.     test    ah,0000$1000b        ; test intensity bit
  3645.     jz    pattr1
  3646.     and    al,1011$1111b        ; turn on intensity
  3647. pattr1:
  3648.     test    VC_BLINK,20h
  3649.     jnz    pattr1a            ; blink not disabled
  3650.     test    ah,1000$0000b        ; blink attr
  3651.     jz    pattr2            ; blink disabled and blink attr then
  3652.     and    al,1011$1111b        ; turn on intensity
  3653.     jmps    pattr2
  3654. pattr1a:
  3655.     test    ah,1000$0000b        ; blinking text?
  3656.      jz    pattr2
  3657.     or    al,0000$0010b        ; turn on blinking
  3658. pattr2:
  3659.     and    ah,0111$0111b        ; isolate other bits
  3660.     test    ah,0111$0000b        ; inverse video?
  3661.      jz    pattr3
  3662.     or    al,0000$0100b        ; turn on reverse
  3663.     jmps    pattr4
  3664. pattr3:
  3665.     cmp    ah,0000$0001b        ; underlined text?
  3666.      jne    pattr4
  3667.     or    al,0000$1000b        ; underlined bit
  3668. pattr4:
  3669.     lea    di,PC_ATTRIB        ; "set attribute" sequence
  3670.     mov    3[di],al        ; set desired attribute
  3671.     call    ser_write        ; write out ESC G attrib
  3672.     ret
  3673.  
  3674. tmp_write:
  3675. ;---------
  3676. ;    entry:    AL = character to write
  3677. ;        BX -> VC screen structure
  3678. ;        SI -> physical screen structure
  3679. ;        SI,BP preserved
  3680.  
  3681.     lea    di,PC_TMPSTR
  3682.     mov    byte ptr [di],1
  3683.     mov    1[di],al
  3684. ;    call    ser_write
  3685. ;    ret
  3686.  
  3687. ser_write:
  3688. ;---------
  3689. ;    entry:    
  3690. ;        SI -> physical screen structure
  3691. ;        BP preserved
  3692. ;        DI -> string for output
  3693.     push    bp
  3694.     mov    al,[di]
  3695.     inc    di            ; 1st byte = character count
  3696.     cbw                ; make it a word
  3697.     xchg    ax,cx            ; CX = byte count
  3698. ser_wrt1:
  3699.     mov    al,[di]
  3700.     inc    di
  3701.     push    bx ! push cx ! push si ! push di
  3702.     mov    cl,al
  3703.     mov    dl,PC_CONS        ; get physical console number
  3704.     add    dl,NUM_VIR_CONS-1    ; make logical VC number
  3705.     call    io_conout        ; call to original io_conout
  3706.     pop     di ! pop si ! pop cx ! pop bx
  3707.     loop    ser_wrt1
  3708.     pop    bp
  3709.     ret
  3710.  
  3711.  
  3712. xlat_esc:
  3713. ;--------
  3714. ;    entry:    SI -> escape sequence  -or-  0000h
  3715. ;        return address = emulation routine
  3716. ;
  3717. ;    Note:    This code will call the code at the return
  3718. ;        address twice, once for the virtual plane
  3719. ;        and once for the physical image...
  3720.  
  3721.     test    VC_MODE,MATCH_BIT    ; test if foreground console
  3722.      jnz    xlat_esc_bg        ;   skip if background
  3723.     test    si,si            ; test if any ESC sequence provided
  3724.      jz    xlat_esc_fg
  3725.     push    si
  3726.     call    wait_sync        ; wait for synchronized screen
  3727.      call    get_point_pc        ; get pointer to physical screen struc.
  3728.     call    ser_mx            ; lock out serial I/O
  3729.     mov    ax,VC_CURSOR
  3730.     call    set_pcursor        ; make sure cursor in right place
  3731.     pop    di            ; string address to DI
  3732.     call    ser_write        ;  for ser_write
  3733.     mov    PC_CURSOR,-1        ; invalidate cursor address
  3734.     mov    PC_BUSY,00h        ; release serial semaphore
  3735. xlat_esc_fg:
  3736.     pop    ax ! push ax        ; get & save image update routine
  3737.     mov    VC_CRT_SEG,CRT_SEG+IMGOFF/16
  3738.     mov    dx,VC_CURSOR
  3739.     call    ax            ; update physical image
  3740. xlat_esc_bg:
  3741.     pop    ax            ; get image update routine
  3742.     mov    VC_CRT_SEG,CRT_SEG+CLNOFF/16
  3743.     mov    dx,VC_CURSOR
  3744.     call    ax            ; update virtual image
  3745.     mov    VC_CRT_SEG,CRT_SEG    ; restore screen segment
  3746.     ret
  3747.  
  3748. eject
  3749.  
  3750.  
  3751. con_control:
  3752. ;-----------
  3753. ; Handle control codes:
  3754.  
  3755.     mov    di,offset norm_scan
  3756.     mov    cx,NORM_COUNT
  3757.     call    con_scan@            ; scan for special chars
  3758.     jmp    norm_table[si]
  3759.  
  3760. con_normal@:
  3761. ;----------
  3762. ; Normal console vector state:
  3763. ;  entry:    cl,al = character
  3764. ;        bx = VC_ base
  3765. ;        dx = cursor
  3766.  
  3767.     cmp    al,' '                ; non-character?
  3768.      jb    con_control            ; try to avoid jumps 
  3769.  
  3770. vc_out@:
  3771. ;------
  3772. ; Printable character to virtual console ram image:
  3773. ;  entry:    bx -> VC_
  3774. ;        cl = character
  3775. ;        dx = cursor
  3776.  
  3777.      call    get_point_pc            ; get pointer to physical screen struc.
  3778.     mov    al,cl
  3779.     call    NX_conout_xlat        ; xlat char for national 7 bit display
  3780.     mov    cl,al                ; translated char
  3781.     push    cx                ; save char
  3782.     test    VC_MODE,MATCH_BIT        ; top screen ?
  3783.     jnz    vc_out_bg            ; no...
  3784.     call    wait_sync            ; wait for synchronized screen
  3785.     call    ser_mx                ; lock out serial I/O
  3786.     mov    ax,VC_CURSOR
  3787.     call    set_pcursor            ; make sure cursor in right place
  3788.     mov    ah,VC_ATTRIB
  3789.     call    set_pattrib            ; set physical attribute
  3790.     pop    ax                 ; get char
  3791.     cmp    al,' '                ; check if character large enough
  3792.     jae    go_vcout            ; go ahead if printable
  3793.     push     ax                ; else output ESC
  3794.     mov    al,ESC                ;   for terminal to recognize
  3795.     call    tmp_write            ;   sequence as illegal and to
  3796.     pop    ax                ; and print control char
  3797. go_vcout:
  3798.     push     ax                ; save char
  3799.     call    tmp_write            ; now write this character
  3800.     inc    PC_CURCOL            ; increment column count
  3801.     mov    PC_BUSY,00h            ; release serial semaphore
  3802. vc_out_bg:
  3803.     pop    ax                ; get char
  3804.  
  3805.     mov    dx,VC_CURSOR
  3806.     push    es
  3807.     mov    di,VC_OFFSET            ; point to screen buffer
  3808.     shl    di,1
  3809.     mov    ah,VC_ATTRIB
  3810.     mov    es,VC_CRT_SEG
  3811.     add    di,CLNOFF
  3812.     stosw                    ; update virtual, don't set D
  3813.  
  3814.     test    VC_MODE,MATCH_BIT        ; top screen ?
  3815.     jnz    vc_out_bg1
  3816.     add    di,IMGOFF-CLNOFF-2        
  3817.     stosw                    ; update physical image if top
  3818. vc_out_bg1:
  3819.     pop    es
  3820.     inc    dl                ; advance cursor
  3821.     cmp    dl,VC_WIDTH            ; if not wrapping around
  3822.      jae    vc_out2                ;   then do cursor
  3823.     mov    VC_CUR_COL,dl            ; update the cursor address
  3824.     mov    ax,dx
  3825.     inc    VC_OFFSET            ; row/col plus index
  3826.     ret
  3827. vc_out2:
  3828.     test    VC_MODE,WRAP_BIT
  3829.      jz    vc_out3                ; exit if not wrapping
  3830.     call    vc_out_cr@            ; send CR, LF and update
  3831.     jmp    vc_out_lf@            ; cursor
  3832. vc_out3:
  3833.     ret                    ; don't touch cursor
  3834.  
  3835.  
  3836. con_scan@:
  3837. ;---------
  3838. ; Scan character string for match:
  3839. ;  entry:    di -> string
  3840. ;        cx = count
  3841. ;        al = charater
  3842. ;  exit:    si = word table index, or just past the end
  3843. ;             of the table if character is not found
  3844. ;        al,cl = character
  3845.  
  3846.     push    es
  3847.     push    ds
  3848.     pop    es                ; local extra segment
  3849.     mov    si,cx
  3850.     repnz    scasb                ; look for match
  3851.      jnz    con_scan1            ; if no match, skip
  3852.     dec    si                ; correct count
  3853. con_scan1:
  3854.     sub    si,cx                ; si = char number
  3855.     shl    si,1                ; word pointer
  3856.     mov    cl,al                ; copy character
  3857.     pop    es
  3858.     ret
  3859.  
  3860.  
  3861. restore_state@:
  3862. ;--------------
  3863. ; Restore the state vector to normal:
  3864.     and    VC_MODE,not ESC_BIT        ; turn off ESC bit
  3865.     mov    VC_VECTOR,offset con_normal@
  3866.     ret                    ; that's all
  3867.  
  3868. leave_until_char@:
  3869. ;----------------
  3870.     or    VC_MODE,ESC_BIT            ; next char. into state machine
  3871.     pop    VC_VECTOR            ; pop return addr into state vector
  3872.     ret
  3873.  
  3874. vc_out_cr@:
  3875. ;----------
  3876. ; VC carriage return out:
  3877.  
  3878.     sub    dl,dl                ; first column
  3879. ;    jmps    put_cursor@            ; update and display
  3880.  
  3881. put_cursor@:
  3882. ;-----------
  3883. ; Update and display cursor if appropriate:
  3884.  
  3885.     call    pc_point_curs@
  3886.     mov    VC_OFFSET,ax
  3887.     mov    VC_CURSOR,dx
  3888.     test    VC_MODE,MATCH_BIT        ; top screen ?
  3889.     jnz    put_cursor_exit            ; no .. leave
  3890.     push    dx                ; save cursor
  3891.     call    wait_sync            ; wait for synchronized screen
  3892.      call    get_point_pc            ; get pointer to physical screen struc.
  3893.     call    ser_mx                ; lock out serial I/O
  3894.     call    poke_ros_cursor@        ; done below
  3895.     mov    ax,VC_CURSOR
  3896.     call    set_pcursor            ; make sure cursor in right place
  3897.     mov    PC_BUSY,00h            ; release serial semaphore
  3898.     pop    dx                ; restore cursor
  3899. put_cursor_exit:
  3900.     ret
  3901.  
  3902. show_cursor@:
  3903.     ret
  3904.  
  3905. pc_point_curs@:
  3906. ;-------------
  3907. ; Point to vc image from cursor row,column:
  3908. ;  entry:    dx = (row,column)
  3909. ;        bx -> vc_
  3910. ;  exit:    ax = vc_width*row + column
  3911. ;        di = 2*ax
  3912. ;        dx = preserved
  3913.  
  3914.     mov    al,VC_WIDTH
  3915.     mul    dh                ; ax = row * (40 or 80)
  3916.     add    al,dl                ; add in the column
  3917.     adc    ah,0                ;   and handle the carry
  3918.     mov    di,ax
  3919.     shl    di,1                ; di = 2*ax
  3920.     ret
  3921.  
  3922. poke_ros_cursor@:
  3923. ;----------------
  3924.     push    es
  3925.     push    ax
  3926.     mov    ax,PC_SEGMENT        ; make sure cursor reflects ROS value
  3927.     mov    es,ax
  3928.     mov    ax,VC_CURSOR        ; finally update ROS values
  3929.     mov    es:cursor_posn_40,ax    ; assume page zero
  3930.     pop    ax
  3931.     pop    es
  3932.     ret
  3933.  
  3934. put_crt_s@:
  3935. ;----------
  3936.     push    es
  3937.     mov    es,VC_CRT_SEG
  3938.     rep    stosw
  3939.     pop    es
  3940.     ret
  3941.  
  3942.  
  3943. vc_out_bs@:
  3944. ;----------
  3945. ; VC back space:
  3946.  
  3947.     dec    dl                ; back one column
  3948.      jns    put_cursor@            ; if not at left
  3949.     test    VC_MODE,WRAP_BIT
  3950.      jz    vc_bs1                ; if no wrap, done
  3951.     mov    dl,VC_WIDTH            ; if at left, wrap
  3952.     sub    dx,0101h            ; up one, left one
  3953.      jns    put_cursor@            ; if not at top
  3954. vc_bs1:
  3955.     ret                    ; if top left, bag it
  3956.  
  3957. vc_out_lf@:
  3958. ;----------
  3959. ; VC line feed out:
  3960.  
  3961.     mov    al,VC_CRT_ROWS            ; get our screen size
  3962.     dec    al                ; al = number of last line
  3963.     cmp    dh,al                ; if at the bottom
  3964.      jae    vc_lf_scroll            ;   do a scroll
  3965.     inc    dh                ; if not, move down
  3966.     mov    VC_CURSOR,dx            ; save the cursor value
  3967.     mov    ax,dx
  3968.     call    poke_ros_cursor@        ; in ros area too
  3969.     add    VC_OFFSET,CRT_COLS
  3970. vc_lf_show:
  3971.     jmps    show_cursor@            ; display current cursor
  3972.  
  3973. vc_lf_scroll:
  3974.     mov    si,offset lf_seq        ; send sequence directly
  3975.     cmp    VC_CRT_ROWS,CRT_ROWS_P        ; test if 24 or 25 lines
  3976.      je    vc_lf_scroll1            ; skip if 25 lines
  3977.     mov    si,offset lfcpm_seq        ; else use some magic
  3978. vc_lf_scroll1:                    ; SI -> direct sequence
  3979.     call    xlat_esc            ;   then update the image
  3980.  
  3981.     sub    ax,ax                ; zero offset from
  3982.     mov    di,ax                ;   the top left
  3983.     mov    si,CRT_COLS*2            ; one row down
  3984.     jmp    z_line                ; delete one line to scroll
  3985.  
  3986. vc_out_bel@:
  3987. ;-----------
  3988. ; VC beep the bell for top screen only:
  3989.     test    VC_MODE,MATCH_BIT    ; top screen ?
  3990.     jnz    vc_bel_done
  3991.     call    wait_sync        ; wait for synchronized screen
  3992.      call    get_point_pc        ; get pointer to physical screen struc.
  3993.     call    ser_mx            ; lock out serial I/O
  3994.     mov    al,BEL            ; output BELL
  3995.     call    tmp_write
  3996.     mov    PC_BUSY,00h        ; release serial semaphore
  3997.  
  3998. vc_bel_done:
  3999.     ret
  4000.  
  4001.  
  4002. vc_out_esc:
  4003. ;----------
  4004.     call    leave_until_char@        ; comes back here:
  4005.  
  4006. ; Console escape sequence branch point:
  4007. ;  entry:    cl,al = character
  4008. ;        bx = VC_base
  4009. ;        dx = cursor
  4010.  
  4011.     call    restore_state@        ; VC_VECTOR back to normal
  4012.     mov    di,offset esc_scan$
  4013.     mov    cx,ESC_COUNT
  4014.     call    con_scan@        ; scan for escape chars
  4015.     jmp    esc_table$[si]
  4016.  
  4017.  
  4018. ; ESC sequences and special character support:
  4019.  
  4020. z_up@:
  4021. ; ESC A  -  cursor up:
  4022.     dec    dh            ; next row up
  4023.      jns    z_cursor        ; if not already on top,
  4024.     ret                ;   then set cursor
  4025.  
  4026. z_down:
  4027. ; ESC B  -  cursor down:
  4028.     inc    dh                ; next row down
  4029.     cmp    dh,VC_CRT_ROWS            ; if not already at bottom,
  4030.      jb    z_cursor            ;   then set cursor
  4031.     ret
  4032.  
  4033. z_forward:
  4034. ; ESC C  -  cursor forward:
  4035.     inc    dl                ; next column right
  4036.     cmp    dl,CRT_COLS            ; if not already at right,
  4037.      jb    z_cursor            ;   then set cursor
  4038.     ret
  4039.  
  4040. z_back:
  4041. ; ESC D  -  cursor backward:
  4042.     dec    dl                ; next column left
  4043.      jns    z_cursor            ; if not already at left,
  4044.     ret                    ;   then set cursor
  4045.  
  4046. z_erase@:
  4047. ; ESC E  -  erase console:
  4048.     call    z_home                ; get to top left
  4049.     sub    dx,dx                ; top left
  4050.     jmps    z_erase_eos@            ; erase to end
  4051.  
  4052. z_home:
  4053. ; ESC H  -  home cursor:
  4054.     sub    dx,dx                ; 0,0 = top left corner
  4055. ;    jmps    z_cursor
  4056.  
  4057. z_cursor:
  4058.     jmp    put_cursor@            ; save and display if visible
  4059.  
  4060. z_rev_index:
  4061. ; ESC I  -  reverse index:
  4062.     test    dh,dh                ; if not on the top row,
  4063.      jnz    z_up@                ;   then just move up
  4064.     jmp    z_insert_line@            ; else scroll down from top
  4065.  
  4066. z_erase_eos@:
  4067. ; ESC J  -  erase to end of screen:
  4068.  
  4069.     mov    si,offset eos_seq        ; send physical sequence
  4070.     call    xlat_esc            ;  & emulate in virtual plane
  4071. ;#IJ    mov    ch,VC_CRT_ROWS            ; erase to bottom corner
  4072.     mov    ch,CRT_ROWS_P            ; erase to bottom corner
  4073.     sub    cl,cl
  4074.     call    eraser                ; common code
  4075. ; the physical screen is out of step with the image on the status line
  4076. ; so we blank the status line reference to correspond
  4077.     pusha
  4078.     push    es
  4079.     mov    ax,CRT_SEG        ; point to screen seg
  4080.     mov    es,ax
  4081.     mov    cx,CRT_ROWS_C        ; line length
  4082.     mov    di,(2*CRT_ROWS_C*CRT_COLS)+IMGOFF
  4083.     mov    ax,7*256+' '        ; make image all spaces
  4084.     cld
  4085.     rep    stosw            ; blank the reference image too
  4086.     pop    es
  4087.  
  4088.     mov    bx,rlr$
  4089.     mov    dl,P_CONS[bx]            ; get process VC number
  4090.     call    get_ccb                ; get the CCB
  4091.     mov    dl,C_PC[di]            ; hence the PCon number
  4092.     xor    cx,cx                ; normal statline call
  4093.     call    fl_io_statline            ; force statline update
  4094.     popa
  4095.     ret
  4096.     
  4097. z_erase_eol@:
  4098. ; ESC K  -  erase to end of line:
  4099.  
  4100.     mov    si,offset eol_seq        ; send physical sequence
  4101.     call    xlat_esc            ;  & emulate in virtual plane
  4102.     mov    ch,dh                ; this row
  4103.     inc    ch                ; to the next row,
  4104.     sub    cl,cl                ;   first column
  4105.     jmps    eraser                ; common code
  4106.  
  4107. z_insert_line@:
  4108. ; ESC L  -  insert a BLANK line:
  4109.  
  4110.     mov    si,offset ins_seq        ; send sequence directly
  4111.     cmp    VC_CRT_ROWS,CRT_ROWS_P        ; test if 24 or 25 lines
  4112.      je    z_ins_dos            ; skip if 25 lines
  4113.     pushf                    ; life is complicated by the
  4114.     cli                    ; need to modify the sequence
  4115.     mov    ax,VC_CURSOR            ; get virtual cursor
  4116.     xchg    al,ah                ; AL = row, AH = col
  4117.     add    ax,2020h            ; add in row/column bias
  4118.     mov    inscpm_cpos,ax            ; patch the sequence
  4119.     mov    si,offset inscpm_seq        ; this is the sequence we want
  4120.     lea    di,VC_ANSI_BUF            ; we can't be in ANSI seq here
  4121.     cld                    ; so we can reuse the buffer
  4122.     mov    cx,4                ; for a per-terminal copy
  4123.     push    es                ; of the sequence
  4124.     push    ds                ; make ES=DS
  4125.     pop    es                ; for the copy - all this
  4126. OP_32 !    rep    movsw                ; to avoid re-entrancy problems
  4127.     pop    es                ; restore ES
  4128.     popf                    ; we are safe again...
  4129.     lea    si,VC_ANSI_BUF            ; send out the copy
  4130. z_ins_dos:                    ; SI -> direct sequence
  4131.     call    xlat_esc            ; perform clean update
  4132.     mov    al,CRT_COLS
  4133.     mul    VC_CRT_ROWS            ; ax = crt size
  4134.     dec    ax
  4135.     mov    di,ax
  4136.     sub    ax,CRT_COLS
  4137.     mov    si,ax
  4138.     shl    di,1                ; end of screen
  4139.     shl    si,1                ; one line up
  4140.  
  4141.     sub    dl,dl                ; first column
  4142.     mov    al,VC_WIDTH            ; do pc_point_curs w/out disturbing di
  4143.     mul    dh                ; AX = count from top
  4144.     std                    ; backwards move
  4145.     jmps    z_ins_del_line            ; shared code
  4146.  
  4147.  
  4148. z_erase_bos@:
  4149. ; ESC d  -  erase from beginning of screen:
  4150.  
  4151.     mov    cx,dx                ; current location
  4152.     sub    dx,dx                ; top left corner start
  4153.     jmps    eraser
  4154.  
  4155. z_erase_line@:
  4156. ; ESC l  -  erase entire line:
  4157.  
  4158.     sub    dl,dl                ; from first column
  4159.     mov    cx,dx                ; to the first column
  4160.     inc    ch                ;   of the next row
  4161.     jmps    eraser
  4162.  
  4163. z_erase_bol@:
  4164. ; ESC o  -  erase from beginning of line:
  4165.  
  4166.     mov    cx,dx                ; erase to cursor
  4167.     sub    dl,dl                ; from first column
  4168. ;    jmps    eraser
  4169. eject
  4170.  
  4171. eraser:
  4172. ; Common erase routine:
  4173. ;  entry:    dx = start of erase row,column
  4174. ;        cx = one past ending row,column
  4175.  
  4176.     xchg    cx,dx                ; dx = one past the end
  4177.     call    pc_point_curs@            ; ax = end pointer
  4178.     xchg    cx,dx                ; dx = start cursor
  4179.     xchg    ax,cx                ; cx = end pointer
  4180.     call    pc_point_curs@            ; ax = start pointer
  4181.     sub    cx,ax                ; cx = erase char count
  4182.      jnz    erase                ; skip if something to erase
  4183.     ret                    ; return if nothing
  4184. erase:
  4185.     mov    al,' '                ; erase to blanks
  4186.     mov    ah,VC_ATTRIB            ;   of the current attribute
  4187. ;    jmps    erase_pc@
  4188.  
  4189.  
  4190. erase_pc@:
  4191. ; This is an entry used by the pc mode emulator:
  4192.  
  4193.     jmp    put_crt_s@            ; if full top, go to physical
  4194.  
  4195.  
  4196. z_delete_line@:
  4197. ; ESC M  -  delete one line:
  4198.  
  4199.     mov    si,offset del_seq        ; handle ESC sequence directly
  4200.     cmp    VC_CRT_ROWS,CRT_ROWS_P        ; test if 24 or 25 lines
  4201.      je    z_del_dos            ; skip if 25 lines
  4202.     mov    si,offset delcpm_seq        ; else use some magic
  4203. z_del_dos:                    ; SI -> direct sequence
  4204.     call    xlat_esc            ;   & call image update
  4205.     sub    dl,dl
  4206.     call    pc_point_curs@            ; di -> line start
  4207.     mov    si,di
  4208.     add    si,CRT_COLS*2            ; next row down
  4209. z_ins_del_line:
  4210.     push    ax
  4211.     mov    ax,dx
  4212.     call    poke_ros_cursor@
  4213.     pop    ax
  4214.     xchg    VC_CURSOR,dx
  4215.     xor    dh,dh
  4216.     sub    VC_OFFSET,dx            ; cursor moves to 1st col.
  4217. ;    jmps    z_line
  4218.  
  4219. z_line:
  4220. ; External entry point:
  4221. ;  entry:    si,di set up for movsw
  4222. ;        ax = count from top of screen
  4223.     xchg    ax,cx                ; cx = count
  4224.     mov    al,CRT_COLS
  4225.     mul    VC_CRT_ROWS            ; ax = crt size
  4226.     sub    ax,CRT_COLS
  4227.     xchg    ax,cx
  4228.     sub    cx,ax                ; cx = character count
  4229.      jbe    z_line1                ; skip if nothing to move
  4230.  
  4231.     call    z_movsw@            ; movsw in vc_segment
  4232. z_line1:
  4233.     mov    cx,CRT_COLS            ; one line's worth
  4234.     call    erase                ; blank one line
  4235.     cld                    ; clear dir. flag (insert)
  4236.     jmp    show_cursor@
  4237.  
  4238.  
  4239. z_movsw@:
  4240. ; repeat movsw in current screen segment:
  4241.     push    es
  4242.     push    ds                ; save around the move
  4243.     mov    es,VC_CRT_SEG            ; else move physical
  4244.     push es ! pop ds            ; move within the seg
  4245.     rep    movsw
  4246.     pop    ds
  4247.     pop    es
  4248.     ret
  4249.  
  4250.  
  4251. z_delete_char:
  4252. ; ESC N  -  delete one character:
  4253.     mov    di,VC_OFFSET
  4254.     shl    di,1                ; DI -> current char
  4255.  
  4256.     mov    cx,CRT_COLS-1            ; last column
  4257.     sub    cl,dl                ; cx = chars to line end
  4258.      jz    z_del_ch1            ; skip if at line end
  4259.     mov    si,di
  4260.     inc    si                ; next char right
  4261.     inc    si
  4262.     call    z_movsw@            ; shift left one char
  4263. z_del_ch1:
  4264.     mov    cx,1                ; erase one last char
  4265.     jmp    erase
  4266.  
  4267. z_set_cursor:
  4268. ; ESC Y  -  set cursor position:
  4269.     call    leave_until_char@
  4270.     sub    cl,' '                ; correct for space offset
  4271.      js    z_set_col            ; if illegal, skip row set
  4272.     cmp    cl,VC_CRT_ROWS            ; check upper bound
  4273.      jae    z_set_col            ; 25 :== 0 through 24 ok
  4274.     mov    VC_CUR_ROW,cl            ; save the row
  4275. z_set_col:
  4276.     call    leave_until_char@
  4277.     sub    cl,' '                ; correct for space offset
  4278.      js    z_set_done            ; if illegal, skip col set
  4279.     cmp    cl,CRT_COLS            ; check upper bound
  4280.      jae    z_set_done            ; 80 :== 0 through 79 ok
  4281.     mov    dl,cl                ; dx = new cursor location
  4282. z_set_done:
  4283.     call    restore_state@            ; back to normal
  4284.     mov    ax,VC_CURSOR            ;
  4285.     jmp    put_cursor@            ; update and display new curs.
  4286.  
  4287. z_set_fore:
  4288. ; ESC b  -  set foreground color:
  4289.     call    leave_until_char@
  4290. z_fore1@:                ;ANSI entry point
  4291.     mov    ah,VC_ATTRIB            ; current attribute
  4292.     jmps    z_fg_bg                ; shared code
  4293.  
  4294. z_set_back:
  4295. ; ESC c  -  set background color:
  4296.     call    leave_until_char@
  4297.     mov    ah,al                ; ah = bg bits
  4298.     mov    cl,4
  4299.     rol    ah,cl                ; bg bits to ms nibble
  4300.     mov    al,VC_ATTRIB
  4301. z_fg_bg:
  4302.     and    al,0fh                ; take the 4 lsb's of al
  4303.     and    ah,0f0h                ;   and the 4 msb's of ah
  4304.     or    al,ah                ;   and mash 'em together
  4305.     mov    VC_ATTRIB,al            ; that's the new attribute
  4306.     jmp    restore_state@            ; back to normal
  4307.  
  4308.  
  4309. z_cursor_on:
  4310. ; ESC e  -  enable cursor:
  4311.     or    VC_MODE,CURSOR_BIT
  4312.     jmp    cursor_on            ; turn on and return
  4313.  
  4314. z_cursor_off:
  4315. ; ESC f  -  disable cursor:
  4316.     and    VC_MODE,not CURSOR_BIT
  4317.     jmp    cursor_off            ; turn off and return
  4318.  
  4319. z_save_cursor@:
  4320. ; ESC j - save cursor position:
  4321.     mov    VC_SAVE_CURSOR,dx
  4322.     ret                    ; save for later
  4323.  
  4324. z_restore_cursor@:
  4325. ; ESC k  -  restore cursor position:
  4326.     mov    dx,VC_SAVE_CURSOR
  4327.     jmp    put_cursor@            ; back where it was
  4328.  
  4329. z_rev_on@:
  4330. ; ESC p  -  reverse video on:
  4331.     test    VC_MODE,REV_BIT            ; if already reversed
  4332.      jnz    z_rev2                ;   then forget it
  4333.     or    VC_MODE,REV_BIT            ; remember
  4334.     jmps    z_rev1                ; to common code
  4335.  
  4336. z_rev_off:
  4337. ; ESC q  -  reverse video off:
  4338.     test    VC_MODE,REV_BIT            ; if already off
  4339.      jz    z_rev2                ;   then forget it
  4340.     and    VC_MODE,not REV_BIT
  4341. z_rev1:                        ; shared code
  4342.     mov    al,VC_ATTRIB            ; get current colors
  4343.     mov    ah,al                ; copy for msb's
  4344.     and    ax,8877h            ; mask colors only
  4345.     mov    cl,4
  4346.     rol    al,cl                ; swap colors
  4347.     or    al,ah                ; restore intense, blink
  4348.     mov    VC_ATTRIB,al            ; new attribute
  4349. z_rev2:
  4350.     ret
  4351.  
  4352. z_intense_on@:
  4353. ; ESC r  -  intensity on:
  4354.     or    VC_ATTRIB,08h            ; set the intense bit
  4355.     ret
  4356.  
  4357. z_intense_off:
  4358. ; ESC u  -  intensity off:
  4359.     and    VC_ATTRIB,0f7h            ; reset the intense bit
  4360.     ret
  4361.  
  4362. z_blink_on@:
  4363. ; ESC s  -  blink on:
  4364.     or    VC_ATTRIB,80h            ; set the blink bit
  4365.     ret
  4366.  
  4367. z_blink_off:
  4368. ; ESC t  -  blink off:
  4369.     and    VC_ATTRIB,7fh            ; reset the blink bit
  4370.     ret
  4371. eject
  4372.  
  4373. z_wrap_on:
  4374. ; ESC v  -  wrap at line end on:
  4375.     or    VC_MODE,WRAP_BIT
  4376.     ret
  4377.  
  4378. z_wrap_off:
  4379. ; ESC w  -  no wrap at line end:
  4380.     and    VC_MODE,not WRAP_BIT
  4381. z_return:
  4382.     ret
  4383.  
  4384. z_pfk_off@:
  4385. ; esc 6  -  turn pfk expansion off
  4386.  
  4387.     mov    VC_PFK_EXP,0            ; expansion flag false
  4388.     ret
  4389.  
  4390. z_pfk_on@:
  4391. ; esc 7  -  turn pfk expansion on
  4392.  
  4393.     mov    VC_PFK_EXP,0FFh            ; expansion flag true
  4394.     ret
  4395.  
  4396. z_set_color@:
  4397.  
  4398. z_set_mono@:
  4399.  
  4400. z_video_mode:
  4401.  
  4402. z_prog_pfk@:
  4403.  
  4404. z_back_door:
  4405.  
  4406. z_norm_attr:
  4407.  
  4408.     ret
  4409.  
  4410. z_sl_color@:            ; we only have mono, so turn that off
  4411.     jmp    z_sl_off@
  4412.  
  4413. z_sl_both@:            ; we only have mono, so turn that on
  4414.     jmp    z_sl_mono@    
  4415.  
  4416. ;#IJ These are now implemented
  4417.  
  4418. ;#IJ z_sl_off@:
  4419. ;#IJ z_sl_mono@:
  4420. ;#IJ z_clk_off@:
  4421. ;#IJ z_clk_on@:
  4422.  
  4423.  
  4424.  
  4425.     
  4426. eject
  4427.     
  4428. ;  ANSI Escape sequence handler
  4429. ;  entry:    
  4430. ;        bx = VC_base
  4431. ;        dx = cursor
  4432.  
  4433. ;    ESC '[' - ANSI lead in character
  4434. ;
  4435. ;    The folowing ANSI standard codes (taken from the PC DOS 2.0
  4436. ;    manual are to be supported:
  4437.  
  4438. ;    ESC [ n;nH    Move cursor to row, col (default 1;1)
  4439. ;    ESC [ nA    Move cursor up (default 1)
  4440. ;    ESC [ nB    Move cursor down (default 1)
  4441. ;    ESC [ nC    Move cursor right (default 1)
  4442. ;    ESC [ nD    Move cursor left (default 1)
  4443. ;    ESC [ n;nf    same as "ESC [n;nH"
  4444. ;    ESC [ s        save cursor position
  4445. ;    ESC [ u        restore cursor position
  4446. ;    ESC [ 0J    erase end of screen
  4447. ;    ESC [ 1J    erase beginning of screen
  4448. ;    ESC [ 2J    erase screen, home cursor
  4449. ;    ESC [ J        erase screen
  4450. ;    ESC [ 0K    erase end of line
  4451. ;    ESC [ 1K    erase beginning of line
  4452. ;    ESC [ 2K    erase entire line
  4453. ;    ESC [ K        erase end of line
  4454. ;    ESC [ L        insert line
  4455. ;    ESC [ M        delete line
  4456. ;    ESC [ n;nm    Set the Character Rendition
  4457. ;    ESC [ = n h    Set the Screen Mode
  4458. ;    ESC [ = n l    Reset the Screen Mode
  4459. ;    ESC [ 6 n    Device Status Report
  4460. ;
  4461. z_ansi@:
  4462. ;------
  4463.     mov    VC_ANSI_COUNT,0        ; no number specified
  4464.     lea    di, VC_ANSI_BUF        ; point to number buffer
  4465.     mov    cx, VC_ANSI_SIZE    ; up to 15 numbers
  4466. z_ansi1a:
  4467.     mov    byte ptr [di],0ffh
  4468.     inc     di
  4469.     loop    z_ansi1a
  4470.     
  4471. z_ansi1:
  4472.     call    leave_until_char@    ; wait for parameters
  4473.                     ; reenter handler here...
  4474.     cmp    al, '0'            ; is it a number?
  4475.     jb    z_ansi3            ; no, delimiter or command
  4476.     cmp    al, '9'            ; is it a number?
  4477.     ja    z_ansi3            ; no, delimiter or command
  4478.     mov    si, VC_ANSI_COUNT    ; Next character to add
  4479.     sub    al, '0'            ; make it a number
  4480.     mov    cl, al            ; save the character
  4481.     lea    di, VC_ANSI_BUF
  4482.     add    di,si
  4483.     mov    al, [di]        ; get numeric value from BUF
  4484.     cmp    al, 0FFh        ; initial digit?
  4485.      jne    z_ansi2            ; skip if not first
  4486.     sub    ax, ax            ; zero it out
  4487. z_ansi2:
  4488.     mov    ah, 10            ; old value * 10
  4489.     mul    ah            ;   before we add
  4490.     add    al, cl            ;   in new digit.
  4491.     mov    [di], al        ; save it in VC_ANSI_BUF
  4492.     jmps    z_ansi1            ; wait for more digits
  4493.  
  4494. z_ansi3:                ; it wasn't a digit
  4495.     cmp    al, ';'            ; is it a delimiter?
  4496.      jnz    z_ansi5            ; no, must be command
  4497.  
  4498.     cmp    VC_ANSI_COUNT, VC_ANSI_SIZE-2    ; is the buffer full?
  4499.      jz    z_ansi1                ; skip if not yet
  4500.     inc    VC_ANSI_COUNT            ; move on to next number
  4501.     jmps    z_ansi1
  4502.  
  4503. z_ansi5:                ; reenter handler here...
  4504.     call    restore_state@        ; exit escape handling
  4505.     mov    di, offset ansi_tbl    ; check which one it is
  4506.     mov    cx, length ansi_tbl    ; number of chars to check
  4507.     call    con_scan@        ; lookup table, --> jump index
  4508.     jmp    ansi_jmp[si]        ; invoke the handler
  4509.  
  4510.  
  4511.  
  4512.  
  4513. con_null:
  4514.     ret
  4515.  
  4516. ;    ESC [ n A    - cursor up
  4517. ansi_cuu:
  4518.     call    ansi_def1        ; how many lines
  4519.     sub    dh, al            ; up by N lines
  4520.     jae    ansi_cur2        ; update cursor
  4521.     ret
  4522.  
  4523. ;    ESC [ n A    - cursor down
  4524. ansi_cud:
  4525.     call    ansi_def1        ; how many lines
  4526.     add    dh, al            ; down by N lines
  4527.     cmp    dh, VC_CRT_ROWS        ; legal row?
  4528.     jb    ansi_cur2        ; yes, update cursor
  4529.     ret
  4530.  
  4531. ;    ESC [ n A    - cursor right
  4532. ansi_cuf:
  4533.     call    ansi_def1        ; how many columns
  4534.     add    dl, al            ; right by N column
  4535.     cmp    dl, CRT_COLS
  4536.     jb    ansi_cur2        ; update cursor
  4537.     ret
  4538.  
  4539.  
  4540. ;    ESC [ n A    - cursor left
  4541. ansi_cub:
  4542.     call    ansi_def1        ; how many columns
  4543.     sub    dl, al            ; left by N column
  4544.     jae    ansi_cur2        ; update cursor
  4545.     ret
  4546.  
  4547.  
  4548. ;    Esc [ n;n H
  4549. ;    ESC [ n;n f    - position cursor
  4550. ansi_cup:
  4551. ansi_hvp:
  4552.     mov    dx,word ptr VC_ANSI_BUF        ; get column/row
  4553.     xchg    dl, dh            ; swap them round (8086 byte order)
  4554.     cmp    dh,0FFh            ; Check for unspecified values
  4555.      jnz    ansi_cup1        ; and insert default of 1
  4556.     mov    dh,1
  4557. ansi_cup1:
  4558.     cmp    dl,0FFh
  4559.      jnz    ansi_cursor
  4560.     mov    dl,1
  4561.  
  4562. ansi_cursor:
  4563.     sub    dx, 0101h        ; ANSI is biased by one
  4564.     cmp    dl, CRT_COLS        ; column in range?
  4565.     jb    ansi_cur1        ; truncate if not
  4566.     mov    dl, CRT_COLS
  4567.     dec    dl
  4568. ansi_cur1:
  4569.     cmp    dh, VC_CRT_ROWS        ; row in range
  4570.     jb    ansi_cur2        ; truncate if not
  4571.     mov    dh, VC_CRT_ROWS
  4572.     dec    dh
  4573. ansi_cur2:
  4574.     jmp    put_cursor@        ; update row/col
  4575.  
  4576.  
  4577. ;    ESC [ nn J    - erase display
  4578. ;
  4579. ;    nn = 0        - erase end of display
  4580. ;    nn = 1        - erase beginning of display
  4581. ;    nn = 2        - erase entire line
  4582. ;    (default = 0)
  4583.  
  4584. ansi_ed:
  4585.     mov    al, VC_ANSI_BUF        ; point to parameter
  4586.     cmp    al, 0FFh        ; is it the default?
  4587.      je    ansi_ed0        ; yes, erase end of display
  4588.     test    al, al            ; is it "0"?
  4589.      jnz    ansi_ed1        ; skip if not
  4590. ansi_ed0:
  4591.     jmp    z_erase_eos@        ; handle like VT52
  4592. ansi_ed1:
  4593.     dec    al            ; is it "1"?
  4594.      jnz    ansi_ed2        ; skip if not
  4595.     jmp    z_erase_bos@        ; erase beginning of line
  4596. ansi_ed2:
  4597.     jmp    z_erase@        ; else erase entire display
  4598.  
  4599.  
  4600. ;    ESC [ nn K    - erase line
  4601. ;
  4602. ;    nn = 0        - erase end of line
  4603. ;    nn = 1        - erase beginning of line
  4604. ;    nn = 2        - erase entire line
  4605. ;    (default = 0)
  4606.  
  4607. ansi_el:
  4608.     mov    al, VC_ANSI_BUF        ; point to parameter
  4609.     cmp    al, 0FFh        ; is it the default?
  4610.      je    ansi_el0        ; yes, erase end of line
  4611.     test    al, al            ; is it "0"?
  4612.      jnz    ansi_el1        ; skip if not
  4613. ansi_el0:
  4614.     jmp    z_erase_eol@        ; handle like VT52
  4615. ansi_el1:
  4616.     dec    al            ; is it "1"?
  4617.      jnz    ansi_el2        ; skip if not
  4618.     jmp    z_erase_bol@        ; erase beginning of line
  4619. ansi_el2:
  4620.     jmp    z_erase_line@        ; else erase entire line
  4621.  
  4622.  
  4623. ;    ESC [ L        insert line
  4624. ;    ESC [ M        delete line
  4625. ;ansi_il        equ    z_insert_line@
  4626. ;ansi_dl        equ    z_delete_line@
  4627.  
  4628.  
  4629. ;    ESC [ n;nm    Set the Character Rendition
  4630. ansi_sgr:
  4631.     lea    si,VC_ANSI_BUF        ; point at 1st parameter
  4632.     cmp    byte ptr [si],0FFh    ; no parameters?
  4633.      je    ansi_sgr0        ; then set defaults
  4634. ansi_sgr_next:
  4635.     lodsb                ; else get parameter
  4636.     cmp    al,0FFh            ; stop if end of parameters
  4637.      je    ansi_sgr_ret
  4638.     push    si
  4639.     call    ansi_sgr_x        ; set attribute
  4640.     pop    si
  4641.     jmps    ansi_sgr_next        ; more parameters
  4642.  
  4643. ansi_sgr_ret:
  4644.     ret
  4645.  
  4646. ansi_sgr0:
  4647.     mov    al,07h            ; get the initial attribute
  4648.     mov    VC_ATTRIB,al        ; and update the current attribute
  4649.     and    VC_MODE,not REV_BIT    ; turn off reverse video and leave 
  4650.     ret                ; wrap and cursor state unchanged.
  4651.  
  4652. ansi_sgr_x:
  4653.     test    al, al            ; 0?
  4654.      jz    ansi_sgr0        ; reset inverse
  4655. ansi_sgr1:
  4656.     cmp    al, 1            ; high intensity
  4657.      jne    ansi_sgr4
  4658.     jmp    z_intense_on@
  4659. ansi_sgr4:
  4660.     cmp    al, 4            ; underscore on
  4661.      jne    ansi_sgr5
  4662.     cmp    VC_CRT_SEG,MONO_SEG    ; This function is only enabled on
  4663.      jnz    ansi_sgr_exit        ; Monochrome Screens
  4664.     mov    al, 1
  4665.     jmp    z_fore1@
  4666. ansi_sgr5:
  4667.     cmp    al, 5            ; blink on
  4668.      jne    ansi_sgr7
  4669.     jmp    z_blink_on@
  4670. ansi_sgr7:
  4671.     cmp    al, 7            ; reverse on
  4672.      jne    ansi_sgr8
  4673.     jmp    z_rev_on@
  4674. ansi_sgr8:
  4675.     cmp    al, 8
  4676.      jne    ansi_sgr30
  4677.     and    VC_ATTRIB, 88h        ; make it invisible
  4678.     ret
  4679.  
  4680. ansi_sgr30:
  4681. ;;    cmp    VC_CRT_SEG,COLOR_SEG    ; These functions are disabled on
  4682. ;;     jnz    ansi_sgr_exit        ; Monochrome Screens
  4683.  
  4684. ansi_sgr_exit:
  4685.     ret
  4686.  
  4687.  
  4688. ;    ESC [ s        save cursor position
  4689. ;    ESC [ u        restore cursor position
  4690. ;ansi_scp    equ    z_save_cursor@
  4691. ;ansi_rcp    equ    z_restore_cursor@
  4692.  
  4693.  
  4694. ;    ESC [ = n h    Set the Screen Mode
  4695. ansi_sm:                ; Set the current Screen Mode
  4696.     mov    al,VC_ANSI_BUF        ; Get the Selected mode and check for
  4697.     cmp    al,7            ; WRAP update
  4698.      jnz    ansi_rm10        ; Normal Set mode
  4699.     or    VC_MODE,WRAP_BIT
  4700.     ret
  4701.  
  4702.  
  4703. ;    ESC [ = n l    Reset the Screen Mode
  4704. ansi_rm:                ; Reset the screen Mode
  4705.     mov    al,VC_ANSI_BUF        ; Get the Selected mode and check for
  4706.     cmp    al,7            ; WRAP update
  4707.      jnz    ansi_rm10        ; Normal Set mode
  4708.     and    VC_MODE,not WRAP_BIT
  4709.     ret
  4710. ansi_rm10:
  4711.     cmp    al,0FFh            ; If no parameter was specified then 
  4712.      jnz    ansi_rm20        ; the default mode of 0 is selected
  4713.     mov    al,0
  4714. ansi_rm20:
  4715. ;;    jmp    z_set_mode@        ; use VT52 driver
  4716.     ret                ; not supported
  4717.  
  4718.  
  4719. ;    ESC [ 6 n    Device Status Report
  4720. ansi_dsr:
  4721.     call    ansi_def1        ; Get the first Parameter
  4722.     cmp    al,6            ; Was it 6
  4723.     jnz    ansi_dsr_exit        ; If not 6 then exit
  4724.  
  4725.     add    dx,0101h        ; Cursor address base 1 (not 0)
  4726.     mov    al,dl            ; Get the Column
  4727.     aam ! add ax,3030h        ; Convert to ASCII
  4728.     xchg    al,ah
  4729.     mov    ansi_cpr_col,ax
  4730.  
  4731.     mov    al,dh            ; Get the Row
  4732.     aam ! add ax,3030h        ; Convert to ASCII
  4733.     xchg    al,ah
  4734.     mov    ansi_cpr_row,ax
  4735.     mov    ansi_cpr_count,ansi_cpr_len    ; Force the CONIN routine to
  4736. ansi_dsr_exit:                ; return ANSI_CPR. 
  4737.     ret
  4738.  
  4739.  
  4740. ansi_def1:        ; return 1st parameter or 1 if none specified
  4741.     mov    al, VC_ANSI_BUF        ; no parameter specified?
  4742.     cmp    al, 0FFh        ; is it still the default?
  4743.      jne    ansi_def1_ret        ; no, number specified
  4744.     mov    al, 1            ; else return 1
  4745. ansi_def1_ret:
  4746.     ret
  4747.  
  4748.  
  4749.  
  4750. eject
  4751. PCTERM_DATA    dseg
  4752.  
  4753.  
  4754. ; XIOS entry intercept offsets - replaced with original values at INIT
  4755.  
  4756. xios_tbl    rw    0
  4757.         dw    IO_CONIN * 2        ; * 2 for word ptr
  4758. io_conin    dw    offset fl_io_conin    ; func 1 console input
  4759.         dw    IO_CONOUT * 2
  4760. io_conout    dw    offset fl_io_conout    ; func 2 console output
  4761.         dw    IO_LISTST * 2
  4762. io_listst    dw    offset fl_io_listst    ; func 3 list output
  4763.         dw    IO_LIST * 2
  4764. io_list        dw    offset fl_io_list    ; func 4 list output
  4765.         dw    IO_SWITCH * 2
  4766. io_switch    dw    offset fl_io_switch    ; func 7 console switch
  4767.         dw    IO_STATLINE * 2
  4768. io_statline    dw    offset fl_io_statline    ; func 8 status line update
  4769.         dw    PC_KBD * 2
  4770. pc_kbd        dw    offset fl_pc_kbd    ; func 32 keyboard switch
  4771.         dw    PC_SHIFTS * 2
  4772. pc_shifts    dw    offset fl_pc_shifts    ; func 33 shift status
  4773.         dw    IO_DEVIO * 2
  4774. io_devio    dw    offset fl_io_devio    ; func 39 block read/write
  4775.  
  4776. NUM_FUNCS    equ    ( offset $ - offset xios_tbl )/4
  4777.  
  4778. ; Global data area
  4779. flush_install    db    0            ; flush installed flag
  4780. intercept_install db    0
  4781.     
  4782.  
  4783. ;    This string is used by the ANSI Device Status Report function to
  4784. ;    return the current cursor location to the calling routine in the
  4785. ;    standard ANSI format.
  4786. ;
  4787. ansi_cpr_count    db    0
  4788. ansi_cpr    db    1Bh, '['
  4789. ansi_cpr_row    rw    1
  4790.         db    ';'
  4791. ansi_cpr_col    rw    1
  4792.         db    'R'
  4793. ansi_cpr_len    equ    offset $ - offset ansi_cpr
  4794.  
  4795.  
  4796.  
  4797. ; Console output handlers
  4798. ;------------------------
  4799. norm_table    dw    vc_out_cr@, vc_out_lf@, vc_out_bs@
  4800.         dw    vc_out_bel@, vc_out_esc, vc_out@
  4801.  
  4802. esc_table$    dw    z_up@,         z_down,       z_forward
  4803.         dw    z_back,         z_erase@,      z_home
  4804.         dw    z_rev_index,     z_erase_eos@,  z_erase_eol@
  4805.         dw    z_erase_bos@,     z_erase_line@, z_erase_bol@
  4806.         dw    z_insert_line@,     z_delete_line@,z_delete_char
  4807.         dw    z_set_cursor,     z_set_fore,   z_set_back
  4808.         dw    z_cursor_on,     z_cursor_off, z_save_cursor@
  4809.         dw    z_restore_cursor@,z_rev_on@,     z_rev_off
  4810.         dw    z_intense_on@,     z_blink_on@,   z_blink_off
  4811.         dw    z_intense_off,     z_wrap_on,    z_wrap_off
  4812.         dw    z_set_color@,     z_set_mono@,   z_video_mode
  4813.         dw    z_prog_pfk@,     z_sl_off@,    z_sl_mono@
  4814.         dw    z_sl_color@,     z_sl_both@,   z_clk_off@
  4815.         dw    z_clk_on@,     z_pfk_off@,   z_pfk_on@
  4816.         dw    z_back_door,     z_norm_attr,     z_ansi@
  4817.         dw    vc_out@
  4818.  
  4819. norm_scan    db    CR,LF,BS,BEL,ESC
  4820. NORM_COUNT    equ    offset $ - offset norm_scan
  4821.  
  4822. esc_scan$    db    'ABCDEH'
  4823.         db    'IJKdlo'
  4824.         db    'LMNYbc'
  4825.         db    'efjkpq'
  4826.         db    'rstuvw'
  4827.         db    'xya:01'
  4828.         db    '234567'
  4829.         db    '!z['
  4830. ESC_COUNT    equ    offset $ - offset esc_scan$
  4831.  
  4832.  
  4833. ; Ansi escape sequence jump table
  4834. ansi_tbl    db    'ABCDHfJKkLMmsu=?hln'
  4835.  
  4836. ansi_jmp    dw    ansi_cuu, ansi_cud, ansi_cuf, ansi_cub
  4837.         dw    ansi_cup, ansi_hvp, ansi_ed, ansi_el, ansi_el
  4838.         dw    z_insert_line@        ; (ansi_il) use VT52 routines
  4839.         dw    z_delete_line@        ; (ansi_dl)
  4840.         dw    ansi_sgr
  4841.         dw    z_save_cursor@        ; (ansi_scp) use VT52 routines
  4842.         dw    z_restore_cursor@    ; (ansi_rcp)
  4843.         dw    z_ansi@, z_ansi@, ansi_sm, ansi_rm
  4844.         dw    ansi_dsr
  4845.         dw    con_null
  4846.  
  4847.  
  4848. eject
  4849.  
  4850. ; KEYBOARD TABLES
  4851.  
  4852. live_tbl    db    SHFT_RIGHT,SHFT_LEFT,CTRL,ALT
  4853.         db    BREAK_SCAN,NUMLOCK,CAPSLOCK,INS_SCAN
  4854. live_tbl_len    equ    offset $ - offset live_tbl        
  4855.  
  4856. live_mask    db    SHFT_RIGHT_BIT,SHFT_LEFT_BIT,CTRL_BIT,ALT_BIT
  4857.         db    SCROLL_BIT,NUMLOCK_BIT,CAPSLOCK_BIT,INS_BIT
  4858.         
  4859. alt_intable    db    82,79,80,81,75
  4860.         db    76,77,71,72,73
  4861. alt_intable_len    equ    offset $ - offset alt_intable
  4862.  
  4863.  
  4864.  
  4865.  
  4866. key_table    db    -1,27,'1234567890-=',8
  4867.         db    9,'qwertyuiop[]',13
  4868.         db    -1,'asdfghjkl;',39,96
  4869.         db    -1,'\zxcvbnm,./',-1,'*'
  4870.         db    -1,' ',-1
  4871.         db    0,0,0,0,0, 0,0,0,0,0
  4872.         db    -1,-1,0,0,0,'-',0,-1,0,'+',0,0,0,0,0
  4873.  
  4874. key_scan    db    -1,1,2,3,4,5,6,7,8,9,10,11,12,13,14
  4875.         db    15,16,17,18,19,20,21,22,23,24,25,26,27,28
  4876.         db    29,30,31,32,33,34,35,36,37,38,39,40,41
  4877.         db    42,43,44,45,46,47,48,49,50,51,52,53,-1,55
  4878.         db    -1,57,-1
  4879.         db    59,60,61,62,63,64,65,66,67,68
  4880.         db    69,70,71,72,73,74,75,76,77,78,79,80,81,82,83
  4881.  
  4882. shift_table    db    -1,27,'!@#$%^&*()_+',8
  4883.         db    0,'QWERTYUIOP{}',13
  4884.         db    -1,'ASDFGHJKL:"~'
  4885.         db    -1,'|ZXCVBNM<>?',-1,'*'
  4886.         db    -1,' ',-1
  4887.         db    0,0,0,0,0, 0,0,0,0,0
  4888.         db    -1,-1,'789-456+1230.'
  4889.  
  4890. shift_scan    db    -1,1,2,3,4,5,6,7,8,9,10,11,12,13,14
  4891.         db    15,16,17,18,19,20,21,22,23,24,25,26,27,28
  4892.         db    -1,30,31,32,33,34,35,36,37,38,39,40,41
  4893.         db    -1,43,44,45,46,47,48,49,50,51,52,53,-1,55
  4894.         db    -1,57,-1
  4895.         db    84,85,86,87,88,89,90,91,92,93
  4896.         db    69,70,71,72,73,74,75,76,77,78,79,80,81,82,83
  4897.  
  4898. ctrl_table    db    -1,27,-1,0,-1,-1,-1,-1,-1,-1,-1,-1,31,-1,127
  4899.         db    9,11h,17h,5,12h,14h,19h,15h,9,15,16,27,29,10
  4900.         db    -1,1,19,4,6,7,8,10,11,12,-1,-1
  4901.         db    -1,-1,28,26,24,3,22,2,14,13,-1,-1,-1,-1,'*'
  4902.         db    -1,' ',-1
  4903.         db    0,0,0,0,0, 0,0,0,0,0
  4904.         db    -1,-1,0,-1,0,-1,0,-1,0,-1,0,-1,0,-1,-1
  4905.  
  4906. ctrl_scan    db    -1,1,2,3,4,5,6,7,8,9,10,11,12,13,14
  4907.         db    15,16,17,18,19,20,21,22,23,24,25,26,27,28
  4908.         db    -1,30,31,32,33,34,35,36,37,38,39,40,41
  4909.         db    -1,43,44,45,46,47,48,49,50,51,52,53,-1,55
  4910.         db    -1,57,-1
  4911.         db    94,95,96,97,98,99,100,101,102,103
  4912.         db    -1,-1,119,-1,132,-1,115,-1,116,-1,117,-1,118,-1,-1
  4913.  
  4914. alt_table    db    -1
  4915.         db    -1,120,121,122,123,124,125,126,127,128,129,130,131,-1
  4916.         db    -1,16,17,18,19,20,21,22,23,24,25,-1,-1,-1
  4917.         db    -1,30,31,32,33,34,35,36,37,38,-1,-1,-1
  4918.         db    -1,-1,44,45,46,47,48,49,50,-1,-1,-1,-1,-1
  4919.         db    -1,57,-1
  4920.         db    104,105,106,107,108,109,110,111,112,113
  4921.         db    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
  4922.  
  4923.  
  4924. ; Output escape sequences
  4925. ; -----------------------
  4926. cur_off_seq    db    3, ESC, '.0'        ; cursor off
  4927. cur_on_seq    db    3, ESC, '.3'        ; cursor on
  4928. clear_seq    db    1, 1Ah            ; erase screen
  4929. cpos_seq    db    4, ESC, '=  '        ; set cursor position
  4930. eos_seq        db    2, ESC, 'Y'        ; erase end of screen
  4931. eol_seq        db    2, ESC, 'T'        ; erase end of line
  4932. ins_seq        db    2, ESC, 'E'        ; insert blank line
  4933. inscpm_seq    db    12,ESC, '=7 '        ; cursor to 24th line
  4934.         db       ESC, 'R'        ; delete it
  4935.         db       ESC, '='        ; position cursor at line to
  4936. inscpm_cpos    dw       0            ; insert (patch at run time)
  4937.         db       ESC, 'E'        ; insert blank line
  4938. del_seq        db    2, ESC, 'R'        ; delete blank line
  4939. delcpm_seq    db    9, ESC, 'R'        ; delete blank line
  4940.         db       ESC, '=8 '        ; set cursor to last line
  4941.         db       VT, ESC, 'E'        ; up a line, and insert a blank
  4942. attrib_seq    db    3, ESC, 'G', 0FFh    ; set new attribute
  4943. lf_seq        db    5, ESC, '=8 ', LF    ; set cursor in last line, LF
  4944. lfcpm_seq    db    8, ESC, '=8 ', LF    ; set cursor to last line, LF
  4945.         db       VT, ESC, 'E'        ; up a line, and insert a blank
  4946. printer_on    db    2, ESC, '`'        ; transparent print mode on
  4947. printer_off    db    2, ESC, 'a'        ; transparent print mode off
  4948.                         ; ** note- the 'a' is tested
  4949.                         ; in fl_list routine **
  4950.  
  4951. ; PHYSICAL CONSOLE STRUCTURES
  4952. ; ---------------------------
  4953. pc_table    dw    pc_0,pc_1,pc_2,pc_3        ; pointers to 9
  4954.         dw    pc_4,pc_5,pc_6,pc_7        ; tables
  4955.         dw    pc_8
  4956.  
  4957. pc_0        db    1        ; physical console number
  4958.         dw    -1        ; physical serial cursor (invalid)
  4959.         db    -1        ; physical attribute
  4960.         db    0        ; busy flag
  4961.         rb    10        ; temporary string buffer
  4962.         rb    8        ; set cursor position (8 byte ANSI ?)
  4963.         db    0        ; keyboard state flag
  4964.         db    0        ; keyboard state flag 1
  4965.         db    0        ; keyboard state flag 3
  4966.         db    0        ; ALT numpad input char
  4967.         rb    4        ; set attribute string
  4968.         db    0        ; top screen VC number
  4969.         rw    1        ; nat ascii table
  4970.         rw    1        ; nat shift table
  4971.         rw    1        ; nat ctrl table
  4972.         rw    1        ; nat dead keys table
  4973.         dw    0ffffh        ; last dead key
  4974.         db    0        ; dead key buffer
  4975.         db    0        ; dead key scan code    
  4976.         db    0        ; US/national flag
  4977.         db    0        ; national language
  4978.         db    0        ; 7/8 etc
  4979.         db    0        ; mode 0 through 5
  4980.         db    false        ; disable 7 -> 8
  4981.         db    0        ; keyboard type
  4982.         db    0        ; raw scan
  4983.         db    0        ; translated scan
  4984.         db    0        ; shift lock
  4985.         db    0        ; enhanced shiftlock
  4986.         db    0        ; last char to printer
  4987.                 
  4988. pc_1        db    2        ; physical console number
  4989.         dw    -1        ; physical serial cursor (invalid)
  4990.         db    -1        ; physical attribute
  4991.         db    0        ; busy flag
  4992.         rb    10        ; temporary string buffer
  4993.         rb    8        ; set cursor position (8 byte ANSI ?)
  4994.         db    0        ; keyboard state flag
  4995.         db    0        ; keyboard state flag 1
  4996.         db    0        ; keyboard state flag 3
  4997.         db    0        ; ALT numpad input char
  4998.         rb    4        ; set attribute string
  4999.         db    0        ; top screen VC number
  5000.         rw    1        ; nat ascii table
  5001.         rw    1        ; nat shift table
  5002.         rw    1        ; nat ctrl table
  5003.         rw    1        ; nat dead keys table
  5004.         dw    0ffffh        ; last dead key
  5005.         db    0        ; dead key buffer
  5006.         db    0        ; dead key scan code    
  5007.         db    0        ; US/national flag
  5008.         db    0        ; national language
  5009.         db    0        ; 7/8 etc
  5010.         db    0        ; mode 0 through 5
  5011.         db    false        ; disable 7 -> 8
  5012.         db    0        ; keyboard type
  5013.         db    0        ; raw scan
  5014.         db    0        ; translated scan
  5015.         db    0        ; shift lock
  5016.         db    0        ; enhanced shiftlock
  5017.         db    0        ; last char to printer
  5018.  
  5019. pc_2        db    3        ; physical console number
  5020.         dw    -1        ; physical serial cursor (invalid)
  5021.         db    -1        ; physical attribute
  5022.         db    0        ; busy flag
  5023.         rb    10        ; temporary string buffer
  5024.         rb    8        ; set cursor position (8 byte ANSI ?)
  5025.         db    0        ; keyboard state flag
  5026.         db    0        ; keyboard state flag 1
  5027.         db    0        ; keyboard state flag 3
  5028.         db    0        ; ALT numpad input char
  5029.         rb    4        ; set attribute string
  5030.         db    0        ; top screen VC number
  5031.         rw    1        ; nat ascii table
  5032.         rw    1        ; nat shift table
  5033.         rw    1        ; nat ctrl table
  5034.         rw    1        ; nat dead keys table
  5035.         dw    0ffffh        ; last dead key
  5036.         db    0        ; dead key buffer
  5037.         db    0        ; dead key scan code    
  5038.         db    0        ; US/national flag
  5039.         db    0        ; national language
  5040.         db    0        ; 7/8 etc
  5041.         db    0        ; mode 0 through 5
  5042.         db    false        ; disable 7 -> 8
  5043.         db    0        ; keyboard type
  5044.         db    0        ; raw scan
  5045.         db    0        ; translated scan
  5046.         db    0        ; shift lock
  5047.         db    0        ; enhanced shiftlock
  5048.         db    0        ; last char to printer
  5049.  
  5050. pc_3        db    4        ; physical console number
  5051.         dw    -1        ; physical serial cursor (invalid)
  5052.         db    -1        ; physical attribute
  5053.         db    0        ; busy flag
  5054.         rb    10        ; temporary string buffer
  5055.         rb    8        ; set cursor position (8 byte ANSI ?)
  5056.         db    0        ; keyboard state flag
  5057.         db    0        ; keyboard state flag 1
  5058.         db    0        ; keyboard state flag 3
  5059.         db    0        ; ALT numpad input char
  5060.         rb    4        ; set attribute string
  5061.         db    0        ; top screen VC number
  5062.         rw    1        ; nat ascii table
  5063.         rw    1        ; nat shift table
  5064.         rw    1        ; nat ctrl table
  5065.         rw    1        ; nat dead keys table
  5066.         dw    0ffffh        ; last dead key
  5067.         db    0        ; dead key buffer
  5068.         db    0        ; dead key scan code    
  5069.         db    0        ; US/national flag
  5070.         db    0        ; national language
  5071.         db    0        ; 7/8 etc
  5072.         db    0        ; mode 0 through 5
  5073.         db    false        ; disable 7 -> 8
  5074.         db    0        ; keyboard type
  5075.         db    0        ; raw scan
  5076.         db    0        ; translated scan
  5077.         db    0        ; shift lock
  5078.         db    0        ; enhanced shiftlock
  5079.         db    0        ; last char to printer
  5080.  
  5081. pc_4        db    5        ; physical console number
  5082.         dw    -1        ; physical serial cursor (invalid)
  5083.         db    -1        ; physical attribute
  5084.         db    0        ; busy flag
  5085.         rb    10        ; temporary string buffer
  5086.         rb    8        ; set cursor position (8 byte ANSI ?)
  5087.         db    0        ; keyboard state flag
  5088.         db    0        ; keyboard state flag 1
  5089.         db    0        ; keyboard state flag 3
  5090.         db    0        ; ALT numpad input char
  5091.         rb    4        ; set attribute string
  5092.         db    0        ; top screen VC number
  5093.         rw    1        ; nat ascii table
  5094.         rw    1        ; nat shift table
  5095.         rw    1        ; nat ctrl table
  5096.         rw    1        ; nat dead keys table
  5097.         dw    0ffffh        ; last dead key
  5098.         db    0        ; dead key buffer
  5099.         db    0        ; dead key scan code    
  5100.         db    0        ; US/national flag
  5101.         db    0        ; national language
  5102.         db    0        ; 7/8 etc
  5103.         db    0        ; mode 0 through 5
  5104.         db    false        ; disable 7 -> 8
  5105.         db    0        ; keyboard type
  5106.         db    0        ; raw scan
  5107.         db    0        ; translated scan
  5108.         db    0        ; shift lock
  5109.         db    0        ; enhanced shiftlock
  5110.         db    0        ; last char to printer
  5111.  
  5112. pc_5        db    6        ; physical console number
  5113.         dw    -1        ; physical serial cursor (invalid)
  5114.         db    -1        ; physical attribute
  5115.         db    0        ; busy flag
  5116.         rb    10        ; temporary string buffer
  5117.         rb    8        ; set cursor position (8 byte ANSI ?)
  5118.         db    0        ; keyboard state flag
  5119.         db    0        ; keyboard state flag 1
  5120.         db    0        ; keyboard state flag 3
  5121.         db    0        ; ALT numpad input char
  5122.         rb    4        ; set attribute string
  5123.         db    0        ; top screen VC number
  5124.         rw    1        ; nat ascii table
  5125.         rw    1        ; nat shift table
  5126.         rw    1        ; nat ctrl table
  5127.         rw    1        ; nat dead keys table
  5128.         dw    0ffffh        ; last dead key
  5129.         db    0        ; dead key buffer
  5130.         db    0        ; dead key scan code    
  5131.         db    0        ; US/national flag
  5132.         db    0        ; national language
  5133.         db    0        ; 7/8 etc
  5134.         db    0        ; mode 0 through 5
  5135.         db    false        ; disable 7 -> 8
  5136.         db    0        ; keyboard type
  5137.         db    0        ; raw scan
  5138.         db    0        ; translated scan
  5139.         db    0        ; shift lock
  5140.         db    0        ; enhanced shiftlock
  5141.         db    0        ; last char to printer
  5142.  
  5143. pc_6        db    7        ; physical console number
  5144.         dw    -1        ; physical serial cursor (invalid)
  5145.         db    -1        ; physical attribute
  5146.         db    0        ; busy flag
  5147.         rb    10        ; temporary string buffer
  5148.         rb    8        ; set cursor position (8 byte ANSI ?)
  5149.         db    0        ; keyboard state flag
  5150.         db    0        ; keyboard state flag 1
  5151.         db    0        ; keyboard state flag 3
  5152.         db    0        ; ALT numpad input char
  5153.         rb    4        ; set attribute string
  5154.         db    0        ; top screen VC number
  5155.         rw    1        ; nat ascii table
  5156.         rw    1        ; nat shift table
  5157.         rw    1        ; nat ctrl table
  5158.         rw    1        ; nat dead keys table
  5159.         dw    0ffffh        ; last dead key
  5160.         db    0        ; dead key buffer
  5161.         db    0        ; dead key scan code    
  5162.         db    0        ; US/national flag
  5163.         db    0        ; national language
  5164.         db    0        ; 7/8 etc
  5165.         db    0        ; mode 0 through 5
  5166.         db    false        ; disable 7 -> 8
  5167.         db    0        ; keyboard type
  5168.         db    0        ; raw scan
  5169.         db    0        ; translated scan
  5170.         db    0        ; shift lock
  5171.         db    0        ; enhanced shiftlock
  5172.         db    0        ; last char to printer
  5173.  
  5174. pc_7        db    8        ; physical console number
  5175.         dw    -1        ; physical serial cursor (invalid)
  5176.         db    -1        ; physical attribute
  5177.         db    0        ; busy flag
  5178.         rb    10        ; temporary string buffer
  5179.         rb    8        ; set cursor position (8 byte ANSI ?)
  5180.         db    0        ; keyboard state flag
  5181.         db    0        ; keyboard state flag 1
  5182.         db    0        ; keyboard state flag 3
  5183.         db    0        ; ALT numpad input char
  5184.         rb    4        ; set attribute string
  5185.         db    0        ; top screen VC number
  5186.         rw    1        ; nat ascii table
  5187.         rw    1        ; nat shift table
  5188.         rw    1        ; nat ctrl table
  5189.         rw    1        ; nat dead keys table
  5190.         dw    0ffffh        ; last dead key
  5191.         db    0        ; dead key buffer
  5192.         db    0        ; dead key scan code    
  5193.         db    0        ; US/national flag
  5194.         db    0        ; national language
  5195.         db    0        ; 7/8 etc
  5196.         db    0        ; mode 0 through 5
  5197.         db    false        ; disable 7 -> 8
  5198.         db    0        ; keyboard type
  5199.         db    0        ; raw scan
  5200.         db    0        ; translated scan
  5201.         db    0        ; shift lock
  5202.         db    0        ; enhanced shiftlock
  5203.         db    0        ; last char to printer
  5204.  
  5205. pc_8        db    9        ; physical console number
  5206.         dw    -1        ; physical serial cursor (invalid)
  5207.         db    -1        ; physical attribute
  5208.         db    0        ; busy flag
  5209.         rb    10        ; temporary string buffer
  5210.         rb    8        ; set cursor position (8 byte ANSI ?)
  5211.         db    0        ; keyboard state flag
  5212.         db    0        ; keyboard state flag 1
  5213.         db    0        ; keyboard state flag 3
  5214.         db    0        ; ALT numpad input char
  5215.         rb    4        ; set attribute string
  5216.         db    0        ; top screen VC number
  5217.         rw    1        ; nat ascii table
  5218.         rw    1        ; nat shift table
  5219.         rw    1        ; nat ctrl table
  5220.         rw    1        ; nat dead keys table
  5221.         dw    0ffffh        ; last dead key
  5222.         db    0        ; dead key buffer
  5223.         db    0        ; dead key scan code    
  5224.         db    0        ; US/national flag
  5225.         db    0        ; national language
  5226.         db    0        ; 7/8 etc
  5227.         db    0        ; mode 0 through 5
  5228.         db    false        ; disable 7 -> 8
  5229.         db    0        ; keyboard type
  5230.         db    0        ; raw scan
  5231.         db    0        ; translated scan
  5232.         db    0        ; shift lock
  5233.         db    0        ; enhanced shiftlock
  5234.         db    0        ; last char to printer
  5235.  
  5236.     
  5237. ; VIRTUAL CONSOLE STRUCTURES
  5238. ; ---------------------------
  5239. vc_table    dw    vc_4,vc_5,vc_6,vc_7        ; pointers to 18
  5240.         dw    vc_8,vc_9,vc_10,vc_11        ; tables
  5241.         dw    vc_12,vc_13,vc_14,vc_15
  5242.         dw    vc_16,vc_17,vc_18,vc_19
  5243.         dw    vc_20,vc_21
  5244.         
  5245. vc_4        dw    0                ; cursor row/col
  5246.         dw    CRT_ROWS_C
  5247.         dw    CRT_SEG                ; CRT segment base
  5248.         db    07h                ; default attribute
  5249.         db    INIT_MODE + UPDATE_BIT        ; initial VC_MODE
  5250.         db    CRT_COLS
  5251.         db    4                ; 4=VC_NUMBER
  5252.         dw    0,con_normal@
  5253.         db    CRT_ROWS_C            ; 24/25 lines
  5254.         dw    0B0Ch                ; cursor type
  5255.         db    0                ; vc_mx
  5256.         dw    0                ; VC_OFFSET
  5257.         db    7                ; ROS video mode
  5258.         dw    0000h                ; ansi options count
  5259.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5260.  
  5261.         db    0                ; virtual port 3B4h
  5262.         rb    0                ; virtual port 3B5h
  5263.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5264.         db    0,0,0,0,0,0,0,0
  5265.         db    0                ; virtual port 3BAh
  5266.         rd    3                ; page save area
  5267.         db    0                ; installed flag
  5268.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5269.         db    20h                ; blink attr. enable
  5270.         db    0                ; update request
  5271.         dw    1ffh                ; status line flag
  5272.         dw    0                ; ros cursor
  5273.         
  5274. vc_5        dw    0                ; cursor row/col
  5275.         dw    CRT_ROWS_C
  5276.         dw    CRT_SEG                ; CRT segment base
  5277.         db    07h                ; default attribute
  5278.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5279.         db    CRT_COLS
  5280.         db    5                ; 5=VC_NUMBER
  5281.         dw    0,con_normal@
  5282.         db    CRT_ROWS_C            ; 24/25 lines
  5283.         dw    0B0Ch                ; cursor type
  5284.         db    0                ; vc_mx
  5285.         dw    0                ; VC_OFFSET
  5286.         db    7                ; ROS video mode
  5287.         dw    0000h                ; ansi options count
  5288.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5289.  
  5290.         db    0                ; virtual port 3B4h
  5291.         rb    0                ; virtual port 3B5h
  5292.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5293.         db    0,0,0,0,0,0,0,0
  5294.         db    0                ; virtual port 3BAh
  5295.         rd    3                ; page save area
  5296.         db    0                ; installed flag
  5297.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5298.         db    20h                ; blink attr. enable
  5299.         db    0                ; update request
  5300.         dw    1ffh                ; status line flag
  5301.         dw    0                ; ros cursor
  5302.         
  5303. vc_6        dw    0                ; cursor row/col
  5304.         dw    CRT_ROWS_C
  5305.         dw    CRT_SEG                ; CRT segment base
  5306.         db    07h                ; default attribute
  5307.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5308.         db    CRT_COLS
  5309.         db    6                ; 6=VC_NUMBER
  5310.         dw    0,con_normal@
  5311.         db    CRT_ROWS_C            ; 24/25 lines
  5312.         dw    0B0Ch                ; cursor type
  5313.         db    0                ; vc_mx
  5314.         dw    0                ; VC_OFFSET
  5315.         db    7                ; ROS video mode
  5316.         dw    0000h                ; ansi options count
  5317.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5318.  
  5319.         db    0                ; virtual port 3B4h
  5320.         rb    0                ; virtual port 3B5h
  5321.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5322.         db    0,0,0,0,0,0,0,0
  5323.         db    0                ; virtual port 3BAh
  5324.         rd    3                ; page save area
  5325.         db    0                ; installed flag
  5326.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5327.         db    20h                ; blink attr. enable
  5328.         db    0                ; update request
  5329.         dw    1ffh                ; status line flag
  5330.         dw    0                ; ros cursor
  5331.  
  5332. vc_7        dw    0                ; cursor row/col
  5333.         dw    CRT_ROWS_C
  5334.         dw    CRT_SEG                ; CRT segment base
  5335.         db    07h                ; default attribute
  5336.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5337.         db    CRT_COLS
  5338.         db    7                ; 7=VC_NUMBER
  5339.         dw    0,con_normal@
  5340.         db    CRT_ROWS_C            ; 24/25 lines
  5341.         dw    0B0Ch                ; cursor type
  5342.         db    0                ; vc_mx
  5343.         dw    0                ; VC_OFFSET
  5344.         db    7                ; ROS video mode
  5345.         dw    0000h                ; ansi options count
  5346.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5347.  
  5348.         db    0                ; virtual port 3B4h
  5349.         rb    0                ; virtual port 3B5h
  5350.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5351.         db    0,0,0,0,0,0,0,0
  5352.         db    0                ; virtual port 3BAh
  5353.         rd    3                ; page save area
  5354.         db    0                ; installed flag
  5355.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5356.         db    20h                ; blink attr. enable
  5357.         db    0                ; update request
  5358.         dw    1ffh                ; status line flag
  5359.         dw    0                ; ros cursor
  5360.  
  5361. vc_8        dw    0                ; cursor row/col
  5362.         dw    CRT_ROWS_C
  5363.         dw    CRT_SEG                ; CRT segment base
  5364.         db    07h                ; default attribute
  5365.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5366.         db    CRT_COLS
  5367.         db    8                ; 8=VC_NUMBER
  5368.         dw    0,con_normal@
  5369.         db    CRT_ROWS_C            ; 24/25 lines
  5370.         dw    0B0Ch                ; cursor type
  5371.         db    0                ; vc_mx
  5372.         dw    0                ; VC_OFFSET
  5373.         db    7                ; ROS video mode
  5374.         dw    0000h                ; ansi options count
  5375.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5376.  
  5377.         db    0                ; virtual port 3B4h
  5378.         rb    0                ; virtual port 3B5h
  5379.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5380.         db    0,0,0,0,0,0,0,0
  5381.         db    0                ; virtual port 3BAh
  5382.         rd    3                ; page save area
  5383.         db    0                ; installed flag
  5384.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5385.         db    20h                ; blink attr. enable
  5386.         db    0                ; update request
  5387.         dw    1ffh                ; status line flag
  5388.         dw    0                ; ros cursor
  5389.  
  5390. vc_9        dw    0                ; cursor row/col
  5391.         dw    CRT_ROWS_C
  5392.         dw    CRT_SEG                ; CRT segment base
  5393.         db    07h                ; default attribute
  5394.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5395.         db    CRT_COLS
  5396.         db    9                ; 9=VC_NUMBER
  5397.         dw    0,con_normal@
  5398.         db    CRT_ROWS_C            ; 24/25 lines
  5399.         dw    0B0Ch                ; cursor type
  5400.         db    0                ; vc_mx
  5401.         dw    0                ; VC_OFFSET
  5402.         db    7                ; ROS video mode
  5403.         dw    0000h                ; ansi options count
  5404.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5405.  
  5406.         db    0                ; virtual port 3B4h
  5407.         rb    0                ; virtual port 3B5h
  5408.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5409.         db    0,0,0,0,0,0,0,0
  5410.         db    0                ; virtual port 3BAh
  5411.         rd    3                ; page save area
  5412.         db    0                ; installed flag
  5413.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5414.         db    20h                ; blink attr. enable
  5415.         db    0                ; update request
  5416.         dw    1ffh                ; status line flag
  5417.         dw    0                ; ros cursor
  5418.  
  5419. vc_10        dw    0                ; cursor row/col
  5420.         dw    CRT_ROWS_C
  5421.         dw    CRT_SEG                ; CRT segment base
  5422.         db    07h                ; default attribute
  5423.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5424.         db    CRT_COLS
  5425.         db    10                ; 10=VC_NUMBER
  5426.         dw    0,con_normal@
  5427.         db    CRT_ROWS_C            ; 24/25 lines
  5428.         dw    0B0Ch                ; cursor type
  5429.         db    0                ; vc_mx
  5430.         dw    0                ; VC_OFFSET
  5431.         db    7                ; ROS video mode
  5432.         dw    0000h                ; ansi options count
  5433.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5434.  
  5435.         db    0                ; virtual port 3B4h
  5436.         rb    0                ; virtual port 3B5h
  5437.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5438.         db    0,0,0,0,0,0,0,0
  5439.         db    0                ; virtual port 3BAh
  5440.         rd    3                ; page save area
  5441.         db    0                ; installed flag
  5442.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5443.         db    20h                ; blink attr. enable
  5444.         db    0                ; update request
  5445.         dw    1ffh                ; status line flag
  5446.         dw    0                ; ros cursor
  5447.  
  5448. vc_11        dw    0                ; cursor row/col
  5449.         dw    CRT_ROWS_C
  5450.         dw    CRT_SEG                ; CRT segment base
  5451.         db    07h                ; default attribute
  5452.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5453.         db    CRT_COLS
  5454.         db    11                ; 11=VC_NUMBER
  5455.         dw    0,con_normal@
  5456.         db    CRT_ROWS_C            ; 24/25 lines
  5457.         dw    0B0Ch                ; cursor type
  5458.         db    0                ; vc_mx
  5459.         dw    0                ; VC_OFFSET
  5460.         db    7                ; ROS video mode
  5461.         dw    0000h                ; ansi options count
  5462.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5463.  
  5464.         db    0                ; virtual port 3B4h
  5465.         rb    0                ; virtual port 3B5h
  5466.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5467.         db    0,0,0,0,0,0,0,0
  5468.         db    0                ; virtual port 3BAh
  5469.         rd    3                ; page save area
  5470.         db    0                ; installed flag
  5471.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5472.         db    20h                ; blink attr. enable
  5473.         db    0                ; update request
  5474.         dw    1ffh                ; status line flag
  5475.         dw    0                ; ros cursor
  5476.  
  5477. vc_12        dw    0                ; cursor row/col
  5478.         dw    CRT_ROWS_C
  5479.         dw    CRT_SEG                ; CRT segment base
  5480.         db    07h                ; default attribute
  5481.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5482.         db    CRT_COLS
  5483.         db    12                ; 12=VC_NUMBER
  5484.         dw    0,con_normal@
  5485.         db    CRT_ROWS_C            ; 24/25 lines
  5486.         dw    0B0Ch                ; cursor type
  5487.         db    0                ; vc_mx
  5488.         dw    0                ; VC_OFFSET
  5489.         db    7                ; ROS video mode
  5490.         dw    0000h                ; ansi options count
  5491.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5492.  
  5493.         db    0                ; virtual port 3B4h
  5494.         rb    0                ; virtual port 3B5h
  5495.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5496.         db    0,0,0,0,0,0,0,0
  5497.         db    0                ; virtual port 3BAh
  5498.         rd    3                ; page save area
  5499.         db    0                ; installed flag
  5500.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5501.         db    20h                ; blink attr. enable
  5502.         db    0                ; update request
  5503.         dw    1ffh                ; status line flag
  5504.         dw    0                ; ros cursor
  5505.  
  5506. vc_13        dw    0                ; cursor row/col
  5507.         dw    CRT_ROWS_C
  5508.         dw    CRT_SEG                ; CRT segment base
  5509.         db    07h                ; default attribute
  5510.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5511.         db    CRT_COLS
  5512.         db    13                ; 13=VC_NUMBER
  5513.         dw    0,con_normal@
  5514.         db    CRT_ROWS_C            ; 24/25 lines
  5515.         dw    0B0Ch                ; cursor type
  5516.         db    0                ; vc_mx
  5517.         dw    0                ; VC_OFFSET
  5518.         db    7                ; ROS video mode
  5519.         dw    0000h                ; ansi options count
  5520.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5521.  
  5522.         db    0                ; virtual port 3B4h
  5523.         rb    0                ; virtual port 3B5h
  5524.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5525.         db    0,0,0,0,0,0,0,0
  5526.         db    0                ; virtual port 3BAh
  5527.         rd    3                ; page save area
  5528.         db    0                ; installed flag
  5529.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5530.         db    20h                ; blink attr. enable
  5531.         db    0                ; update request
  5532.         dw    1ffh                ; status line flag
  5533.         dw    0                ; ros cursor
  5534.  
  5535. vc_14        dw    0                ; cursor row/col
  5536.         dw    CRT_ROWS_C
  5537.         dw    CRT_SEG                ; CRT segment base
  5538.         db    07h                ; default attribute
  5539.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5540.         db    CRT_COLS
  5541.         db    14                ; 14=VC_NUMBER
  5542.         dw    0,con_normal@
  5543.         db    CRT_ROWS_C            ; 24/25 lines
  5544.         dw    0B0Ch                ; cursor type
  5545.         db    0                ; vc_mx
  5546.         dw    0                ; VC_OFFSET
  5547.         db    7                ; ROS video mode
  5548.         dw    0000h                ; ansi options count
  5549.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5550.  
  5551.         db    0                ; virtual port 3B4h
  5552.         rb    0                ; virtual port 3B5h
  5553.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5554.         db    0,0,0,0,0,0,0,0
  5555.         db    0                ; virtual port 3BAh
  5556.         rd    3                ; page save area
  5557.         db    0                ; installed flag
  5558.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5559.         db    20h                ; blink attr. enable
  5560.         db    0                ; update request
  5561.         dw    1ffh                ; status line flag
  5562.         dw    0                ; ros cursor
  5563.  
  5564. vc_15        dw    0                ; cursor row/col
  5565.         dw    CRT_ROWS_C
  5566.         dw    CRT_SEG                ; CRT segment base
  5567.         db    07h                ; default attribute
  5568.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5569.         db    CRT_COLS
  5570.         db    15                ; 15=VC_NUMBER
  5571.         dw    0,con_normal@
  5572.         db    CRT_ROWS_C            ; 24/25 lines
  5573.         dw    0B0Ch                ; cursor type
  5574.         db    0                ; vc_mx
  5575.         dw    0                ; VC_OFFSET
  5576.         db    7                ; ROS video mode
  5577.         dw    0000h                ; ansi options count
  5578.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5579.  
  5580.         db    0                ; virtual port 3B4h
  5581.         rb    0                ; virtual port 3B5h
  5582.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5583.         db    0,0,0,0,0,0,0,0
  5584.         db    0                ; virtual port 3BAh
  5585.         rd    3                ; page save area
  5586.         db    0                ; installed flag
  5587.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5588.         db    20h                ; blink attr. enable
  5589.         db    0                ; update request
  5590.         dw    1ffh                ; status line flag
  5591.         dw    0                ; ros cursor
  5592.  
  5593. vc_16        dw    0                ; cursor row/col
  5594.         dw    CRT_ROWS_C
  5595.         dw    CRT_SEG                ; CRT segment base
  5596.         db    07h                ; default attribute
  5597.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5598.         db    CRT_COLS
  5599.         db    16                ; 16=VC_NUMBER
  5600.         dw    0,con_normal@
  5601.         db    CRT_ROWS_C            ; 24/25 lines
  5602.         dw    0B0Ch                ; cursor type
  5603.         db    0                ; vc_mx
  5604.         dw    0                ; VC_OFFSET
  5605.         db    7                ; ROS video mode
  5606.         dw    0000h                ; ansi options count
  5607.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5608.  
  5609.         db    0                ; virtual port 3B4h
  5610.         rb    0                ; virtual port 3B5h
  5611.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5612.         db    0,0,0,0,0,0,0,0
  5613.         db    0                ; virtual port 3BAh
  5614.         rd    3                ; page save area
  5615.         db    0                ; installed flag
  5616.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5617.         db    20h                ; blink attr. enable
  5618.         db    0                ; update request
  5619.         dw    1ffh                ; status line flag
  5620.         dw    0                ; ros cursor
  5621.  
  5622. vc_17        dw    0                ; cursor row/col
  5623.         dw    CRT_ROWS_C
  5624.         dw    CRT_SEG                ; CRT segment base
  5625.         db    07h                ; default attribute
  5626.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5627.         db    CRT_COLS
  5628.         db    17                ; 17=VC_NUMBER
  5629.         dw    0,con_normal@
  5630.         db    CRT_ROWS_C            ; 24/25 lines
  5631.         dw    0B0Ch                ; cursor type
  5632.         db    0                ; vc_mx
  5633.         dw    0                ; VC_OFFSET
  5634.         db    7                ; ROS video mode
  5635.         dw    0000h                ; ansi options count
  5636.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5637.  
  5638.         db    0                ; virtual port 3B4h
  5639.         rb    0                ; virtual port 3B5h
  5640.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5641.         db    0,0,0,0,0,0,0,0
  5642.         db    0                ; virtual port 3BAh
  5643.         rd    3                ; page save area
  5644.         db    0                ; installed flag
  5645.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5646.         db    20h                ; blink attr. enable
  5647.         db    0                ; update request
  5648.         dw    1ffh                ; status line flag
  5649.         dw    0                ; ros cursor
  5650.  
  5651. vc_18        dw    0                ; cursor row/col
  5652.         dw    CRT_ROWS_C
  5653.         dw    CRT_SEG                ; CRT segment base
  5654.         db    07h                ; default attribute
  5655.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5656.         db    CRT_COLS
  5657.         db    18                ; 18=VC_NUMBER
  5658.         dw    0,con_normal@
  5659.         db    CRT_ROWS_C            ; 24/25 lines
  5660.         dw    0B0Ch                ; cursor type
  5661.         db    0                ; vc_mx
  5662.         dw    0                ; VC_OFFSET
  5663.         db    7                ; ROS video mode
  5664.         dw    0000h                ; ansi options count
  5665.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5666.  
  5667.         db    0                ; virtual port 3B4h
  5668.         rb    0                ; virtual port 3B5h
  5669.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5670.         db    0,0,0,0,0,0,0,0
  5671.         db    0                ; virtual port 3BAh
  5672.         rd    3                ; page save area
  5673.         db    0                ; installed flag
  5674.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5675.         db    20h                ; blink attr. enable
  5676.         db    0                ; update request
  5677.         dw    1ffh                ; status line flag
  5678.         dw    0                ; ros cursor
  5679.  
  5680. vc_19        dw    0                ; cursor row/col
  5681.         dw    CRT_ROWS_C
  5682.         dw    CRT_SEG                ; CRT segment base
  5683.         db    07h                ; default attribute
  5684.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5685.         db    CRT_COLS
  5686.         db    19                ; 19=VC_NUMBER
  5687.         dw    0,con_normal@
  5688.         db    CRT_ROWS_C            ; 24/25 lines
  5689.         dw    0B0Ch                ; cursor type
  5690.         db    0                ; vc_mx
  5691.         dw    0                ; VC_OFFSET
  5692.         db    7                ; ROS video mode
  5693.         dw    0000h                ; ansi options count
  5694.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5695.  
  5696.         db    0                ; virtual port 3B4h
  5697.         rb    0                ; virtual port 3B5h
  5698.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5699.         db    0,0,0,0,0,0,0,0
  5700.         db    0                ; virtual port 3BAh
  5701.         rd    3                ; page save area
  5702.         db    0                ; installed flag
  5703.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5704.         db    20h                ; blink attr. enable
  5705.         db    0                ; update request
  5706.         dw    1ffh                ; status line flag
  5707.         dw    0                ; ros cursor
  5708.  
  5709. vc_20        dw    0                ; cursor row/col
  5710.         dw    CRT_ROWS_C
  5711.         dw    CRT_SEG                ; CRT segment base
  5712.         db    07h                ; default attribute
  5713.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5714.         db    CRT_COLS
  5715.         db    20                ; 20=VC_NUMBER
  5716.         dw    0,con_normal@
  5717.         db    CRT_ROWS_C            ; 24/25 lines
  5718.         dw    0B0Ch                ; cursor type
  5719.         db    0                ; vc_mx
  5720.         dw    0                ; VC_OFFSET
  5721.         db    7                ; ROS video mode
  5722.         dw    0000h                ; ansi options count
  5723.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5724.  
  5725.         db    0                ; virtual port 3B4h
  5726.         rb    0                ; virtual port 3B5h
  5727.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5728.         db    0,0,0,0,0,0,0,0
  5729.         db    0                ; virtual port 3BAh
  5730.         rd    3                ; page save area
  5731.         db    0                ; installed flag
  5732.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5733.         db    20h                ; blink attr. enable
  5734.         db    0                ; update request
  5735.         dw    1ffh                ; status line flag
  5736.         dw    0                ; ros cursor
  5737.  
  5738. vc_21        dw    0                ; cursor row/col
  5739.         dw    CRT_ROWS_C
  5740.         dw    CRT_SEG                ; CRT segment base
  5741.         db    07h                ; default attribute
  5742.         db    INIT_MODE+UPDATE_BIT        ; initial VC_MODE
  5743.         db    CRT_COLS
  5744.         db    21                ; 21=VC_NUMBER
  5745.         dw    0,con_normal@
  5746.         db    CRT_ROWS_C            ; 24/25 lines
  5747.         dw    0B0Ch                ; cursor type
  5748.         db    0                ; vc_mx
  5749.         dw    0                ; VC_OFFSET
  5750.         db    7                ; ROS video mode
  5751.         dw    0000h                ; ansi options count
  5752.         rb    VC_ANSI_SIZE            ; ansi input buffer
  5753.  
  5754.         db    0                ; virtual port 3B4h
  5755.         rb    0                ; virtual port 3B5h
  5756.         db    61h,80,52h,0fh,25,6,25,25,2,0dh,0bh,0ch
  5757.         db    0,0,0,0,0,0,0,0
  5758.         db    0                ; virtual port 3BAh
  5759.         rd    3                ; page save area
  5760.         db    0                ; installed flag
  5761.         dw    su_pfk_tbl$,0,0FF00h        ; PFK info
  5762.         db    20h                ; blink attr. enable
  5763.         db    0                ; update request
  5764.         dw    1ffh                ; status line flag
  5765.         dw    0                ; ros cursor
  5766.         
  5767. ; save area for memory allocation blocks
  5768. mp_entry_ptr        dw    offset mp_table_entries ; current pointer
  5769. mp_table_entries    rd    28        ; 9 phys + 18 virtual console
  5770.                         ; 4k block entries, rounded up
  5771.                         ; to 16k blocks
  5772. flushstr    db    'Flush'            ; Flush RSP name
  5773. PINstr        db    'PIN'            ; pin rsp name
  5774.  
  5775. active_vc$    db    0            ; current active virtual cons
  5776. active_top    db    0            ; current top screen
  5777. pc_kbd_save$    rb    39            ; ROS data area keyboard data
  5778.                         ; all terminals use same dummy 
  5779.                         ; area.
  5780.  
  5781. save_mode    db    3            ; save crt mode on dispatch
  5782. save_cols    db    80            ; copy the ROS data here
  5783. save_cursor    dw    0            ; (and cols, and cursor)
  5784. save_6845    dw    0            ; (and crt address)
  5785. save_sl_flags    dw    0            ; status line flag save area
  5786.  
  5787. bad_mode_msg    db    0dh, 0ah
  5788.  db 'Concurrent Error:  This program can not run on a non-graphics console.'
  5789.  
  5790. BAD_MODE_MSG_LEN    equ    offset $ - offset bad_mode_msg
  5791.  
  5792. end
  5793.  
  5794. ; END OF PCTERM.A86
  5795.