home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-01-26 | 31.5 KB | 1,265 lines |
- ; PCVIDEO.A86
- title 'PCDOS Video Support'
- pagesize 60+10
- ;********************************************************
- ;* *
- ;* PC MODE VIDEO SUPPORT *
- ;* CDOS 6.0 XIOS *
- ;* DRI OS ENGR, JMB, GMS, JW *
- ;* *
- ;********************************************************
- ; Mods:
- ; 6.x
- ; 18 Nov 88 -- also suspend 43 line modes IJ
- ; 9 Nov 88 -- force suspend on when in graphics modes IJ
- ; 3 Nov 88 -- push & pop VID_CX and VID_DX in pc_v_erase_loop ACH
- ; 5 Oct 88 -- enable ints during int 10 handler IJ
- ; 21 Sep 88 -- int 10 subf 13 takes better notice of DX value IJ
- ; 18 AUG 88 -- ROS Palettes only updated if foreground GMS
- ; 12 Jul 88 -- Ros cursor mode support IJ
- ; 1 JUL 88 -- turn TEMPKEEP flag on while in int 10h functions GMS
- ; 11 APR 88 -- added Sun River support GMS
- ; 7 MAR 88 -- Don't change cursor type if background VC GMS
- ; 4 FEB 88 -- VS_CUR_TYPE_HW updated in trans_cur_type GMS
- ; 16 DEC 87 -- bug fix for string writes function 13h GMS
- ; 7 DEC 87 -- int10_bx entries replaced with int10_entry GMS
- ; 4 DEC 87 -- VS_SCREEN_MODE now uses ROS video mode values GMS
- ; 4 DEC 87 -- removed pc_video_write_char GMS
- ; 2 DEC 87 -- replaced ega$ with redefined video$ GMS
- ; 6.0
- ; 12 NOV 87 -- correct statline on/off after mode change GMS
- ; 10 NOV 87 -- Int 10h cursor update calls tick_cursor@ GMS
- ; 7 NOV 87 -- fix EGA 43 lines on monochrome display JW
- ; -- fix 43 line CY state for ROS calls (V_I_GR) JW
- ; 4 NOV 87 -- set blink toggle for ega mono GMS
- ; 3 NOV 87 -- set pal reg subfunction 0bh checked if graphics GMS
- ; 2 NOV 87 -- Int 10h set cursor type checks for cursor on/off GMS
- ; 24 SEP 87 -- Int 10h now does stack swap onto UDA stack GMS
- ; 21 AUG 87 -- Implemented Ega top bit on mode selects GMS
- ; 17 JUL 87 -- small model XIOS conversion JW
- ; 22 JUN 87 -- 43 line ega support GMS
- ; 13 JUN 87 -- new video_int@ code for 6.0 int 10h emulation JW
- ; 5.2
- ; 24 APR 87 -- return cursor type from VS_CUR_TYPE - function 3 GMS
- ; 13 APR 87 -- abort serial terminal process if making ROS call GMS
- ; 2 MAR 87 -- colour pallettes saved for each virtual console GMS
- ; 27 FEB 87 -- save EGA blink toggle in VS_ GMS
- ; 5.1
- ; 14 JAN 87 -- Set cursor update bit GMS
- ; 21 NOV 86 -- Use current screen attribute for subfunction 14 GMS
- ; 26 JUN 86 -- elim. double spaceing in f. 10 -- WD
- ; 3 JUN 86 -- save cursor posn in 40: for VP_PLNR.
- ; 16 APR 86 -- support VS_CUR_TYPE_HW (for ega)
- ; 13 FEB 86 -- fix int 10h function 0Ah attribute bug
- ; 6 JAN 86 -- fix int 10h function 10h
- ; 7 NOV 85 -- add int 10h sub-functions 10h,11h,12h, and 13h for EGA
- ; 2 JUL 85 -- use ROS int 10h for palette color
- ; 12 JUN 85 -- update 4.1 ASM86 XIOS to RASM86
-
- ; include COPYRITE.TXT
-
- nolist
- include CDOS.EQU
- include XIOS.EQU
- include PCHW.EQU
- include ROSDATA.EQU
- include ASCII.EQU
- list
- ; These have been included:
- ; include CDOS.EQU
- ; include XIOS.EQU
- ; include PCHW.EQU
- ; include ROSDATA.EQU
- ; include ASCII.EQU
-
- CGROUP group CODE
- DGROUP group DATA
-
- public video_int@ ; for INIT.A86
- public poke_ros_cursor@
- public update_vs_cursor_from_ros@
-
- cseg
- extrn sysdat$:word ; in HEADER.A86
- extrn show_cursor@:near, put_cursor@:near ; in WINDOWS1.A86
- extrn z_movsw@:near, erase_pc@:near
- extrn in_window@:near, vc_out@:near
- extrn vc_out_bs@:near, vc_out_cr@:near
- extrn vc_out_lf@:near, vc_out_bel@:near
- extrn ser_abort@:near, gr_abort@:near
- extrn set_screen@:near
- extrn point_cursor@:near, point_vs@:near ; in WINDOWS2.A86
- extrn get_mx@:near
- extrn get_crt_c@:near, put_if_ours@:near ; in WINDOWS3.A86
- extrn put_crt_s@:near
- extrn trans_cur_type@:near
- extrn int10_entry@:near ; in ROSIF.A86
- extrn int10_isr$:dword
- extrn tick_cursor@:near ; in ISRS.A86
- extrn switch_statline@:near ; in STATLINE.A86
- if SR
- extrn test_srterm@:near ; in SRTERM.A86
- extrn point_pc@:near
- endif
-
- dseg
- extrn cloneflag$:byte
- extrn video$: byte
- extrn vc_map_seg$: word
- extrn top_screen$: byte
- ;extrn palette_word$: word
- extrn graphic_bits$:byte ; in WINDOWS3.A86
- eject
-
- cseg
-
- v_i_ros: ; pass on to ROS
- ;-------
- jmpf int10_isr$ ;
-
-
- ;==========
- video_int@:
- ;==========
- ; This function handles Int 10h calls from PC DOS applications.
- ; It emulates some of the functions, mainly for performance and
- ; in order to support text based windowing. Graphics can not be
- ; windowed and therefore the ROS is used for all graphic mode
- ; video I/O.
- ; Switches onto UDA stack.
- sti
- cld
- cmp ah,13H ; last function that we handle
- ja v_i_ros ; function out of range, call ROS
-
- push ds ; save DS and DI on
- push di ; users stack
- mov ds,sysdat$
-
- mov di,rlr$ ; Get our PD
- mov ds,P_UDA[di] ; DS = UDA segment
- inc ds:U_INSYS ; Increment the INSYS flag but do not
- cmp ds:U_INSYS,1 ; swap the stack if INSYS is already
- jne noswtch ; non zero.
- mov ds:U_STACK_SS,ss ;
- mov ds:U_STACK_SP,sp ; save users SS and SP
- mov di,ds ! mov ss,di ; The stack starts at the end of
- mov sp,ds:U_USIZE ; the standard UDA
-
- noswtch:
- push ds ; save UDA
-
- mov ds,sysdat$
- push si
- push bx ; extra for temp store
- push es
- push bp ! push bp
- push dx ! push cx ! push bx ! push ax
- mov bp,sp
-
- mov di,rlr$ ; get calling process
- or P_FLAG[di],PF_TEMPKEEP ; prevent aborting
- mov dl,P_CONS[di] ; get its virtual console #
- mov VID_VCONS[bp],dl ; set virtual console
- cmp dl,NUM_VIR_CONS ; is it a serial terminal?
- jb v_i_1 ; main console
- if SR
- call test_srterm@ ; test if SUN RIVER main console
- jnz v_i_1 ; yes ..
- endif
- jmps v_i_kill ; dumb terminal - shouldn't issue INT 10h
- v_i_1:
- call point_vs@ ; get virtual console structure
- call get_mx@ ; get screen semaphore
-
- mov al,VID_AH[bp] ; get ROS sub-function
- or al,al ; MODE change ?
- jz v_i_emu ; yes lets emulate
- cmp al,16 ; set palette regs ega
- jz v_i_emu
- cmp al,15 ; get video mode
- jz v_i_emu
- cmp al,11 ; set palette reg
- jz v_i_emu
- cmp VS_SCREEN_MODE,04 ;
- jb not_gra2
- cmp VS_SCREEN_MODE,07 ; if graphics mode
- jne v_i_gr
- not_gra2:
- test VS_MODE1,LINE_43_MODE ; or 43 line mode
- jnz v_i_gr ; go direct to the ROS
- v_i_emu:
- cbw ; make it a word
- mov di,ax ; DI = sub function #
- shl di,1 ; entry into word table
- call v_i_table[di] ; invoke subfunction
-
- v_i_exit:
- mov VS_MX,0 ; release semaphore
- mov di,rlr$
- and P_FLAG[di],not PF_TEMPKEEP
-
- pop ax ! pop bx ! pop cx ! pop dx
- pop bp ! pop bp ; restore all registers
- pop es
- pop si ; temp store
- pop si
-
- pop ds ; back to UDA segment
-
- dec ds:U_INSYS ; If U_INSYS is zero then restore
- jnz nstk ; the user's stack
-
- mov ss,ds:U_STACK_SS
- mov sp,ds:U_STACK_SP
- nstk:
- pop di ; users DI
- pop ds ; users DS
-
-
- iret
-
-
-
- v_i_kill:
- mov al,VID_AH[bp] ; get ROS sub-function
- cmp al,15 ; is it get mode function
- jne v_i_killit ; no .... abort process
- mov ax,5009h ; else let's pretend we're monochrome
- mov VID_AX[bp],ax
- jmp v_i_exit
-
- v_i_killit:
- jmp ser_abort@ ; can't make ROS calls on serial term.
-
- v_i_gr:
- xchg bx,VID_TEMP[bp] ; save VS ->
- pop ax ! pop bx ! pop cx ! pop dx
- pop bp ! pop bp ; restore all registers
- pop es
-
- call int10_entry@ ; do the ROS function
- mov si,bx ; save bx
- pop bx ; get saved VS->
- mov VS_MX,0 ; release semaphore
- mov di,rlr$
- and P_FLAG[di],not PF_TEMPKEEP
- mov bx,si ; restore bx
- pop si
- pop ds ; back to UDA segment
- dec ds:U_INSYS ; If U_INSYS is zero then restore
- jnz nstk1 ; the user's stack
-
- mov ss,ds:U_STACK_SS
- mov sp,ds:U_STACK_SP
- nstk1:
- pop di ; users DI
- pop ds ; users DS
-
- iret
-
- v_i_table dw v_i_smode ; 0 set video mode
- dw v_i_cursortype ; 1 set cursor type
- dw v_i_setcursor ; 2 set cursor position
- dw v_i_getcursor ; 3 get cursor position
- dw v_i_lpen ; 4 read light pen
- dw v_i_spage ; 5 select display page
- dw v_i_scroll_up ; 6 scroll window up
- dw v_i_scroll_down ; 7 scroll window down
- dw v_i_read ; 8 get attr/char at cursor
- dw v_i_write_attr ; 9 set attr/char at cursor
- dw v_i_write_char@ ; 10 set char (curr.attr) @ cur
- dw v_i_set_color ; 11 pallette / border control
- dw v_i_ros ; 12 graphics pix write
- dw v_i_ros ; 13 graphics pix read
- dw v_i_write_tty ; 14 write char stream as a tty
- dw v_i_gmode ; 15 current video state
- dw v_i_set_pal_reg ; 16 EGA set pallette registers
- dw v_i_char_gen ; 17 EGA character generator
- dw v_i_alt_select ; 18 EGA alternate select
- dw v_i_write_string ; 19 EGA write string
-
- v_i_smode: ; 0 set video mode
- ;---------
- ; Entry: VID_AL = new video mode
- ; (bit 7 = 1 if screen memory not to be
- ; cleared on mode switch)
- ;
- ; Modes: 0, 1: 40x25 16 color (CGA, EGA, MCGA, VGA)
- ; 2, 3: 80x25 16 color (CGA, EGA, MCGA, VGA)
- ; 4, 5: 320x200 4 color (CGA, EGA, MCGA, VGA)
- ; 6: 640x200 2 color (CGA, EGA, MCGA, VGA)
- ; 7: 80x25 monochrome (MDA, EGA, VGA)
- ; 8-C: -not supported- (-PC jr only-)
- ; D: 320x200 16 color (EGA, VGA)
- ; E: 640x200 16 color (EGA, VGA)
- ; F: 640x350 monochrome (EGA, CGA)
- ; 10: 640x350 16 color (EGA, VGA)
- ; 11: 640x480 monochrome (EGA, CGA, MCGA)
- ; 12: 640x480 16 color (EGA, VGA)
- ; 13: 320x200 256 color (MCGA, VGA)
- ; 40: 640x400 2 color (Olivetti M24/M28)
- ; 48: 640x400 2 color (Olivetti M24/M28)
- ;
- mov al,VID_AL[bp] ; what mode are we going in to ?
- cmp al,3 ; CGA text mode ?
- jbe v_i_sm2
- cmp al,7 ; mono text mode
- je v_i_sm2
-
- mov al,VS_SCREEN_MODE ; we are going to a graphics mode
- cmp al,3 ; but is it coming from a text one ?
- jbe v_i_sm1 ; if not it's already OK
- cmp al,7
- jne v_i_sm4
- v_i_sm1:
- and VS_MODE1, not SUSPEND_STATE
- push bx ; we are changing from text mode
- mov bx,rlr$ ; to a graphics mode
- test P_SFLAG[bx],PSF_SUSPEND ; so we examine the original state
- pushf ; of the suspend flag
- or P_SFLAG[bx],PSF_SUSPEND ; and set it as well
- popf
- pop bx
- jz v_i_sm4
- or VS_MODE1, SUSPEND_STATE ; save original suspend state in VS_
- jmps v_i_sm4
-
- v_i_sm2:
- mov al,VS_SCREEN_MODE ; we are going to a text mode
- cmp al,3 ; but was it graphics before ?
- jbe v_i_sm4 ; if not it's already OK
- cmp al,7
- je v_i_sm4
- test VS_MODE1, SUSPEND_STATE ; examine original suspend state in VS_
- push bx ; we are changing from text mode
- mov bx,rlr$ ; to a graphics mode
- pushf
- and P_SFLAG[bx],not PSF_SUSPEND ; so we examine the original state
- popf ; of the suspend flag
- jz v_i_sm3
- or P_SFLAG[bx],PSF_SUSPEND ; and set it as well
- v_i_sm3:
- pop bx
- and VS_MODE1, not SUSPEND_STATE
- v_i_sm4:
- mov al,VID_AL[bp] ; get ROM BIOS video mode
- and al,7Fh ; strip off no-clear flag
- cmp al,7 ; CGA or MDA mode
- jbe v_i_sm7 ; normal video mode
- test video$,EGA+VGA+MCGA ; EGA /MCGA or VGA installed?
- jz v_i_sm6 ; skip if not
- cmp al,13H ; modes D-13 are EGA/VGA only
- jbe v_i_sm7 ; modes 11 and 13 also supported on
- ; MCGA - set_screen@ tests for
- ; unsupported ega modes on MCGA
- v_i_sm6:
- cmp cloneflag,IS_M24 ; else better had be M24 mode...
- jne v_i_sm9
- cmp al,64 ; 640x400, 8x16 font
- je v_i_sm7
- cmp al,72 ; 640x400, 8x8 font
- je v_i_sm7
- jmps v_i_sm9 ; no recognizable mode...ignore it
-
- v_i_sm7:
- mov VS_MX,0 ; release semaphore
- mov di,rlr$
- mov dl,P_CONS[di] ; get virtual console number
- push bx ! push bp ; keep VS_ and VID_ structs safe
- mov cl,VID_AL[bp] ; get ROM BIOS video mode (+ top bit)
- call set_screen@ ; call set mode
- pop bp ! pop bx ; restore VS_ and VID_ pointers
- call switch_statline@ ; correct statline on/off
- v_i_sm9: ; skip to here if not supported
- ret
-
-
- v_i_cursortype: ; 1 set cursor type
- ;--------------
- ; Entry: VID_CH, VID_CL = cursor type
-
- mov cx,VID_CX[bp] ; get new cursor type
- push cx
- call trans_cur_type@ ; translate to hardware cursor
- pop cx ! push cx
- and VS_MODE,not CURSOR_BIT ; turn off cursor
- test ch,60h ; setting bits 5 or 6 turns cursor off
- jnz v_i_off
- and ch,0fh ; mask start cursor line
- and cl,0fh ; and end
- cmp ch,cl ; if start > end
- ja v_i_off ; then turn cursor off
- or VS_MODE,CURSOR_BIT ; else make sure its on
- v_i_off:
- pop cx
- mov VS_CUR_TYPE,cx ; save the new cursor
- mov dl,VS_NUMBER
- cmp top_screen$,dl
- jne v_i_ret
- mov ah,1 ; int 10 function #
- call int10_entry@
- jmp show_cursor@ ; and display it
- v_i_ret:
- ret
-
- v_i_setcursor: ; 2 set cursor position
- ;-------------
- ; Entry: VID_DH, _DL = row, column
- ; VID_BH = page number (ignored by us)
-
- mov dx,VID_DX[bp]
- cmp dh,VS_CRT_ROWS
- jb pc_v_row_ok ; if row is too big
- mov dh,VS_CRT_ROWS ; then clip it
- dec dh
- pc_v_row_ok:
- cmp dl,VS_WIDTH
- jb pc_v_col_ok ; if column is too big
- mov dl,VS_WIDTH ; then clip it
- dec dl
- pc_v_col_ok:
- call put_cursor@ ; (updates VS_CURSOR as well)
- mov dl,VS_NUMBER
- cmp top_screen$,dl
- jne v_i1_ret
- if SR
- mov di,rlr$ ; get calling process
- mov dl,P_CONS[di] ; get its virtual console #
- call point_pc@ ; returns SI = PC_ structure
- endif
- jmp tick_cursor@ ; force physical cursor update
- v_i1_ret:
- ret
-
- v_i_getcursor: ; 3 get cursor position
- ;-------------
- ; Entry: VID_BH = page number (ignored by us)
- ; Exit: VID_DH, VID_DL = cursor row, column
- ; VID_CH, VID_CL = current cursor type
-
- call update_vs_cursor_from_ros@
- mov ax,VS_CURSOR
- mov VID_DX[bp],ax
- mov ax,VS_CUR_TYPE
- mov VID_CX[bp],ax
- ret
-
- v_i_lpen: ; 4 - read light pen position
- ;--------
- ; Exit: VID_AH = 0
-
- mov VID_AH[bp],0 ; say light pen not triggered
- ret
-
-
- v_i_spage: ; 5 - select active page
- ;---------
- ; Entry: VID_AL = new display page
-
- ret ; -not supported-
-
-
- v_i_scroll_up: ; 6 scroll rectangle up
- ;-------------
- ; Entry: VID_AL = # of lines to scroll
- ; 0 = clear entire rectangle
- ; VID_CH, VID_CL = top left corner of rectangle
- ; VID_DH, VID_DL = bottom right corner of rectangle
- ; VID_BH = attribute for spaces scrolled in
-
- push VID_CX[bp]
- push VID_DX[bp]
-
- mov dx,VID_CX[bp] ; top left corner to start
- call point_cursor@ ; di -> top left corner
- call pc_video_count ; move, erase and column counts
- jc pc_v_scroll_exit ; quit on illegal box
-
- mov al,VS_WIDTH ; next row down
- cbw ! shl ax,1
- jmps pc_v_move_erase ; shared routine from here
-
- v_i_scroll_down: ; 7 scroll window down
- ;---------------
- ; Entry: VID_AL = # of lines to scroll
- ; 0 = clear entire rectangle
- ; VID_CH, VID_CL = top left corner of rectangle
- ; VID_DH, VID_DL = bottom right corner of rectangle
- ; VID_BH = attribute for spaces scrolled in
-
- push VID_CX[bp]
- push VID_DX[bp]
-
- mov dh,VID_DH[bp] ; bottom row
- mov dl,VID_CL[bp] ; left column
- call point_cursor@ ; di -> bottom left corner
- call pc_video_count ; move, erase and column counts
- jc pc_v_scroll_exit ; quit on illegal box
-
- mov al,VS_WIDTH ; next row down
- cbw ! shl ax,1 ! neg ax
- ; jmps pc_v_move_erase ; shared routine from here
-
- pc_v_move_erase:
- ; Shared code for scroll up and down:
- ; entry: ax = + or - chars per crt row
-
- push ax ; save row increment
- imul VID_DX[bp] ; ax = move offset
- mov si,di
- add si,ax ; si -> move source
- pop dx ; dx = row increment
-
- cmp VID_CX[bp],0 ; if no moves to do
- jz pc_v_erase_loop ; then just erase
-
- pc_v_move_loop:
- mov cx,VID_AX[bp] ; get column count
- push si ! push di ; save line pointers
- call z_movsw@ ; move one screen line
- pop di ! pop si
- add si,dx ; next source line
- add di,dx ; and next destination
- dec VID_CX[bp] ; move countdown
- jnz pc_v_move_loop
-
- pc_v_erase_loop:
- cmp VID_DX[bp], 0
- jz pc_v_scroll_exit
- pc_v_erase_loop1:
- mov cx,VID_AX[bp] ; get column count
- mov al,' ' ; erase to a blank
- mov ah,VID_BH[bp] ; pick up the attribute
- push dx ! push di
- call erase_pc@ ; erase one line
- pop di ! pop dx
- add di,dx ; next line to erase
- dec VID_DX[bp] ; erase countdown
- jnz pc_v_erase_loop1
-
- pc_v_scroll_exit:
- pop VID_DX[bp]
- pop VID_CX[bp]
- ret
- eject
-
- pc_video_count:
- ;--------------
- ; calculate move, erase and column counts
- ; exit: VID_DX[bp] = erase count
- ; VID_CX[bp] = move count
- ; VID_AX[bp] = column count
- ; - or -
- ; cf set on illegal box
-
- mov al,VID_DH[bp] ; bottom row
- sub al,VID_CH[bp] ; minus top row
- jc pc_count_exit ; if negative, forget it
-
- cbw ! inc ax ; ax = # of rows in box
- mov dx,ax ; dx = default erase count
- sub cx,cx ; default move count = 0
- sub al,VID_AL[bp] ; subtract lines to scroll
- jbe pc_count_erase ; if too much, just erase
- cmp VID_AL[bp],0 ; if al = 0, just erase
- jz pc_count_erase
-
- mov cx,ax ; cx = move count
- sub dx,ax ; dx = erase count
- pc_count_erase:
- mov al,VID_DL[bp] ; right column
- sub al,VID_CL[bp] ; minus left column
- jc pc_count_exit ; if negative, forget it
-
- cbw ! inc ax ; ax = column count
- mov VID_DX[bp],dx ; save the erase count
- mov VID_CX[bp],cx ; the move count and
- mov VID_AX[bp],ax ; column count in the stack
- clc ; all is well
- pc_count_exit:
- ret
-
-
-
- pc_video_ret:
- ret
-
-
- v_i_read: ; 8 get attr/char at cursor
- ;--------
- ; Entry: VID_BH = page number (ignored by us)
- ; Exit: VID_AL = character read
- ; VID_AH = attribute read (undefined if graphics)
-
- call update_vs_cursor_from_ros@
- mov dx,VS_CURSOR
- call get_char_attr ; call into common routine
- jmps ret_char_attr
-
- get_char_attr: ; entry point from subfunction 14
- ; to get current attribute
- call point_cursor@ ; di -> cursor dest
- test VS_MODE,MATCH_BIT ; if matched then
- jnz pc_v_read_image ; get it from the image
- mov si,di ; for lodsw
- call get_crt_c@ ; with sync'ing for color
- jmps ret_char_attr
- pc_v_read_image:
- push es
- mov es,VS_VC_SEG
- mov ax,es:[di] ; no hurry here
- pop es
- ret_char_attr:
- mov VID_AX[bp],ax
- ret
-
-
-
- v_i_write_attr: ; 9 set attr/char at cursor
- ;--------------
- ; Entry: VID_BH = page number (ignored by us)
- ; VID_AL = character to write
- ; VID_BL = attribute (text)/xor flag (graphics)
- ; VID_CX = repeat count
-
- mov al,VID_AL[bp] ; get character
- mov ah,VID_BL[bp] ; get attribute
- mov cx,VID_CX[bp] ; get character count
- ; Write cx attr/chars at current cursor:
- call update_vs_cursor_from_ros@
- mov dx,VS_CURSOR
-
- pc_ch_wr_a:
- ; Entry from EGA write_string:
- ; AX = attr/char
- ; CX = count
- ; DX = cursor position
- push ax ; save attr/char
- call point_cursor@ ; di -> cursor dest
- pop ax ; restor attr/char
- test VS_MODE,MATCH_BIT ; if full screen top
- jz pc_v_write_full_a ; then skip
-
- ; This is a little redundant but it's much better than
- ; the old way of updating the screen every character!
-
- pc_v_write_image_a:
- push es
- push cx
- mov cx,ax ; save char in cx
- call point_cursor@
- mov es,VS_VC_SEG ; go to the vc image
- mov es:[di],cx ; store char and attribute
-
- ; Now update screen if character belongs:
-
- mov es,vc_map_seg$ ; for ownership check
- add ax,VS_CORRECT
- xchg ax,si ; save for map check
- call in_window@ ; is char in window?
- mov ax,cx ; ax = character + attrib
- jc pc_v_image_bump_a ; skip if not
-
- mov di,si
- shl di,1 ; back to screen coords
- call put_if_ours@ ; print it if we own it
- pc_v_image_bump_a:
- inc dl ; advance cursor
- cmp dl,VS_WIDTH ; if not wrapping around
- jb pc_v_image_next ; then do next char
-
- mov dl,0
- inc dh ; next row
- pc_v_image_next_a:
- pop cx
- pop es
- loop pc_v_write_image
- ret
-
- pc_v_write_full_a:
- jmp put_crt_s@ ; go right to physical
-
- eject
-
- v_i_write_char@: ; 10 set char @ cur
- ;---------------
- ; Entry: VID_BH = page number (ignored by us)
- ; VID_AL = character to write
- ; VID_CX = repeat count
- ;
- ; Note: attributes are not modified
-
- mov al,VID_AL[bp] ; recover character
- mov cx,VID_CX[bp] ; repeat count
- ; Write cx attr/chars at current cursor:
- push ax ; save attr/char
- call update_vs_cursor_from_ros@
- mov dx,VS_CURSOR
- call point_cursor@ ; di -> cursor dest
- pop ax ; restor attr/char
- test VS_MODE,MATCH_BIT ; if full screen top
- jz pc_v_write_full ; then skip
-
- ; This is a little redundant but it's much better than
- ; the old way of updating the screen every character!
-
- pc_v_write_image:
- push es
- push cx
- mov cx,ax ; save char in cx
- call point_cursor@
- mov es,VS_VC_SEG ; go to the vc image
- mov es:[di],cl ; store char, and...
- mov cx,es:[di] ; get screen attribute
-
- ; Now update screen if character belongs:
-
- mov es,vc_map_seg$ ; for ownership check
- add ax,VS_CORRECT
- xchg ax,si ; save for map check
- call in_window@ ; is char in window?
- mov ax,cx ; ax = character + attrib
- jc pc_v_image_bump ; skip if not
-
- mov di,si
- shl di,1 ; back to screen coords
- call put_if_ours@ ; print it if we own it
- pc_v_image_bump:
- inc dl ; advance cursor
- cmp dl,VS_WIDTH ; if not wrapping around
- jb pc_v_image_next ; then do next char
-
- mov dl,0
- inc dh ; next row
- pc_v_image_next:
- pop cx
- pop es
- loop pc_v_write_image
- ret
-
- pc_v_write_full:
- mov dx,ax ; save char.
- mov si,di ; dest. to source
- call get_crt_c@ ; get char + attr di,bx,cx,dx ok
- ; This bit is ok for function A, where we're only writing a character, but for
- ; function 9, this screw up the passed-in attribute.
- mov al,dl ; add in new char
- jmp put_crt_s@ ; go right to physical
-
-
-
- v_i_set_color: ; 11 pallette / border control
- ;-------------
- ; Entry: VID_BH = color ID to set
- ; VID_BL = color value to set
-
- mov dl,VS_NUMBER
- cmp top_screen$,dl
- jne v_i3_ret
- push bx ; save vs_
- mov bx,VID_BX[bp]
- mov ah,11 ; set color palette func.
- call int10_entry@ ; and hit up ROS
- pop bx
-
- push ds
- mov ax,PC_SEGMENT
- mov ds,ax
- mov al,crt_pallette_40
- pop ds
-
- mov VS_COLORSEL,al ; save it in the screen struct.
- v_i3_ret:
- ret
-
- eject
-
-
- v_i_write_tty: ; 14 write char stream as a tty
- ;-------------
- ; Entry: VID_AL = character to write
- ; VID_BL = color in graphics mode
-
- mov cl,VID_AL[bp]
- call update_vs_cursor_from_ros@
- mov dx,VS_CURSOR
- cmp cl,BS ; backspace?
- jne pc_not_bs
- jmp vc_out_bs@
-
- pc_not_bs:
- cmp cl,CR ; cr?
- jne pc_not_cr
- jmp vc_out_cr@
-
- pc_not_cr:
- cmp cl,LF ; lf
- jne pc_not_lf
- jmp vc_out_lf@
-
- pc_not_lf:
- cmp cl,BEL ; bell?
- jne pc_not_bell
- jmp vc_out_bel@
-
- pc_not_bell:
- push cx ; save character
- call get_char_attr ; find attr on current char
- pop cx
- push word ptr VS_ATTRIB ; save default
- mov VS_ATTRIB,ah ; temp change attribute
- call vc_out@
- pop word ptr VS_ATTRIB
- ret
-
-
-
- v_i_gmode: ; 15 current video state
- ;---------
- ; Exit: VID_AL = current video mode (see v_i_smode:)
- ; VID_AH = # of columns per line
- ; VID_BH = current screen page (always 0 in CDOS)
-
- mov al,VS_SCREEN_MODE ; get current ROS video mode
- mov ah,VS_WIDTH ; get screen width (40 / 80 cols)
- mov VID_AX[bp],ax
- mov VID_BH[bp],0 ; always in page 0
- ret
-
- v_i_set_pal_reg: ; 16 EGA set pallette registers
- ;---------------
-
- test video$,EGA+VGA ; EGA or VGA ?
- jmpz pc_video_ret ; return if neither mode
- push es ;******
- push bx ; save vs_ for mx release
- lea di,VS_PALLETTE ; get pallette save area
- mov al,VID_AL[bp]
- mov bx,VID_BX[bp]
- mov dx,VID_DX[bp]
- mov es,VID_ES[bp]
- mov ah,16 ; function number
- cmp al,0
- jnz not_indiv_reg
-
- push bx
- sub bh,bh
- add di,bx
- pop bx
- set_1:
- mov [di],bh ; set value
- jmps to_ros10
-
- not_indiv_reg:
- cmp al,1
- jnz not_over_reg
- add di,16 ; 17th entry
- jmps set_1
-
- not_over_reg:
- cmp al,2
- jnz toggle_blink
-
- mov si,dx
- mov cx,17 ; count = 16 pall. + overscan
- push ds ! push es
- pop ds ! pop es ; switch segs
- rep movsb ; save in VS_
- push es ! push ds
- pop es ! pop ds ; restore segs
- jmps to_ros10
-
- toggle_blink: ; toggle the blink bit for ega
- cmp al,3
- jnz to_ros10 ; not one of the functions we emulate
- pop cx ; get VS->
- push cx ; and resave for exit
- xchg cx,bx ; get VS-> to BX
- push cx
- mov ch,VS_MODE1
- and ch,not BLINK_TOGGLE ; mask out blink bit
- and cl,BLINK_TOGGLE ; isolate
- or cl,ch ; mash together
- mov VS_MODE1,cl ; save blink toggle state
- pop cx
- xchg cx,bx ; retore BL and go to ROS
-
- to_ros10:
- pop cx ; get VS->
- push cx ; and resave for exit
- xchg bx,cx ; BX = VS->
- mov bl,VS_NUMBER
- cmp top_screen$,bl
- jne v_i2_ret ; do not go to ROS if background VC
- xchg bx,cx ; restore bx
- mov cx,VID_CX[bp]
- call int10_entry@ ; call ROS
- v_i2_ret:
- pop bx ; restore vs_ for mx release
- pop es ;********
- ret
-
- v_i_char_gen: ; 17 EGA character generator
- ;------------
-
- test video$,EGA+VGA ; EGA VGA present?
- jmpz pc_video_ret
- push es ;*****
- push bx ; save vs_ for mx release
- mov al,VID_AL[bp]
- cmp al,14h ; 16x8 (VGA) font?
- je v_i_char_gen0 ; back to normal on VGA
- cmp al,11h ; 14x8 (ECD/mono) font?
- jne v_i_char_gen1 ; no, must be 8x8 (43/50) font
- v_i_char_gen0:
- and VS_MODE1,not LINE_43_MODE ; reset 43 line mode bit
- cmp VS_SCREEN_MODE,04
- jb not_gra3
- cmp VS_SCREEN_MODE,07 ; if graphics mode
- jne v_i_char_gen1 ; leave graphic_bits
- not_gra3:
- mov cl,VS_BIT
- not cl
- and graphic_bits$,cl ; else mask us out
-
- test VS_MODE1, SUSPEND_STATE ; examine original suspend VS_
- push bx
- pushf
- mov bx,rlr$
- and P_SFLAG[bx],not PSF_SUSPEND ; clear suspend state
- popf
- jz v_i_char_gen0a
- or P_SFLAG[bx],PSF_SUSPEND ; and restore to original value
- v_i_char_gen0a:
- pop bx
- and VS_MODE1, not SUSPEND_STATE ; clear the copy
-
- v_i_char_gen1:
- cmp al,12h
- jne v_i_char_gen3
- mov al,VS_BIT
- not al ; if anybody else is in
- test graphic_bits$,al ; anybody in graphics mode
- jz v_i_char_gen2
- mov VS_MX,0 ; release semaphore
- push bp
- call gr_abort@ ; suspend running process
- pop bp
- call get_mx@
- v_i_char_gen2:
- or VS_MODE1,LINE_43_MODE ; set 43 line mode bit
- mov cl,VS_BIT ; 43 line is incompatible
- or graphic_bits$,cl ; w/ screen switching - set as graphics
- and VS_MODE1, not SUSPEND_STATE ; clear copy of suspend state
- push bx
- mov bx,rlr$ ; look at the PD
- test P_SFLAG[bx],PSF_SUSPEND ; examine the original state
- pushf
- or P_SFLAG[bx],PSF_SUSPEND ; now set it
- popf
- pop bx
- jz v_i_char_gen2a
- or VS_MODE1, SUSPEND_STATE ; save original suspend in VS_
- v_i_char_gen2a:
- mov al,VID_AL[bp] ; reload AL
- v_i_char_gen3:
- push bp
- mov bx,VID_BX[bp]
- mov cx,VID_CX[bp]
- mov dx,VID_DX[bp]
- mov es,VID_ES[bp]
- mov bp,VID_BP[bp]
- mov ah,17 ; function number
- call int10_entry@ ; call ROS
- mov ax,bp ; save temporary
- pop bp
- mov VID_CX[bp],cx
- mov VID_DX[bp],dx
- mov VID_ES[bp],es
- mov VID_BP[bp],ax ; BP on return
- pop bx ; restore vs_ for mx release
- pop es ;********
- ret
-
- v_i_alt_select: ; 18 EGA alternate select
- ;--------------
- test video$,EGA+VGA ; EGA/VGA present?
- jmpz pc_video_ret
- push es ;********
- push bx ; save vs_ for mx release
- mov ah,18 ; function number
- mov bx,VID_BX[bp] ; sub sub function
- mov cx,VID_CX[bp]
- mov es,VID_ES[bp]
- mov dx,VID_DX[bp]
- mov al,VID_AL[bp]
- call int10_entry@ ; call ROS
- mov VID_BX[bp],bx ; mode and memory
- mov VID_CX[bp],cx ; feat/switch
- mov VID_AX[bp],ax
- pop bx ; restore vs_ for mx release
- pop es ;*************
-
- ret
-
- v_i_write_string: ; 19 EGA write string
- ;----------------
- ; Entry: VID_ES:VID_BP -> string to display
- ; VID_CX = character count
- ; VID_DH, VID_DL = starting cursor address
- ; VID_BH (ignored by CDOS)
- ; VID_BL = attribute if VID_AL = 0 or 1
- ; VID_AL = 0-3:
- ; 0: ES:BP -> chars only, cursor not moved
- ; 1: ES:BP -> chars only, cursor is moved
- ; 2: ES:BP -> chars/attribs, cursor not moved
- ; 3: ES:BP -> chars/attribs, cursor is moved
- ; Note: AL = 2, 3 are not supported in graphics mode
- ; CR, LF, BS, BEL are interpreted rather than displayed.
-
- call update_vs_cursor_from_ros@
- mov ax,VID_AX[bp] ; get sub func. #
- cmp al,3 ; is it legal ??
- ja v_i_write_string1 ; no ignore it
- cmp al,0
- je attr_9 ; don't move cursor
- cmp al,1
- je attr_e ; move cursor
- cmp al,2
- je ch_attr_9 ; don't move cursor
- ; cmp al,3
- ; je ch_attr_e ; must be...
- jmp ch_attr_e ; move cursor
- v_i_write_string1:
- ret
-
-
- attr_9:
- ; String is char only..no cursor movement:
-
- mov cx,VID_CX[bp]
- mov si,VID_BP[bp]
- mov dx,VID_DX[bp] ; get start position
- push VS_CURSOR
- a9_lp:
- push ds
- mov ds,VID_ES[bp]
- lodsb
- pop ds
-
- mov ah,VID_BL[bp]
-
- push si
- push cx
- push dx ; save position
- mov cx,1
- call pc_ch_wr_a ; will release MX
- pop dx
- inc dx ; move to next position
- pop cx
- pop si
-
- loop a9_lp
- pop dx ; restore old VS_CURSOR
- call point_cursor@
- mov VS_OFFSET,ax
- mov VS_CURSOR,dx
- mov ax,dx
- jmp poke_ros_cursor@
- ; ret
-
-
- ch_attr_9:
- ; String is char/attr...no cursor movement:
- mov cx,VID_CX[bp]
- mov si,VID_BP[bp]
- mov dx,VID_DX[bp] ; get start position
- push VS_CURSOR
- cha9_lp:
- push ds
- mov ds,VID_ES[bp]
- lodsw
- pop ds
-
- push si
- push cx
- push dx ; save position
- mov cx,1
- call pc_ch_wr_a ; will release MX
- pop dx
- inc dx ; next position
- pop cx
- pop si
-
- loop cha9_lp
- pop dx ; restore old VS_CURSOR
- call point_cursor@
- mov VS_OFFSET,ax
- mov VS_CURSOR,dx
- mov ax,dx
- jmp poke_ros_cursor@
- ; ret
-
-
- attr_e:
- ; String is char only...move cursor:
- mov cx,VID_CX[bp]
- mov si,VID_BP[bp]
- mov dx,VID_DX[bp] ; get start cursor position
- call point_cursor@
- mov VS_OFFSET,ax
- mov VS_CURSOR,dx ; update position
- ae_lp:
- push ds
- mov ds,VID_ES[bp]
- lodsb
- pop ds
-
- push si
- push cx
- push dx
- mov cl,al
- mov al,VID_BL[bp]
- mov VS_ATTRIB,al
- call tty_branch
- pop dx
- inc dx ; next location
- pop cx
- pop si
- loop ae_lp
- call point_cursor@
- mov VS_OFFSET,ax
- mov VS_CURSOR,dx ; update position
- mov ax,dx
- jmp poke_ros_cursor@
- ; ret
-
-
- ch_attr_e:
- ; String is char/attr...move cursor:
-
- mov cx,VID_CX[bp]
- mov si,VID_BP[bp]
- mov dx,VID_DX[bp] ; get start cursor position
- call point_cursor@
- mov VS_OFFSET,ax
- mov VS_CURSOR,dx ; update position
- chae_lp:
- push ds
- mov ds,VID_ES[bp]
- lodsw
- pop ds
- mov VS_ATTRIB,ah
-
- push si
- push cx
- push dx
- mov cl,al
- call tty_branch
- pop dx
- inc dx ; next location
- pop cx
- pop si
-
- loop chae_lp
- call point_cursor@
- mov VS_OFFSET,ax
- mov VS_CURSOR,dx ; update position
- mov ax,dx
- jmp poke_ros_cursor@
- ; ret
-
-
- tty_branch:
- cmp cl,' '
- jb t_ctl
- jmp vc_out@
- t_ctl:
- cmp cl,BS
- jne t_no_bs
- jmp vc_out_bs@
- t_no_bs:
- cmp cl,CR
- jne t_no_cr
- jmp vc_out_cr@
- t_no_cr:
- cmp cl,LF
- jne t_no_lf
- jmp vc_out_lf@
- t_no_lf:
- cmp cl,BEL
- jne t_no_bl
- jmp vc_out_bel@
- t_no_bl:
- jmp vc_out@
- ret
-
-
- v_i_notimp:
- ;----------
- ret ; ROS function not implemented
-
-
-
- poke_ros_cursor@:
- ;----------------
- ; Routine to update the cursor posn word in the ros data area:
- ; Entry: AX = cursor...high = row, low = col
- ; BX = VS_
- ; Exit: all preserved
- pushf
- cli
- push dx
- mov dl,VS_NUMBER
- cmp top_screen$,dl
- pop dx
- jne prc1
-
- push ds
- mov ds,ros_seg ; assume active page zero
- mov cursor_posn_40,ax
- pop ds
- prc1:
- popf
- ret
-
- update_vs_cursor_from_ros@:
- ;--------------------------
- ; Routine to read the cursor posn word in the ros data area:
- ; Entry: DS:BX = VS_
- ; Exit:
- ; preserve all regs
- ;
- pushf
- cli
- push dx
- mov dl,VS_NUMBER ; if we aren't the top screen
- cmp top_screen$,dl ; don't use the ros
- jne update_vs2
- push es
- mov es,ros_seg
- mov dx,es:cursor_posn_40 ; assume page zero
- cmp dx,VS_CURSOR
- je update_vs1
- push ax
- push di
- call point_cursor@
- mov VS_OFFSET,ax
- mov VS_CURSOR,dx
- pop di
- pop ax
- update_vs1:
- pop es
- update_vs2:
- pop dx
- popf
- ret
-
-
- ros_seg dw PC_SEGMENT
-
- end
-
- ; END OF PCVIDEO.A86
-