;************************************************************************ ;* Copyright 1999, Caldera Thin Clients, Inc. * ;* This software is licenced under the GNU Public License. * ;* Please see LICENSE.TXT for further information. * ;* * ;* Historical Copyright * ;* * ;* * ;* * ;* Copyright (c) 1987, Digital Research, Inc. All Rights Reserved. * ;* The Software Code contained in this listing is proprietary to * ;* Digital Research, Inc., Monterey, California and is covered by U.S. * ;* and other copyright protection. Unauthorized copying, adaptation, * ;* distribution, use or display is prohibited and may be subject to * ;* civil and criminal penalties. Disclosure to others is prohibited. * ;* For the terms and conditions of software code use refer to the * ;* appropriate Digital Research License Agreement. * ;* * ;************************************************************************ EJECT ;Hist ; cseg public dygedx_tran public vec_len public GET_DS public ABLINE public HABLINE public DIS_CUR public HIDE_CUR public MOV_CUR public SMUL_DIV public CLC_FLIT public XFM_CRFM public XFM_UDFL public VEX_BUTV public VEX_MOTV public VEX_CURV public RECTFILL public EGA_KLUG public box_ega_init public box_plane_enable ega_seq_add equ 3c4h ;the ega sequencer add reg ega_seq_data equ 3c5h ;the ega sequencer data reg ega_wmapmask_reg equ 2 ;the write plane mask reg ega_graphic_add equ 3ceh ;the ega graphics add reg ega_graphic_data equ 3cfh ega_setres_reg equ 0 ;the ega plane set reset values ega_ensetres_reg equ 1 ;the ega plane set reset enable bits ega_datarot_reg equ 3 ;the ega data rotate register ega_rmapmask_reg equ 4 ;the ega plane read mask ega_mode_reg equ 5 ;the ega data source mode register ega_bitmask_reg equ 8 ;the ega bit mask register GET_DS: mov ax,ds ret ; ;****************************************************************************** ; ; PROCEDURE: RECTFIL Fill Rectangle ; ; Inputs: X1,Y1 = upper left ; X2,Y2 = lower right ; ;****************************************************************************** ; RECTFILL: mov ax, CLIP ; is clipping on? and ax, ax jnz rectfill_clip_1 jmp BOX_FILL ; goto horizontal line draw routine rectfill_clip_1: mov ax, XMN_CLIP mov bx, X1 mov cx, X2 cmp bx, ax ; is x1 < xmn_clip jnl rectfill_clip_3 cmp cx, ax ; is x2 >= xmn_clip jl rectfill_clip_2 mov X1, ax rectfill_clip_3: mov ax, XMX_CLIP cmp cx, ax ; is x2 > xmx_clip jle rectfill_clip_4 cmp bx, ax ; is x1 <= xmx_clip jg rectfill_clip_2 mov X2, ax jmps rectfill_clip_4 rectfill_clip_2: ret ; if x2 not > xmn_clip exit rectfill_clip_4: mov ax, YMN_CLIP mov bx, Y1 mov cx, Y2 cmp bx, ax ; is y1 < ymn_clip jnl rectfill_clip_5 cmp cx, ax ; is y2 >= ymn_clip jl rectfill_clip_2 mov Y1, ax rectfill_clip_5: mov ax, YMX_CLIP cmp cx, ax ; is y2 > ymx_clip jle rectfill_clip_6 cmp bx, ax ; is y1 <= ymx_clip jg rectfill_clip_2 mov Y2, ax rectfill_clip_6: jmps BOX_FILL ;****************************************************************************** ; BOX_FILL ; Fill a rectangular area with pattern ; ; Entry X1,Y1 = upper left corner inclusive ; X2,Y2 = lower right corner inclusive ; ;****************************************************************************** BOX_FILL: mov bx, X1 and bx, 0fff0h ; make sure it lines up on a word boundary mov ax, Y1 ; find the physical address call concat ; di = display memory pointer if byte_swap and di, 0fffeh ; make sure it points to low byte endif mov ax, graph_plane mov es, ax ; init the segment register BOX_FILL_LINE: mov ax, 0fh mov dx, X1 mov bx, dx ; save X1 for later and bx, ax ; get the left mask word shl bx, 1 ; index by words mov bx, word_mask_table[bx] xchg bh,bl ; account for byte swap mov left_word_mask, bx mov bp, X2 inc bp ; point one past the right most pixel mov bx, bp ; save X2 + 1 for later and bx, ax shl bx, 1 ; index by words mov bx, word_mask_table[bx] not bx ; make it the right one xchg bh,bl mov right_word_mask,bx mov cl,4 ; find the word count bp = x2 , dx = x1 shr bp, cl ; divide by four shr dx, cl sub bp, dx ; word count = x2/4 - x1/4 -1 dec bp jge box_fill_ok xor bp,bp ; make word count = 0 cmp bx, 0 ; is it left only? jz box_left_mask_only and left_word_mask, bx box_left_mask_only: mov right_word_mask,0 ; don't let the right mask do anything box_fill_ok: mov si, Y1 mov cx, Y2 ; calculate the scan count sub cx, si inc cx ; cx = scan count = delta y + 1 and si, patmsk ; get the pattern index value mov bx, patptr ; get the pattern pointer add bx, si add bx, si ; index in properly mov patcnt, si mov si, bx mov bx, WRT_MODE shl bx, 1 mov bx, box_optbl[bx] call bx ret ;******************************* ; box_tran_mode ; entry es:di = memory address ; patcnt = pattern index ; si = pattern pointer ; patmsk = current pattern max count ; bp = word count ; cx = scan line count ; dx used for pattern storage ; ;******************************* box_tran_mode: mov bx, FG_BP_1 and bl, 0fh call box_plane_enable ;enable the planes to be drawn with 1's mov bh, 0 ;don't allow any planes to use set/res mov bl, 00010000b ;set to no rotate and an or op call box_ega_init push di push si push cx push patcnt call box_plane_top pop patcnt pop cx pop si pop di mov bx, FG_BP_1 not bx and bl, 0fh call box_plane_enable mov dx, ega_graphic_add ;set up the writing mode to be applied mov al, ega_datarot_reg out dx, al mov dx, ega_graphic_data mov al, 00001000b ;set to no rotate with an and op out dx, al call box_plane_top_not ret ;******************************* ; box_invtran_mode ; entry es:di = memory address ; patcnt = pattern index ; si = pattern pointer ; patmsk = current pattern max count ; bp = word count ; cx = scan line count ; dx used for pattern storage ; ;******************************* box_invtran_mode: mov bx, FG_BP_1 and bl, 0fh call box_plane_enable ;enable the planes to be drawn with 1's mov bh, 0 ;don't allow any planes to use set/res mov bl, 00010000b ;set to no rotate and an or op call box_ega_init push di push si push cx push patcnt call box_plane_top_not pop patcnt pop cx pop si pop di mov bx, FG_BP_1 not bx and bl, 0fh call box_plane_enable mov dx, ega_graphic_add ;set up the writing mode to be applied mov al, ega_datarot_reg out dx, al mov dx, ega_graphic_data mov al, 00001000b ;set to no rotate with an and op out dx, al call box_plane_top ret ;******************************* ; box_replace_mode ; entry es:di = memory address ; patcnt = pattern index ; si = pattern pointer ; patmsk = current pattern max count ; bp = word count ; cx = scan line count ; dx used for pattern storage ; ;******************************* box_replace_mode: test NEXT_PAT, 0ffffh jnz box_replace_multi mov bl, 0fh ;enable all planes to draw call box_plane_enable mov bx, FG_BP_1 not bx xchg bh, bl and bh, 0fh ;set the planes with ix=0 to set/res mov bl, 00000000b ;set to no rotate and an replace op call box_ega_init mov dx, ega_graphic_add ;now set the planes to reset mov al, ega_setres_reg out dx, al mov dx, ega_graphic_data mov al, 0 out dx, al call box_plane_rep_top ret box_replace_multi: mov plane_loop_count, num_planes ; load up the plane count xor bh, bh ;no planes to set/res mov bl, 00000000b ;set to no rotate and an replace op call box_ega_init push patptr ; save away the pointer for user fill mov bx, 1 ;set up the mask bit for plane/color push bx box_fill_0: mov dx, ega_seq_add mov al, ega_wmapmask_reg out dx, al pop bx mov dx, ega_seq_data mov al, ss:plane_port_tbl[bx] out dx, al shl bx, 1 push bx ; save the mask push cx push si push di push patcnt call box_plane_rep_top mov bx, NEXT_PAT add patptr, bx pop patcnt pop di pop si pop cx add si, NEXT_PAT ; add in the next pattern ammount dec plane_loop_count ; is line done jnz box_fill_0 pop ax pop patptr ret ; ;******************************* ; box_xor_mode ; entry es:di = memory address ; patcnt = pattern index ; si = pattern pointer ; patmsk = current pattern max count ; bp = word count ; cx = scan line count ; dx used for pattern storage ; ;******************************* box_xor_mode: mov bl, 0fh call box_plane_enable ;enable the planes to be drawn with 1's mov bh, 0 ;don't allow any planes to use set/res mov bl, 00011000b ;set to no rotate and an or op call box_ega_init call box_plane_top ret ; ;bl = planes which may be drawn to box_plane_enable: mov dx, ega_seq_add ;enable the planes to be drawn with 1's mov al, ega_wmapmask_reg out dx, al mov dx, ega_seq_data mov al, bl out dx, al ret ; ; ;bh = planes which are set to set/res ;bl = writing mode to be applied box_ega_init: mov al, ega_ensetres_reg mov dx, ega_graphic_add out dx, al ;don't allow any planes to use set/res mov dx, ega_graphic_data mov al, bh out dx, al mov dx, ega_graphic_add ;set up the writing mode to be applied mov al, ega_datarot_reg out dx, al mov dx, ega_graphic_data mov al, bl out dx, al mov dx, ega_graphic_add ;set the ega mode reg to processor data mov al, ega_mode_reg out dx, al mov dx, ega_graphic_data if num_planes eq 2 mov al, 00010000b ;turn on odd / even mode else mov al, 00000000b endif out dx, al ret ; ; box_plane_rep_top: mov dx, ega_graphic_add ;set up the bit mask reg mov al, ega_bitmask_reg out dx, al mov dx, ega_graphic_data jmps box_plane_rep box_plane_rep_loop: add di, next_line inc si inc si ; point to next word inc patcnt ; point to next word mov ax, patmsk cmp patcnt, ax ; is the pattern index > mask jle box_plane_rep mov si, patptr ; point pattern back to top mov patcnt, 0 ; start pattern count over box_plane_rep: push di ; save the current address push cx ; save the outer loop count mov bx,[si] ; get the current pattern xchg bh,bl ; requires byte swap ; ; Left Fringe mov ax, left_word_mask out dx, al ; output the first mask byte mov al, es:[di] ; apply the left fringe mask mov es:[di], bl xchg ah,al out dx, al ; output the second mask byte inc di mov al, es:[di] mov es:[di], bh mov al, 0ffh ; now don't mask anything out dx, al inc di ; ; Inner Word Loop mov cx, bp jcxz box_plane_rep_right mov ax, bx ; use the correct pattern rep stosw ; move out the word to memory in fastest way ; ; Right Fringe box_plane_rep_right: mov ax, right_word_mask out dx, al ; output the first mask byte mov al, es:[di] ; apply the right fringe mask mov es:[di], bl xchg ah,al out dx, al ; output the second mask byte inc di mov al, es:[di] mov es:[di], bh mov al, 0ffh ; now don't mask anything out dx, al pop cx pop di dec cx jcxz box_plane_rep_done jmp box_plane_rep_loop box_plane_rep_done: ret ; ; box_plane_top: mov dx, ega_graphic_add ;set up the bit mask reg mov al, ega_bitmask_reg out dx, al mov dx, ega_graphic_data jmps box_plane box_plane_loop: add di, next_line inc si inc si ; point to next word inc patcnt ; point to next word mov ax, patmsk cmp patcnt, ax ; is the pattern index > mask jle box_plane mov si, patptr ; point pattern back to top mov patcnt, 0 ; start pattern count over box_plane: push di ; save the current address push cx ; save the outer loop count mov bx,[si] ; get the current pattern xchg bh,bl ; requires byte swap ; ; Left Fringe mov ax, left_word_mask out dx, al ; output the first mask byte mov al, es:[di] ; apply the left fringe mask mov es:[di], bl xchg ah,al out dx, al ; output the second mask byte inc di mov al, es:[di] mov es:[di], bh mov al, 0ffh ; now don't mask anything out dx, al inc di ; ; Inner Word Loop mov cx, bp jcxz box_plane_right box_plane_inner: mov al,es:[di] mov es:[di], bl inc di mov al, es:[di] mov es:[di], bh inc di loop box_plane_inner ; move out the word to memory in fastest way ; ; Right Fringe box_plane_right: mov ax, right_word_mask out dx, al ; output the first mask byte mov al, es:[di] ; apply the right fringe mask mov es:[di], bl xchg ah,al out dx, al ; output the second mask byte inc di mov al, es:[di] mov es:[di], bh mov al, 0ffh ; now don't mask anything out dx, al pop cx pop di dec cx jcxz box_plane_done jmp box_plane_loop box_plane_done: ret ; ; box_plane_top_not: mov dx, ega_graphic_add ;set up the bit mask reg mov al, ega_bitmask_reg out dx, al mov dx, ega_graphic_data jmps box_plane_not box_plane_not_loop: add di, next_line inc si inc si ; point to next word inc patcnt ; point to next word mov ax, patmsk cmp patcnt, ax ; is the pattern index > mask jle box_plane_not mov si, patptr ; point pattern back to top mov patcnt, 0 ; start pattern count over box_plane_not: push di ; save the current address push cx ; save the outer loop count mov bx,[si] ; get the current pattern not bx ; invert the pattern xchg bh,bl ; requires byte swap ; ; Left Fringe mov ax, left_word_mask out dx, al ; output the first mask byte mov al, es:[di] ; apply the left fringe mask mov es:[di], bl xchg ah,al out dx, al ; output the second mask byte inc di mov al, es:[di] mov es:[di], bh mov al, 0ffh ; now don't mask anything out dx, al inc di ; ; Inner Word Loop mov cx, bp jcxz box_plane_not_right box_plane_not_inner: mov al,es:[di] mov es:[di], bl inc di mov al, es:[di] mov es:[di], bh inc di loop box_plane_not_inner ; move out the word to memory in fastest way ; ; Right Fringe box_plane_not_right: mov ax, right_word_mask out dx, al ; output the first mask byte mov al, es:[di] ; apply the right fringe mask mov es:[di], bl xchg ah,al out dx, al ; output the second mask byte inc di mov al, es:[di] mov es:[di], bh mov al, 0ffh ; now don't mask anything out dx, al pop cx pop di dec cx jcxz box_plane_not_done jmp box_plane_not_loop box_plane_not_done: ret ;****************************************************************************** ; ; VEX_BUTV ; ; Exchange button change vector ; ; Entry contrl(7),contrl(8) = pointer to user defined routine ; ; Exit contrl(9),contrl(10) = old pointer to button routine ; ; ;****************************************************************************** VEX_BUTV: mov si, offset userbut call exchg_vector ret exchg_vector: pushf cli push es push ds mov ax, seg contrl mov ds, ax les di,contrl_ptr mov ax,[si] ;get the offset mov es:word ptr 18[di],ax mov ax,2[si] mov es:word ptr 20[di],ax ;get the segment mov ax,contrl+14 mov [si],ax mov ax,contrl+16 mov 2[si],ax ;load the new offset/segment pop ds pop es popf ret ;****************************************************************************** ; ; VEX_MOTV ; ; Exchange coordinate change vector ; ; Entry contrl(7),contrl(8) = pointer to user defined routine ; ; Exit contrl(9),contrl(10) = old pointer to button routine ; ; ;****************************************************************************** VEX_MOTV: mov si, offset usermot call exchg_vector ret ;****************************************************************************** ; ; VEX_CURV ; ; Exchange cursor draw vector ; ; Entry contrl(7),contrl(8) = pointer to user defined routine ; ; Exit contrl(9),contrl(10) = old pointer to button routine ; ; ;****************************************************************************** VEX_CURV: mov si, offset usercur call exchg_vector ret ; ;*********************************************************************** ;XFM_CRFM ; Transform the user defined cursor form to device spec format ; ; Entry CONTRL[7] ; CONTRL[8] = long pointer to input data ; ; Exit ; ; ;*********************************************************************** XFM_CRFM: push ds ;make sure es=ds pop es mov di,offset mxhot ;point at dest mov si,offset intin mov cx,37 rep movsw ;copy the data mov bx, mous_ci_mask ; get the color index val shl bx,1 mov ax, MAP_COL[bx] mov bx, mous_ci_data shl bx,1 mov bx, MAP_COL[bx] mov cx, 4 xfm_crlp: ror al,1 rcr ah,1 ror bl,1 rcr ah,1 loop xfm_crlp mov mous_col_map,ah ret eject ;*********************************************************************** ;XFM_UDFL ; Transform the user defined fill pattern to device spec format ; ; Entry INTIN[0] - INTIN[15] = fill pattern ; ; ;*********************************************************************** XFM_UDFL: mov dx, CONTRL+6 ;get the intin count mov cx, dx ; save away the count xor al, al xfm_udfl_size_ck: inc al sub dx, 16 jc xfm_udfl_bad jz xfm_udfl_size jmps xfm_udfl_size_ck xfm_udfl_size: cmp al, 1 ; 1 is always ok jz xfm_udfl_ok cmp al, num_planes jz xfm_udfl_ok1 xfm_udfl_bad: ;must be integral of 16 mov ax, -1 ret xfm_udfl_ok: mov udpt_np, 0 jmps xfm_udfl_ok2 xfm_udfl_ok1: mov udpt_np, 32 xfm_udfl_ok2: mov dx, cx push ds ;make sure es=ds pop es mov di,offset ud_patrn ;point at dest mov si,offset INTIN mov cx, dx rep movsw ;copy the data mov si,offset ud_patrn if (msb_first and byte_swap) mov cx, dx ;swap 16 words xfm_udfl_loop: mov ax,[si] xchg ah,al mov [si],ax inc si inc si loop xfm_udfl_loop ret endif if (msb_first and not byte_swap) ret endif if (not msb_first and not byte_swap) mov cx, dx xfm_udfl_loop: push cx mov ax,[si] mov cx,16 xfm_udfl_ilp: rol ax,1 rcr bx,1 loop xfm_udfl_ilp mov [si],bx pop cx inc si inc si loop xfm_udfl_loop ret endif eject ;*********************************************************************** ;CLC_FLIT ; Find the Intersection points for each raster line y ; ; Entry CONTRL[1] = vectex count ; PTSIN[] = verticies ; y = scan line to intersect ; fill_int = 0 ; ; Exit fill_int = count of intersections ; INTIN = x values of intersections ; ;*********************************************************************** CLC_FLIT: mov cx,CONTRL+2 ; get points count mov si,offset PTSIN mov di,offset INTIN flit_lp: push cx mov cx, 6[si] ; test ch, 80h ; look at the flag if not a required edge ; jnz no_fill_int mov dx, 2[si] ; and dx, 7fffh ; get rid of flag if any sub cx, dx ; get delta y jz fillit_zero ; goto next x,y if deltay = 0 mov bx,Y1 mov ax,bx sub ax, dx ; delta y1 sub bx, 6[si] ; delta y2 mov dx,ax xor dx,bx ; check if signs = jns fillit_done mov dx, 4[si] sub dx, [si] ; dx = delta x add dx,dx ; 2 * delta x imul dx ; ax = dx * 2 * deltay1 idiv cx ; ax = dx * 2 * deltay1 / deltay and ax,ax ; test if negative js int_neg inc ax shr ax,1 load_fill_int: add ax, [si] ; add in x1 mov [di],ax inc di inc di inc fill_int ; increment fill count and buffer pointer no_fill_int: inc si inc si inc si inc si ; increment ptsin ptr pop cx loop flit_lp jmps sort_fill_int ret fillit_zero: ; or 6[si], 8000h ; set the flag for done with edge jmps no_fill_int fillit_done: and ax, ax jns no_fill_int ; or 6[si], 8000h jmps no_fill_int int_neg: neg ax inc ax shr ax,1 neg ax jmps load_fill_int sort_fill_int: mov cx, fill_int cmp cx, 2 jz fast_fill_int ; if 2 then simple sort and draw jl fill_no_int ; if less than 2 then do nothing dec cx ; make it 0 based jmp full_fill_sort fill_no_int: ret fast_fill_int: mov ax, INTIN ; get the first x mov bx, INTIN+2 cmp ax, bx jle fast_fill_int_1 xchg ax, bx ; if x1 > x2 exchange them fast_fill_int_1: mov X1, ax mov X2, bx call HLINE_CLIP ret full_fill_sort: mov dx, cx mov di, offset INTIN full_fill_sort_outlp: push cx ; save the full count mov si, di mov ax, word ptr 0[si] ; get the initial lower word full_fill_sort_inlp: mov bx, word ptr 2[si] cmp ax, bx ; is ax <= bx jle full_fill_sort_inlp_1 mov word ptr 0[si], bx ; if ax > bx then exchange mov word ptr 2[si], ax mov bx, ax ; set up for next word full_fill_sort_inlp_1: mov ax, bx ; already have lower word inc si inc si ; point upwards loop full_fill_sort_inlp pop cx dec dx jnz full_fill_sort_outlp mov cx, fill_int shr cx, 1 ; make count of word pairs full_fill_drawlp: mov ax, [di] mov bx, 2[di] mov X1, ax mov X2, bx push di push cx call HLINE_CLIP pop cx pop di add di,4 ; point to the next pair loop full_fill_drawlp ret HLINE_CLIP: mov ax, CLIP ; is clipping on? and ax, ax jnz hline_clip_1 jmp HABLINE ; goto horizontal line draw routine hline_clip_1: mov ax, XMN_CLIP mov bx, X1 mov cx, X2 cmp bx, ax ; is x1 < xmn_clip jnl hline_clip_3 cmp cx, ax ; is x2 >= xmn_clip jl hline_clip_2 mov X1, ax hline_clip_3: mov ax, XMX_CLIP cmp cx, ax ; is x2 > xmx_clip jle hline_clip_4 cmp bx, ax ; is x1 <= xmx_clip jg hline_clip_2 mov X2, ax hline_clip_4: jmp HABLINE hline_clip_2: ret ; if x2 not > xmn_clip exit eject