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 / PCVIDEO.A86 < prev    next >
Encoding:
Text File  |  1989-01-26  |  31.5 KB  |  1,265 lines

  1. ; PCVIDEO.A86
  2. title 'PCDOS Video Support'
  3. pagesize 60+10
  4. ;********************************************************
  5. ;*                            *
  6. ;*        PC MODE VIDEO SUPPORT            *
  7. ;*        CDOS 6.0 XIOS                *
  8. ;*        DRI OS ENGR, JMB, GMS, JW        *
  9. ;*                            *
  10. ;********************************************************
  11. ; Mods:
  12. ; 6.x
  13. ; 18 Nov 88 -- also suspend 43 line modes            IJ
  14. ;  9 Nov 88 -- force suspend on when in graphics modes        IJ 
  15. ;  3 Nov 88 -- push & pop VID_CX and VID_DX in pc_v_erase_loop    ACH
  16. ;  5 Oct 88 -- enable ints during int 10 handler        IJ
  17. ; 21 Sep 88 -- int 10 subf 13 takes better notice of DX value    IJ
  18. ; 18 AUG 88 -- ROS Palettes only updated if foreground        GMS
  19. ; 12 Jul 88 -- Ros cursor mode support                IJ
  20. ;  1 JUL 88 -- turn TEMPKEEP flag on while in int 10h functions    GMS
  21. ; 11 APR 88 -- added Sun River support                GMS
  22. ;  7 MAR 88 -- Don't change cursor type if background VC    GMS
  23. ;  4 FEB 88 -- VS_CUR_TYPE_HW updated in trans_cur_type        GMS
  24. ; 16 DEC 87 -- bug fix for string writes function 13h        GMS
  25. ;  7 DEC 87 -- int10_bx entries replaced with int10_entry    GMS
  26. ;  4 DEC 87 -- VS_SCREEN_MODE now uses ROS video mode values    GMS
  27. ;  4 DEC 87 -- removed pc_video_write_char            GMS
  28. ;  2 DEC 87 -- replaced ega$ with redefined video$        GMS
  29. ; 6.0
  30. ; 12 NOV 87 -- correct statline on/off after mode change    GMS
  31. ; 10 NOV 87 -- Int 10h cursor update calls tick_cursor@        GMS
  32. ;  7 NOV 87 -- fix EGA 43 lines on monochrome display        JW
  33. ;        -- fix 43 line CY state for ROS calls (V_I_GR)    JW
  34. ;  4 NOV 87 -- set blink toggle for ega mono            GMS
  35. ;  3 NOV 87 -- set pal reg subfunction 0bh checked if graphics     GMS
  36. ;  2 NOV 87 -- Int 10h set cursor type checks for cursor on/off    GMS
  37. ; 24 SEP 87 -- Int 10h now does stack swap onto UDA stack    GMS
  38. ; 21 AUG 87 -- Implemented Ega top bit on mode selects        GMS
  39. ; 17 JUL 87 -- small model XIOS conversion            JW
  40. ; 22 JUN 87 -- 43 line ega support                GMS
  41. ; 13 JUN 87 -- new video_int@ code for 6.0 int 10h emulation    JW
  42. ; 5.2
  43. ; 24 APR 87 -- return cursor type from VS_CUR_TYPE - function 3    GMS
  44. ; 13 APR 87 -- abort serial terminal process if making ROS call    GMS
  45. ;  2 MAR 87 -- colour pallettes saved for each virtual console    GMS
  46. ; 27 FEB 87 -- save EGA blink toggle in VS_            GMS
  47. ; 5.1
  48. ; 14 JAN 87 -- Set cursor update bit                GMS
  49. ; 21 NOV 86 -- Use current screen attribute for subfunction 14    GMS
  50. ; 26 JUN 86 -- elim. double spaceing in f. 10 -- WD 
  51. ;  3 JUN 86 -- save cursor posn in 40: for VP_PLNR.
  52. ; 16 APR 86 -- support VS_CUR_TYPE_HW (for ega)    
  53. ; 13 FEB 86 -- fix int 10h function 0Ah attribute bug
  54. ;  6 JAN 86 -- fix int 10h function 10h
  55. ;  7 NOV 85 -- add int 10h sub-functions 10h,11h,12h, and 13h for EGA
  56. ;  2 JUL 85 -- use ROS int 10h for palette color
  57. ; 12 JUN 85 -- update 4.1 ASM86 XIOS to RASM86
  58.  
  59. ; include COPYRITE.TXT
  60.  
  61. nolist
  62. include CDOS.EQU
  63. include XIOS.EQU
  64. include PCHW.EQU
  65. include ROSDATA.EQU
  66. include ASCII.EQU
  67. list
  68. ; These have been included:
  69. ; include CDOS.EQU
  70. ; include XIOS.EQU
  71. ; include PCHW.EQU
  72. ; include ROSDATA.EQU
  73. ; include ASCII.EQU
  74.  
  75. CGROUP    group    CODE
  76. DGROUP    group    DATA
  77.  
  78. public    video_int@                ; for INIT.A86
  79. public    poke_ros_cursor@
  80. public    update_vs_cursor_from_ros@
  81.  
  82.     cseg
  83. extrn          sysdat$:word            ; in HEADER.A86
  84. extrn     show_cursor@:near,  put_cursor@:near    ; in WINDOWS1.A86
  85. extrn         z_movsw@:near,    erase_pc@:near
  86. extrn       in_window@:near,      vc_out@:near
  87. extrn       vc_out_bs@:near,   vc_out_cr@:near
  88. extrn       vc_out_lf@:near,  vc_out_bel@:near
  89. extrn       ser_abort@:near,    gr_abort@:near
  90. extrn       set_screen@:near
  91. extrn    point_cursor@:near,    point_vs@:near    ; in WINDOWS2.A86
  92. extrn          get_mx@:near
  93. extrn       get_crt_c@:near, put_if_ours@:near    ; in WINDOWS3.A86
  94. extrn       put_crt_s@:near
  95. extrn trans_cur_type@:near
  96. extrn     int10_entry@:near            ; in ROSIF.A86
  97. extrn       int10_isr$:dword
  98. extrn     tick_cursor@:near            ; in ISRS.A86
  99. extrn switch_statline@:near            ; in STATLINE.A86
  100. if SR
  101. extrn     test_srterm@:near            ; in SRTERM.A86
  102. extrn        point_pc@:near
  103. endif
  104.  
  105.     dseg
  106. extrn    cloneflag$:byte
  107. extrn    video$: byte
  108. extrn     vc_map_seg$: word
  109. extrn     top_screen$: byte
  110. ;extrn  palette_word$: word
  111. extrn    graphic_bits$:byte            ; in WINDOWS3.A86
  112. eject
  113.  
  114.     cseg
  115.  
  116. v_i_ros:                ; pass on to ROS
  117. ;-------
  118.     jmpf    int10_isr$        ; 
  119.  
  120.  
  121. ;==========
  122. video_int@:
  123. ;==========
  124. ;    This function handles Int 10h calls from PC DOS applications.
  125. ;    It emulates some of the functions, mainly for performance and
  126. ;    in order to support text based windowing. Graphics can not be
  127. ;    windowed and therefore the ROS is used for all graphic mode
  128. ;    video I/O.
  129. ;    Switches onto UDA stack.
  130.     sti
  131.     cld
  132.     cmp    ah,13H            ; last function that we handle
  133.      ja    v_i_ros            ; function out of range, call ROS
  134.  
  135.     push     ds            ; save DS and DI on
  136.     push     di            ; users stack
  137.     mov    ds,sysdat$
  138.     
  139.     mov     di,rlr$            ; Get our PD
  140.     mov     ds,P_UDA[di]        ; DS = UDA segment
  141.     inc    ds:U_INSYS        ; Increment the INSYS flag but do not
  142.     cmp     ds:U_INSYS,1        ; swap the stack if INSYS is already
  143.     jne    noswtch            ; non zero.
  144.     mov    ds:U_STACK_SS,ss    ; 
  145.     mov    ds:U_STACK_SP,sp    ; save users SS and SP
  146.     mov di,ds ! mov ss,di        ; The stack starts at the end of
  147.     mov     sp,ds:U_USIZE        ; the standard UDA
  148.  
  149. noswtch:
  150.     push    ds            ; save UDA
  151.  
  152.     mov    ds,sysdat$
  153.     push     si 
  154.     push    bx            ; extra for temp store
  155.     push es
  156.     push    bp ! push bp
  157.     push    dx ! push cx ! push bx ! push ax
  158.     mov    bp,sp
  159.  
  160.     mov    di,rlr$            ; get calling process
  161.     or    P_FLAG[di],PF_TEMPKEEP  ; prevent aborting
  162.     mov    dl,P_CONS[di]        ; get its virtual console #
  163.     mov    VID_VCONS[bp],dl    ; set virtual console
  164.     cmp    dl,NUM_VIR_CONS        ; is it a serial terminal?
  165.      jb    v_i_1            ; main console
  166. if SR
  167.     call    test_srterm@        ; test if SUN RIVER main console
  168.     jnz    v_i_1            ; yes .. 
  169. endif
  170.     jmps    v_i_kill        ; dumb terminal - shouldn't issue INT 10h
  171. v_i_1:
  172.     call    point_vs@        ; get virtual console structure
  173.     call    get_mx@            ; get screen semaphore
  174.  
  175.     mov    al,VID_AH[bp]        ; get ROS sub-function
  176.     or    al,al            ; MODE change ?
  177.     jz    v_i_emu            ; yes lets emulate
  178.     cmp    al,16            ; set palette regs ega
  179.     jz    v_i_emu
  180.     cmp    al,15            ; get video mode
  181.     jz    v_i_emu
  182.     cmp    al,11            ; set palette reg
  183.     jz    v_i_emu
  184.     cmp    VS_SCREEN_MODE,04    ;
  185.     jb    not_gra2
  186.     cmp    VS_SCREEN_MODE,07    ; if graphics mode
  187.     jne    v_i_gr
  188. not_gra2:
  189.     test    VS_MODE1,LINE_43_MODE    ; or 43 line mode
  190.     jnz    v_i_gr            ; go direct to the ROS
  191. v_i_emu:
  192.     cbw                ; make it a word
  193.     mov    di,ax            ; DI = sub function #
  194.     shl    di,1            ; entry into word table
  195.     call    v_i_table[di]        ; invoke subfunction
  196.  
  197. v_i_exit:
  198.     mov    VS_MX,0            ; release semaphore
  199.     mov    di,rlr$
  200.     and    P_FLAG[di],not PF_TEMPKEEP
  201.  
  202.     pop    ax ! pop bx ! pop cx ! pop dx
  203.     pop    bp ! pop bp        ; restore all registers
  204.     pop    es 
  205.     pop    si            ; temp store
  206.     pop     si
  207.  
  208.     pop    ds            ; back to UDA segment
  209.     
  210.         dec     ds:U_INSYS        ; If U_INSYS is zero then restore
  211.     jnz    nstk            ; the user's stack
  212.  
  213.     mov    ss,ds:U_STACK_SS
  214.     mov    sp,ds:U_STACK_SP
  215. nstk:
  216.     pop    di            ; users DI
  217.     pop    ds            ; users DS
  218.  
  219.  
  220.     iret
  221.  
  222.  
  223.  
  224. v_i_kill:
  225.     mov    al,VID_AH[bp]        ; get ROS sub-function
  226.     cmp    al,15            ; is it get mode function
  227.     jne    v_i_killit        ; no .... abort process
  228.     mov    ax,5009h        ; else let's pretend we're monochrome
  229.     mov    VID_AX[bp],ax
  230.     jmp    v_i_exit
  231.  
  232. v_i_killit:
  233.     jmp    ser_abort@        ; can't make ROS calls on serial term.
  234.  
  235. v_i_gr:
  236.     xchg    bx,VID_TEMP[bp]        ; save VS ->
  237.     pop    ax ! pop bx ! pop cx ! pop dx
  238.     pop    bp ! pop bp        ; restore all registers
  239.     pop    es 
  240.  
  241.     call    int10_entry@        ; do the ROS function
  242.     mov    si,bx            ; save bx
  243.     pop    bx            ; get saved VS->
  244.     mov    VS_MX,0            ; release semaphore
  245.     mov    di,rlr$
  246.     and    P_FLAG[di],not PF_TEMPKEEP
  247.     mov    bx,si            ; restore bx
  248.     pop     si
  249.     pop    ds            ; back to UDA segment
  250.         dec     ds:U_INSYS        ; If U_INSYS is zero then restore
  251.     jnz    nstk1            ; the user's stack
  252.  
  253.     mov    ss,ds:U_STACK_SS
  254.     mov    sp,ds:U_STACK_SP
  255. nstk1:
  256.     pop    di            ; users DI
  257.     pop    ds            ; users DS
  258.  
  259.     iret
  260.  
  261. v_i_table    dw    v_i_smode        ; 0 set video mode
  262.         dw    v_i_cursortype        ; 1 set cursor type
  263.         dw    v_i_setcursor        ; 2 set cursor position
  264.         dw    v_i_getcursor        ; 3 get cursor position
  265.         dw    v_i_lpen        ; 4 read light pen
  266.         dw    v_i_spage        ; 5 select display page
  267.         dw    v_i_scroll_up        ; 6 scroll window up
  268.         dw    v_i_scroll_down        ; 7 scroll window down
  269.         dw    v_i_read        ; 8 get attr/char at cursor
  270.         dw    v_i_write_attr        ; 9 set attr/char at cursor
  271.         dw    v_i_write_char@        ; 10 set char (curr.attr) @ cur
  272.         dw    v_i_set_color        ; 11 pallette / border control
  273.         dw    v_i_ros            ; 12 graphics pix write
  274.         dw    v_i_ros            ; 13 graphics pix read
  275.         dw    v_i_write_tty        ; 14 write char stream as a tty
  276.         dw    v_i_gmode        ; 15 current video state
  277.         dw    v_i_set_pal_reg        ; 16 EGA set pallette registers
  278.         dw    v_i_char_gen        ; 17 EGA character generator
  279.         dw    v_i_alt_select        ; 18 EGA alternate select
  280.         dw    v_i_write_string    ; 19 EGA write string
  281.  
  282. v_i_smode:        ; 0 set video mode
  283. ;---------
  284. ;    Entry:    VID_AL = new video mode
  285. ;        (bit 7 = 1 if screen memory not to be
  286. ;         cleared on mode switch)
  287. ;
  288. ;    Modes:    0, 1:    40x25 16 color        (CGA, EGA, MCGA, VGA)
  289. ;        2, 3:    80x25 16 color        (CGA, EGA, MCGA, VGA)
  290. ;        4, 5:    320x200 4 color        (CGA, EGA, MCGA, VGA)
  291. ;        6:    640x200 2 color        (CGA, EGA, MCGA, VGA)
  292. ;        7:    80x25 monochrome    (MDA, EGA, VGA)
  293. ;        8-C:    -not supported-        (-PC jr only-)
  294. ;        D:    320x200 16 color    (EGA, VGA)
  295. ;        E:    640x200 16 color    (EGA, VGA)
  296. ;        F:    640x350 monochrome    (EGA, CGA)
  297. ;        10:    640x350 16 color    (EGA, VGA)
  298. ;        11:    640x480 monochrome    (EGA, CGA, MCGA)
  299. ;        12:    640x480 16 color    (EGA, VGA)
  300. ;        13:    320x200 256 color    (MCGA, VGA)
  301. ;        40:    640x400 2 color        (Olivetti M24/M28)
  302. ;        48:    640x400 2 color        (Olivetti M24/M28)
  303. ;
  304.     mov    al,VID_AL[bp]        ; what mode are we going in to ?
  305.     cmp    al,3            ; CGA text mode ?
  306.      jbe    v_i_sm2
  307.     cmp    al,7            ; mono text mode
  308.      je    v_i_sm2
  309.  
  310.     mov    al,VS_SCREEN_MODE    ; we are going to a graphics mode
  311.     cmp    al,3            ; but is it coming from a text one ?
  312.      jbe    v_i_sm1            ; if not it's already OK
  313.     cmp    al,7
  314.      jne    v_i_sm4
  315. v_i_sm1:
  316.     and    VS_MODE1, not SUSPEND_STATE
  317.     push    bx            ; we are changing from text mode
  318.     mov    bx,rlr$            ; to a graphics mode
  319.     test    P_SFLAG[bx],PSF_SUSPEND    ; so we examine the original state
  320.     pushf                ; of the suspend flag
  321.     or    P_SFLAG[bx],PSF_SUSPEND    ; and set it as well
  322.     popf
  323.     pop    bx
  324.      jz    v_i_sm4
  325.     or    VS_MODE1, SUSPEND_STATE    ; save original suspend state in VS_
  326.     jmps    v_i_sm4
  327.     
  328. v_i_sm2:    
  329.     mov    al,VS_SCREEN_MODE    ; we are going to a text mode
  330.     cmp    al,3            ; but was it graphics before ?
  331.      jbe    v_i_sm4            ; if not it's already OK
  332.     cmp    al,7
  333.      je    v_i_sm4
  334.     test    VS_MODE1, SUSPEND_STATE    ; examine original suspend state in VS_
  335.     push    bx            ; we are changing from text mode
  336.     mov    bx,rlr$            ; to a graphics mode
  337.     pushf
  338.     and    P_SFLAG[bx],not PSF_SUSPEND    ; so we examine the original state
  339.     popf                ; of the suspend flag
  340.      jz    v_i_sm3
  341.     or    P_SFLAG[bx],PSF_SUSPEND    ; and set it as well
  342. v_i_sm3:
  343.     pop    bx
  344.     and    VS_MODE1, not SUSPEND_STATE
  345. v_i_sm4:
  346.     mov    al,VID_AL[bp]        ; get ROM BIOS video mode
  347.     and    al,7Fh            ; strip off no-clear flag
  348.     cmp    al,7            ; CGA or MDA mode
  349.      jbe    v_i_sm7            ; normal video mode
  350.     test    video$,EGA+VGA+MCGA    ; EGA /MCGA or VGA installed?
  351.      jz    v_i_sm6            ; skip if not
  352.     cmp    al,13H            ; modes D-13 are EGA/VGA only
  353.      jbe    v_i_sm7            ;  modes 11 and 13 also supported on
  354.                     ;  MCGA - set_screen@ tests for 
  355.                     ;  unsupported ega modes on MCGA
  356. v_i_sm6:
  357.     cmp    cloneflag,IS_M24    ; else better had be M24 mode...
  358.      jne    v_i_sm9
  359.     cmp    al,64            ; 640x400, 8x16 font
  360.      je    v_i_sm7
  361.     cmp    al,72            ; 640x400, 8x8 font
  362.      je    v_i_sm7
  363.     jmps    v_i_sm9            ; no recognizable mode...ignore it
  364.  
  365. v_i_sm7:
  366.     mov    VS_MX,0            ; release semaphore
  367.     mov    di,rlr$
  368.     mov    dl,P_CONS[di]        ; get virtual console number
  369.     push    bx ! push bp        ; keep VS_ and VID_ structs safe
  370.     mov    cl,VID_AL[bp]        ; get ROM BIOS video mode (+ top bit)
  371.     call    set_screen@        ; call set mode
  372.     pop    bp ! pop bx        ; restore VS_ and VID_ pointers
  373.     call    switch_statline@    ; correct statline on/off
  374. v_i_sm9:                ; skip to here if not supported
  375.     ret
  376.  
  377.  
  378. v_i_cursortype:        ; 1 set cursor type
  379. ;--------------
  380. ;    Entry:    VID_CH, VID_CL = cursor type
  381.  
  382.     mov    cx,VID_CX[bp]        ; get new cursor type
  383.     push    cx
  384.     call    trans_cur_type@        ; translate to hardware cursor
  385.     pop    cx ! push cx
  386.     and    VS_MODE,not CURSOR_BIT    ; turn off cursor 
  387.     test    ch,60h            ; setting bits 5 or 6 turns cursor off
  388.     jnz    v_i_off
  389.     and    ch,0fh            ; mask start cursor line
  390.     and    cl,0fh            ; and end
  391.     cmp    ch,cl            ; if start > end
  392.     ja    v_i_off            ; then turn cursor off
  393.     or    VS_MODE,CURSOR_BIT    ; else make sure its on
  394. v_i_off:
  395.     pop    cx
  396.     mov    VS_CUR_TYPE,cx        ; save the new cursor
  397.     mov    dl,VS_NUMBER
  398.     cmp    top_screen$,dl
  399.     jne    v_i_ret
  400.     mov    ah,1            ; int 10 function #
  401.     call    int10_entry@
  402.     jmp    show_cursor@        ;   and display it
  403. v_i_ret:
  404.     ret
  405.  
  406. v_i_setcursor:        ; 2 set cursor position
  407. ;-------------
  408. ;    Entry:    VID_DH, _DL = row, column
  409. ;        VID_BH = page number (ignored by us)
  410.  
  411.     mov    dx,VID_DX[bp]
  412.     cmp    dh,VS_CRT_ROWS
  413.      jb    pc_v_row_ok            ; if row is too big
  414.     mov    dh,VS_CRT_ROWS            ;   then clip it
  415.     dec    dh
  416. pc_v_row_ok:
  417.     cmp    dl,VS_WIDTH
  418.      jb    pc_v_col_ok            ; if column is too big
  419.     mov    dl,VS_WIDTH            ;   then clip it
  420.     dec    dl
  421. pc_v_col_ok:
  422.     call    put_cursor@            ; (updates VS_CURSOR as well)
  423.     mov    dl,VS_NUMBER
  424.     cmp    top_screen$,dl
  425.     jne    v_i1_ret
  426. if SR
  427.     mov    di,rlr$                ; get calling process
  428.     mov    dl,P_CONS[di]            ; get its virtual console #
  429.     call    point_pc@            ; returns SI = PC_ structure
  430. endif
  431.     jmp    tick_cursor@            ; force physical cursor update
  432. v_i1_ret:
  433.     ret
  434.     
  435. v_i_getcursor:        ; 3 get cursor position
  436. ;-------------
  437. ;    Entry:    VID_BH = page number (ignored by us)
  438. ;    Exit:    VID_DH, VID_DL = cursor row, column
  439. ;        VID_CH, VID_CL = current cursor type
  440.  
  441.     call    update_vs_cursor_from_ros@
  442.     mov    ax,VS_CURSOR
  443.     mov    VID_DX[bp],ax
  444.     mov    ax,VS_CUR_TYPE
  445.     mov    VID_CX[bp],ax
  446.     ret
  447.  
  448. v_i_lpen:        ; 4 - read light pen position
  449. ;--------
  450. ;    Exit:    VID_AH = 0
  451.  
  452.     mov    VID_AH[bp],0        ; say light pen not triggered
  453.     ret
  454.  
  455.  
  456. v_i_spage:        ; 5 - select active page
  457. ;---------
  458. ;    Entry:    VID_AL = new display page
  459.  
  460.     ret                ; -not supported-
  461.  
  462.  
  463. v_i_scroll_up:        ; 6 scroll rectangle up
  464. ;-------------
  465. ;    Entry:    VID_AL = # of lines to scroll
  466. ;             0 = clear entire rectangle
  467. ;        VID_CH, VID_CL = top left corner of rectangle
  468. ;        VID_DH, VID_DL = bottom right corner of rectangle
  469. ;        VID_BH = attribute for spaces scrolled in
  470.  
  471.     push    VID_CX[bp]
  472.     push    VID_DX[bp]
  473.  
  474.     mov    dx,VID_CX[bp]            ; top left corner to start
  475.     call    point_cursor@            ; di -> top left corner
  476.     call    pc_video_count            ; move, erase and column counts
  477.      jc    pc_v_scroll_exit        ; quit on illegal box
  478.  
  479.     mov    al,VS_WIDTH            ; next row down
  480.     cbw  !    shl ax,1
  481.     jmps    pc_v_move_erase            ; shared routine from here
  482.  
  483. v_i_scroll_down:    ; 7 scroll window down
  484. ;---------------
  485. ;    Entry:    VID_AL = # of lines to scroll
  486. ;             0 = clear entire rectangle
  487. ;        VID_CH, VID_CL = top left corner of rectangle
  488. ;        VID_DH, VID_DL = bottom right corner of rectangle
  489. ;        VID_BH = attribute for spaces scrolled in
  490.  
  491.     push    VID_CX[bp]
  492.     push    VID_DX[bp]
  493.  
  494.     mov    dh,VID_DH[bp]            ; bottom row
  495.     mov    dl,VID_CL[bp]            ; left column
  496.     call    point_cursor@            ; di -> bottom left corner
  497.     call    pc_video_count            ; move, erase and column counts
  498.      jc    pc_v_scroll_exit        ; quit on illegal box
  499.  
  500.     mov    al,VS_WIDTH            ; next row down
  501.     cbw ! shl ax,1 ! neg ax
  502. ;    jmps    pc_v_move_erase            ; shared routine from here
  503.  
  504. pc_v_move_erase:
  505. ; Shared code for scroll up and down:
  506. ;  entry:    ax = + or - chars per crt row
  507.  
  508.     push    ax                ; save row increment
  509.     imul    VID_DX[bp]            ; ax = move offset
  510.     mov    si,di
  511.     add    si,ax                ; si -> move source
  512.     pop    dx                ; dx = row increment
  513.  
  514.     cmp    VID_CX[bp],0            ; if no moves to do
  515.      jz    pc_v_erase_loop            ;   then just erase
  516.  
  517. pc_v_move_loop:
  518.     mov    cx,VID_AX[bp]            ; get column count
  519.     push si ! push di            ; save line pointers
  520.     call    z_movsw@            ; move one screen line
  521.     pop di ! pop si
  522.     add    si,dx                ; next source line
  523.     add    di,dx                ;   and next destination
  524.     dec    VID_CX[bp]            ; move countdown
  525.      jnz    pc_v_move_loop
  526.  
  527. pc_v_erase_loop:
  528.     cmp    VID_DX[bp], 0
  529.      jz    pc_v_scroll_exit
  530. pc_v_erase_loop1:
  531.     mov    cx,VID_AX[bp]            ; get column count
  532.     mov    al,' '                ; erase to a blank
  533.     mov    ah,VID_BH[bp]            ; pick up the attribute
  534.     push dx ! push di
  535.     call    erase_pc@            ; erase one line
  536.     pop di ! pop dx
  537.     add    di,dx                ; next line to erase
  538.     dec    VID_DX[bp]            ; erase countdown
  539.      jnz    pc_v_erase_loop1
  540.  
  541. pc_v_scroll_exit:
  542.     pop    VID_DX[bp]
  543.     pop    VID_CX[bp]
  544.     ret
  545. eject
  546.  
  547. pc_video_count:
  548. ;--------------
  549. ; calculate move, erase and column counts
  550. ;  exit:    VID_DX[bp] = erase count
  551. ;        VID_CX[bp] = move count
  552. ;        VID_AX[bp] = column count
  553. ;              -    or -
  554. ;        cf set on illegal box
  555.  
  556.     mov    al,VID_DH[bp]            ; bottom row
  557.     sub    al,VID_CH[bp]            ; minus top row
  558.      jc    pc_count_exit            ; if negative, forget it
  559.  
  560.     cbw  !  inc ax                ; ax = # of rows in box
  561.     mov    dx,ax                ; dx = default erase count
  562.     sub    cx,cx                ; default move count = 0
  563.     sub    al,VID_AL[bp]            ; subtract lines to scroll
  564.      jbe    pc_count_erase            ; if too much, just erase
  565.     cmp    VID_AL[bp],0            ; if al = 0, just erase
  566.      jz    pc_count_erase
  567.  
  568.     mov    cx,ax                ; cx = move count
  569.     sub    dx,ax                ; dx = erase count
  570. pc_count_erase:
  571.     mov    al,VID_DL[bp]            ; right column
  572.     sub    al,VID_CL[bp]            ; minus left column
  573.      jc    pc_count_exit            ; if negative, forget it
  574.  
  575.     cbw  !    inc ax                ; ax = column count
  576.     mov    VID_DX[bp],dx            ; save the erase count
  577.     mov    VID_CX[bp],cx            ;   the move count and
  578.     mov    VID_AX[bp],ax            ;   column count in the stack
  579.     clc                    ; all is well
  580. pc_count_exit:
  581.     ret
  582.  
  583.  
  584.  
  585. pc_video_ret:
  586.     ret
  587.  
  588.  
  589. v_i_read:        ; 8 get attr/char at cursor
  590. ;--------
  591. ;    Entry:    VID_BH = page number (ignored by us)
  592. ;    Exit:    VID_AL = character read
  593. ;        VID_AH = attribute read (undefined if graphics)
  594.  
  595.     call    update_vs_cursor_from_ros@
  596.     mov    dx,VS_CURSOR
  597.     call    get_char_attr            ; call into common routine
  598.     jmps    ret_char_attr
  599.  
  600. get_char_attr:                ; entry point from subfunction 14
  601.                     ; to get current attribute
  602.     call    point_cursor@        ; di -> cursor dest
  603.     test    VS_MODE,MATCH_BIT    ; if matched then
  604.      jnz    pc_v_read_image        ;   get it from the image
  605.     mov    si,di            ; for lodsw
  606.     call    get_crt_c@        ; with sync'ing for color
  607.     jmps    ret_char_attr
  608. pc_v_read_image:
  609.     push    es
  610.     mov    es,VS_VC_SEG
  611.     mov    ax,es:[di]        ; no hurry here
  612.     pop    es
  613. ret_char_attr:
  614.     mov    VID_AX[bp],ax
  615.     ret
  616.     
  617.     
  618.  
  619. v_i_write_attr:        ; 9 set attr/char at cursor
  620. ;--------------
  621. ;    Entry:    VID_BH = page number (ignored by us)
  622. ;        VID_AL = character to write
  623. ;        VID_BL = attribute (text)/xor flag (graphics)
  624. ;        VID_CX = repeat count
  625.  
  626.     mov    al,VID_AL[bp]            ; get character
  627.     mov    ah,VID_BL[bp]            ; get attribute
  628.     mov    cx,VID_CX[bp]            ; get character count
  629.                 ; Write cx attr/chars at current cursor:
  630.     call    update_vs_cursor_from_ros@
  631.     mov    dx,VS_CURSOR
  632.  
  633. pc_ch_wr_a:
  634. ; Entry from EGA write_string:
  635. ;    AX = attr/char
  636. ;    CX = count
  637. ;    DX = cursor position
  638.     push    ax                ; save attr/char
  639.     call    point_cursor@            ; di -> cursor dest
  640.     pop    ax                ; restor attr/char
  641.     test    VS_MODE,MATCH_BIT        ; if full screen top
  642.      jz    pc_v_write_full_a        ;   then skip
  643.  
  644. ; This is a little redundant but it's much better than
  645. ; the old way of updating the screen every character!
  646.  
  647. pc_v_write_image_a:
  648.     push    es
  649.     push    cx
  650.     mov    cx,ax                ; save char in cx
  651.     call    point_cursor@
  652.     mov    es,VS_VC_SEG            ; go to the vc image
  653.     mov    es:[di],cx            ; store char and attribute
  654.  
  655. ; Now update screen if character belongs:
  656.  
  657.     mov    es,vc_map_seg$            ; for ownership check
  658.     add    ax,VS_CORRECT
  659.     xchg    ax,si                ; save for map check
  660.     call    in_window@            ; is char in window?
  661.     mov    ax,cx                ; ax = character + attrib
  662.      jc    pc_v_image_bump_a            ; skip if not
  663.  
  664.     mov    di,si
  665.     shl    di,1                ; back to screen coords
  666.     call    put_if_ours@            ; print it if we own it
  667. pc_v_image_bump_a:
  668.     inc    dl                ; advance cursor
  669.     cmp    dl,VS_WIDTH            ; if not wrapping around
  670.      jb    pc_v_image_next            ;   then do next char
  671.  
  672.     mov    dl,0
  673.     inc    dh                ; next row
  674. pc_v_image_next_a:
  675.     pop    cx
  676.     pop    es
  677.     loop    pc_v_write_image
  678.     ret
  679.  
  680. pc_v_write_full_a:
  681.     jmp    put_crt_s@            ; go right to physical
  682.  
  683. eject
  684.  
  685. v_i_write_char@:    ; 10 set char @ cur
  686. ;---------------
  687. ;    Entry:    VID_BH = page number (ignored by us)
  688. ;        VID_AL = character to write
  689. ;        VID_CX = repeat count
  690. ;
  691. ;    Note:    attributes are not modified
  692.  
  693.     mov    al,VID_AL[bp]            ; recover character
  694.     mov    cx,VID_CX[bp]            ; repeat count
  695.                 ; Write cx attr/chars at current cursor:
  696.     push    ax                ; save attr/char
  697.     call    update_vs_cursor_from_ros@
  698.     mov    dx,VS_CURSOR
  699.     call    point_cursor@            ; di -> cursor dest
  700.     pop    ax                ; restor attr/char
  701.     test    VS_MODE,MATCH_BIT        ; if full screen top
  702.      jz    pc_v_write_full            ;   then skip
  703.  
  704. ; This is a little redundant but it's much better than
  705. ; the old way of updating the screen every character!
  706.  
  707. pc_v_write_image:
  708.     push    es
  709.     push    cx
  710.     mov    cx,ax                ; save char in cx
  711.     call    point_cursor@
  712.     mov    es,VS_VC_SEG            ; go to the vc image
  713.     mov    es:[di],cl            ; store char, and...
  714.     mov    cx,es:[di]            ;  get screen attribute
  715.  
  716. ; Now update screen if character belongs:
  717.  
  718.     mov    es,vc_map_seg$            ; for ownership check
  719.     add    ax,VS_CORRECT
  720.     xchg    ax,si                ; save for map check
  721.     call    in_window@            ; is char in window?
  722.     mov    ax,cx                ; ax = character + attrib
  723.      jc    pc_v_image_bump            ; skip if not
  724.  
  725.     mov    di,si
  726.     shl    di,1                ; back to screen coords
  727.     call    put_if_ours@            ; print it if we own it
  728. pc_v_image_bump:
  729.     inc    dl                ; advance cursor
  730.     cmp    dl,VS_WIDTH            ; if not wrapping around
  731.      jb    pc_v_image_next            ;   then do next char
  732.  
  733.     mov    dl,0
  734.     inc    dh                ; next row
  735. pc_v_image_next:
  736.     pop    cx
  737.     pop    es
  738.     loop    pc_v_write_image
  739.     ret
  740.  
  741. pc_v_write_full:
  742.     mov    dx,ax                ; save char.
  743.     mov    si,di                ; dest. to source
  744.     call    get_crt_c@            ; get char + attr di,bx,cx,dx ok
  745. ; This bit is ok for function A, where we're only writing a character, but for
  746. ; function 9, this screw up the passed-in attribute.
  747.     mov    al,dl                ; add in new char
  748.     jmp    put_crt_s@            ; go right to physical
  749.  
  750.  
  751.  
  752. v_i_set_color:        ; 11 pallette / border control
  753. ;-------------
  754. ;    Entry:    VID_BH = color ID to set
  755. ;        VID_BL = color value to set
  756.  
  757.     mov    dl,VS_NUMBER
  758.     cmp    top_screen$,dl
  759.     jne    v_i3_ret
  760.     push    bx                ; save vs_
  761.      mov    bx,VID_BX[bp]
  762.      mov    ah,11                ; set color palette func.
  763.      call    int10_entry@            ; and hit up ROS
  764.     pop    bx
  765.  
  766.     push    ds
  767.      mov    ax,PC_SEGMENT
  768.      mov    ds,ax
  769.      mov    al,crt_pallette_40
  770.     pop    ds
  771.  
  772.     mov    VS_COLORSEL,al            ; save it in the screen struct.
  773. v_i3_ret:
  774.     ret
  775.  
  776. eject
  777.  
  778.  
  779. v_i_write_tty:        ; 14 write char stream as a tty
  780. ;-------------
  781. ;    Entry:    VID_AL = character to write
  782. ;        VID_BL = color in graphics mode
  783.  
  784.     mov    cl,VID_AL[bp]
  785.     call    update_vs_cursor_from_ros@
  786.     mov    dx,VS_CURSOR
  787.     cmp    cl,BS                ; backspace?
  788.      jne    pc_not_bs
  789.     jmp    vc_out_bs@
  790.  
  791. pc_not_bs:
  792.     cmp    cl,CR                ; cr?
  793.      jne    pc_not_cr
  794.     jmp    vc_out_cr@
  795.  
  796. pc_not_cr:
  797.     cmp    cl,LF                ; lf
  798.      jne    pc_not_lf
  799.     jmp    vc_out_lf@
  800.  
  801. pc_not_lf:
  802.     cmp    cl,BEL                ; bell?
  803.     jne    pc_not_bell
  804.     jmp    vc_out_bel@
  805.  
  806. pc_not_bell:
  807.     push    cx                ; save character
  808.     call    get_char_attr            ; find attr on current char
  809.     pop    cx
  810.     push    word ptr VS_ATTRIB        ; save default
  811.     mov    VS_ATTRIB,ah            ; temp change attribute
  812.     call    vc_out@
  813.     pop    word ptr VS_ATTRIB
  814.     ret
  815.  
  816.  
  817.  
  818. v_i_gmode:        ; 15 current video state
  819. ;---------
  820. ;    Exit:    VID_AL = current video mode (see v_i_smode:)
  821. ;        VID_AH = # of columns per line
  822. ;        VID_BH = current screen page (always 0 in CDOS)
  823.  
  824.     mov    al,VS_SCREEN_MODE    ; get current ROS video mode
  825.     mov    ah,VS_WIDTH        ; get screen width (40 / 80 cols)
  826.     mov    VID_AX[bp],ax
  827.     mov    VID_BH[bp],0        ; always in page 0
  828.     ret
  829.  
  830. v_i_set_pal_reg:    ; 16 EGA set pallette registers
  831. ;---------------
  832.  
  833.     test    video$,EGA+VGA        ; EGA or VGA ?
  834.      jmpz    pc_video_ret        ; return if neither mode
  835.     push    es            ;******
  836.     push    bx            ; save vs_ for mx release
  837.     lea    di,VS_PALLETTE        ; get pallette save area
  838.     mov    al,VID_AL[bp]
  839.     mov    bx,VID_BX[bp]
  840.     mov    dx,VID_DX[bp]
  841.     mov    es,VID_ES[bp]
  842.     mov    ah,16            ; function number
  843.     cmp    al,0
  844.      jnz    not_indiv_reg
  845.  
  846.     push    bx
  847.      sub    bh,bh
  848.      add    di,bx
  849.     pop    bx
  850. set_1:
  851.     mov    [di],bh            ; set value
  852.     jmps    to_ros10
  853.  
  854. not_indiv_reg:
  855.     cmp    al,1
  856.      jnz    not_over_reg
  857.     add    di,16            ; 17th entry
  858.     jmps    set_1
  859.  
  860. not_over_reg:
  861.     cmp    al,2
  862.      jnz    toggle_blink
  863.  
  864.     mov    si,dx
  865.     mov    cx,17            ; count = 16 pall. + overscan
  866.     push ds ! push es
  867.     pop ds ! pop es            ; switch segs
  868.     rep    movsb            ; save in VS_
  869.     push es ! push ds
  870.     pop es ! pop ds            ; restore segs
  871.     jmps    to_ros10
  872.  
  873. toggle_blink:                ; toggle the blink bit for ega
  874.     cmp    al,3
  875.     jnz    to_ros10        ; not one of the functions we emulate
  876.     pop    cx            ; get VS->
  877.     push    cx            ; and resave for exit
  878.     xchg    cx,bx            ; get VS-> to BX
  879.     push    cx
  880.     mov    ch,VS_MODE1
  881.     and    ch,not BLINK_TOGGLE    ; mask out blink bit
  882.     and    cl,BLINK_TOGGLE        ; isolate
  883.     or    cl,ch            ; mash together
  884.     mov    VS_MODE1,cl        ; save blink toggle state
  885.     pop    cx
  886.     xchg    cx,bx            ; retore BL and go to ROS
  887.  
  888. to_ros10:
  889.     pop    cx            ; get VS->
  890.     push    cx            ; and resave for exit
  891.     xchg    bx,cx            ; BX = VS->
  892.     mov    bl,VS_NUMBER
  893.     cmp    top_screen$,bl
  894.     jne    v_i2_ret        ; do not go to ROS if background VC
  895.     xchg    bx,cx            ; restore bx
  896.     mov    cx,VID_CX[bp]
  897.     call    int10_entry@        ; call ROS
  898. v_i2_ret:
  899.     pop    bx            ; restore vs_ for mx release
  900.     pop    es            ;********
  901.     ret
  902.  
  903. v_i_char_gen:        ; 17 EGA character generator
  904. ;------------
  905.  
  906.     test    video$,EGA+VGA            ; EGA VGA present?
  907.      jmpz    pc_video_ret
  908.     push    es                ;*****
  909.     push    bx                ; save vs_ for mx release
  910.     mov    al,VID_AL[bp]
  911.     cmp    al,14h                ; 16x8 (VGA) font?
  912.      je    v_i_char_gen0            ; back to normal on VGA
  913.     cmp    al,11h                ; 14x8 (ECD/mono) font?
  914.      jne    v_i_char_gen1            ; no, must be 8x8 (43/50) font
  915. v_i_char_gen0:
  916.     and    VS_MODE1,not LINE_43_MODE    ; reset 43 line mode bit
  917.     cmp    VS_SCREEN_MODE,04
  918.     jb    not_gra3
  919.     cmp    VS_SCREEN_MODE,07        ; if graphics mode
  920.     jne    v_i_char_gen1            ; leave graphic_bits
  921. not_gra3:
  922.     mov    cl,VS_BIT
  923.     not    cl
  924.     and    graphic_bits$,cl        ; else mask us out
  925.  
  926.     test    VS_MODE1, SUSPEND_STATE        ; examine original suspend VS_
  927.     push    bx
  928.     pushf
  929.     mov    bx,rlr$
  930.     and    P_SFLAG[bx],not PSF_SUSPEND    ; clear suspend state
  931.     popf
  932.      jz    v_i_char_gen0a
  933.     or    P_SFLAG[bx],PSF_SUSPEND        ; and restore to original value
  934. v_i_char_gen0a:
  935.     pop    bx
  936.     and    VS_MODE1, not SUSPEND_STATE    ; clear the copy
  937.  
  938. v_i_char_gen1:
  939.     cmp    al,12h
  940.     jne    v_i_char_gen3
  941.     mov    al,VS_BIT
  942.     not    al                ; if anybody else is in
  943.     test    graphic_bits$,al        ; anybody in graphics mode
  944.      jz    v_i_char_gen2
  945.     mov    VS_MX,0                ; release semaphore
  946.     push    bp
  947.      call    gr_abort@            ; suspend running process
  948.     pop    bp
  949.     call    get_mx@
  950. v_i_char_gen2:
  951.     or    VS_MODE1,LINE_43_MODE        ; set 43 line mode bit
  952.     mov    cl,VS_BIT            ; 43 line is incompatible
  953.     or    graphic_bits$,cl        ;  w/ screen switching - set as graphics
  954.     and    VS_MODE1, not SUSPEND_STATE    ; clear copy of suspend state
  955.     push    bx
  956.     mov    bx,rlr$                ; look at the PD
  957.     test    P_SFLAG[bx],PSF_SUSPEND        ; examine the original state
  958.     pushf
  959.     or    P_SFLAG[bx],PSF_SUSPEND        ; now set it
  960.     popf
  961.     pop    bx
  962.      jz    v_i_char_gen2a
  963.     or    VS_MODE1, SUSPEND_STATE        ; save original suspend in VS_
  964. v_i_char_gen2a:
  965.     mov    al,VID_AL[bp]            ; reload AL
  966. v_i_char_gen3:
  967.     push    bp
  968.     mov    bx,VID_BX[bp]
  969.     mov    cx,VID_CX[bp]
  970.     mov    dx,VID_DX[bp]
  971.     mov    es,VID_ES[bp]
  972.     mov    bp,VID_BP[bp]
  973.     mov    ah,17                ; function number
  974.     call    int10_entry@            ; call ROS
  975.     mov    ax,bp                ; save temporary
  976.     pop    bp
  977.     mov    VID_CX[bp],cx
  978.     mov    VID_DX[bp],dx
  979.     mov    VID_ES[bp],es
  980.     mov    VID_BP[bp],ax            ; BP on return
  981.     pop    bx                ; restore vs_ for mx release
  982.     pop    es                ;********
  983.     ret
  984.  
  985. v_i_alt_select:        ; 18 EGA alternate select
  986. ;--------------
  987.     test    video$,EGA+VGA            ; EGA/VGA present?
  988.      jmpz    pc_video_ret
  989.     push    es                ;********
  990.     push    bx                ; save vs_ for mx release
  991.     mov    ah,18                ; function number
  992.     mov    bx,VID_BX[bp]            ; sub sub function
  993.     mov    cx,VID_CX[bp]
  994.     mov    es,VID_ES[bp]
  995.     mov    dx,VID_DX[bp]
  996.     mov    al,VID_AL[bp]
  997.     call    int10_entry@            ; call ROS
  998.     mov    VID_BX[bp],bx            ; mode and memory
  999.     mov    VID_CX[bp],cx            ; feat/switch
  1000.     mov    VID_AX[bp],ax
  1001.     pop    bx                ; restore vs_ for mx release
  1002.     pop    es                ;*************
  1003.  
  1004.     ret
  1005.  
  1006. v_i_write_string:    ; 19 EGA write string
  1007. ;----------------
  1008. ;    Entry:    VID_ES:VID_BP -> string to display
  1009. ;        VID_CX = character count
  1010. ;        VID_DH, VID_DL = starting cursor address
  1011. ;        VID_BH (ignored by CDOS)
  1012. ;        VID_BL = attribute if VID_AL = 0 or 1
  1013. ;        VID_AL = 0-3:
  1014. ;             0: ES:BP -> chars only, cursor not moved
  1015. ;             1: ES:BP -> chars only, cursor is moved
  1016. ;             2: ES:BP -> chars/attribs, cursor not moved
  1017. ;             3: ES:BP -> chars/attribs, cursor is moved
  1018. ;    Note:    AL = 2, 3 are not supported in graphics mode
  1019. ;        CR, LF, BS, BEL are interpreted rather than displayed.
  1020.  
  1021.     call    update_vs_cursor_from_ros@
  1022.     mov    ax,VID_AX[bp]            ; get sub func. #
  1023.     cmp    al,3                ; is it legal ??
  1024.      ja    v_i_write_string1        ; no ignore it
  1025.     cmp    al,0
  1026.      je    attr_9                ; don't move cursor
  1027.     cmp    al,1
  1028.      je    attr_e                ; move cursor
  1029.     cmp    al,2
  1030.      je    ch_attr_9            ; don't move cursor
  1031. ;    cmp    al,3
  1032. ;     je    ch_attr_e            ; must be...
  1033.     jmp    ch_attr_e            ; move cursor
  1034. v_i_write_string1:
  1035.     ret
  1036.  
  1037.  
  1038. attr_9:
  1039. ; String is char only..no cursor movement:
  1040.  
  1041.     mov    cx,VID_CX[bp]
  1042.     mov    si,VID_BP[bp]
  1043.     mov    dx,VID_DX[bp]            ; get start position
  1044.     push    VS_CURSOR
  1045. a9_lp:
  1046.     push    ds
  1047.      mov    ds,VID_ES[bp]
  1048.      lodsb
  1049.     pop    ds
  1050.  
  1051.     mov    ah,VID_BL[bp]
  1052.  
  1053.     push    si
  1054.     push    cx
  1055.     push    dx            ; save position
  1056.      mov    cx,1
  1057.      call    pc_ch_wr_a        ; will release MX
  1058.     pop    dx
  1059.     inc    dx            ; move to next position
  1060.     pop    cx
  1061.     pop    si
  1062.     
  1063.     loop    a9_lp
  1064.     pop    dx            ; restore old VS_CURSOR
  1065.     call    point_cursor@
  1066.     mov    VS_OFFSET,ax
  1067.     mov    VS_CURSOR,dx
  1068.     mov    ax,dx
  1069.     jmp    poke_ros_cursor@
  1070. ;    ret
  1071.  
  1072.  
  1073. ch_attr_9:
  1074. ; String is char/attr...no cursor movement:
  1075.     mov    cx,VID_CX[bp]
  1076.     mov    si,VID_BP[bp]
  1077.     mov    dx,VID_DX[bp]            ; get start position
  1078.     push    VS_CURSOR
  1079. cha9_lp:
  1080.     push    ds
  1081.      mov    ds,VID_ES[bp]
  1082.      lodsw
  1083.     pop    ds
  1084.  
  1085.     push    si
  1086.     push    cx
  1087.     push    dx            ; save position
  1088.      mov    cx,1
  1089.      call    pc_ch_wr_a        ; will release MX
  1090.     pop    dx
  1091.     inc    dx            ; next position            
  1092.     pop    cx
  1093.     pop    si
  1094.  
  1095.     loop    cha9_lp
  1096.     pop    dx            ; restore old VS_CURSOR
  1097.     call    point_cursor@
  1098.     mov    VS_OFFSET,ax
  1099.     mov    VS_CURSOR,dx
  1100.     mov    ax,dx
  1101.     jmp    poke_ros_cursor@
  1102. ;    ret
  1103.  
  1104.  
  1105. attr_e:
  1106. ; String is char only...move cursor:
  1107.     mov    cx,VID_CX[bp]
  1108.     mov    si,VID_BP[bp]
  1109.     mov    dx,VID_DX[bp]            ; get start cursor position
  1110.     call    point_cursor@
  1111.     mov    VS_OFFSET,ax
  1112.     mov    VS_CURSOR,dx            ; update position
  1113. ae_lp:
  1114.     push    ds
  1115.      mov    ds,VID_ES[bp]
  1116.      lodsb
  1117.     pop    ds
  1118.  
  1119.     push    si
  1120.     push    cx
  1121.     push    dx
  1122.     mov    cl,al
  1123.     mov    al,VID_BL[bp]
  1124.     mov    VS_ATTRIB,al
  1125.     call    tty_branch    
  1126.     pop    dx
  1127.     inc    dx                ; next location
  1128.     pop    cx
  1129.     pop    si
  1130.     loop    ae_lp
  1131.     call    point_cursor@
  1132.     mov    VS_OFFSET,ax
  1133.     mov    VS_CURSOR,dx            ; update position
  1134.     mov    ax,dx
  1135.     jmp    poke_ros_cursor@
  1136. ;    ret
  1137.  
  1138.  
  1139. ch_attr_e:
  1140. ; String is char/attr...move cursor:
  1141.  
  1142.     mov    cx,VID_CX[bp]
  1143.     mov    si,VID_BP[bp]
  1144.     mov    dx,VID_DX[bp]            ; get start cursor position
  1145.     call    point_cursor@
  1146.     mov    VS_OFFSET,ax
  1147.     mov    VS_CURSOR,dx            ; update position
  1148. chae_lp:
  1149.     push    ds
  1150.      mov    ds,VID_ES[bp]
  1151.      lodsw
  1152.     pop    ds
  1153.     mov    VS_ATTRIB,ah
  1154.  
  1155.     push    si
  1156.     push    cx
  1157.     push    dx
  1158.     mov    cl,al
  1159.     call    tty_branch
  1160.     pop    dx
  1161.     inc    dx                ; next location
  1162.     pop    cx
  1163.     pop    si
  1164.  
  1165.     loop    chae_lp
  1166.     call    point_cursor@
  1167.     mov    VS_OFFSET,ax
  1168.     mov    VS_CURSOR,dx            ; update position
  1169.     mov    ax,dx
  1170.     jmp    poke_ros_cursor@
  1171. ;    ret
  1172.  
  1173.  
  1174. tty_branch:
  1175.     cmp    cl,' '
  1176.      jb    t_ctl
  1177.     jmp    vc_out@    
  1178. t_ctl:
  1179.     cmp    cl,BS
  1180.     jne    t_no_bs
  1181.      jmp    vc_out_bs@
  1182. t_no_bs:
  1183.     cmp    cl,CR
  1184.      jne    t_no_cr
  1185.     jmp    vc_out_cr@
  1186. t_no_cr:
  1187.     cmp    cl,LF
  1188.     jne    t_no_lf
  1189.      jmp    vc_out_lf@
  1190. t_no_lf:
  1191.     cmp    cl,BEL
  1192.      jne    t_no_bl
  1193.     jmp    vc_out_bel@
  1194. t_no_bl:
  1195.     jmp    vc_out@    
  1196.     ret
  1197.  
  1198.  
  1199. v_i_notimp:
  1200. ;----------
  1201.     ret            ; ROS function not implemented
  1202.  
  1203.  
  1204.  
  1205. poke_ros_cursor@:
  1206. ;----------------
  1207. ; Routine to update the cursor posn word in the ros data area:
  1208. ; Entry:    AX = cursor...high = row, low = col
  1209. ;        BX = VS_
  1210. ; Exit:        all preserved
  1211.     pushf
  1212.     cli
  1213.     push    dx
  1214.     mov    dl,VS_NUMBER
  1215.     cmp    top_screen$,dl
  1216.     pop    dx
  1217.      jne    prc1
  1218.  
  1219.     push    ds
  1220.     mov    ds,ros_seg        ; assume active page zero
  1221.     mov    cursor_posn_40,ax
  1222.     pop    ds
  1223. prc1:
  1224.     popf
  1225.     ret
  1226.  
  1227. update_vs_cursor_from_ros@:
  1228. ;--------------------------
  1229. ; Routine to read the cursor posn word in the ros data area:
  1230. ; Entry:    DS:BX = VS_
  1231. ; Exit:
  1232. ;        preserve all regs
  1233. ;     
  1234.     pushf
  1235.     cli
  1236.     push    dx
  1237.     mov    dl,VS_NUMBER        ; if we aren't the top screen
  1238.     cmp    top_screen$,dl        ; don't use the ros
  1239.      jne    update_vs2
  1240.     push    es
  1241.     mov    es,ros_seg
  1242.     mov    dx,es:cursor_posn_40    ; assume page zero
  1243.     cmp    dx,VS_CURSOR
  1244.      je    update_vs1
  1245.     push    ax
  1246.     push    di
  1247.     call    point_cursor@
  1248.     mov    VS_OFFSET,ax
  1249.     mov    VS_CURSOR,dx
  1250.     pop    di
  1251.     pop    ax
  1252. update_vs1:
  1253.     pop    es
  1254. update_vs2:
  1255.     pop    dx
  1256.     popf
  1257.     ret
  1258.  
  1259.  
  1260. ros_seg        dw    PC_SEGMENT
  1261.  
  1262. end
  1263.  
  1264. ; END OF PCVIDEO.A86
  1265.