home *** CD-ROM | disk | FTP | other *** search
- ;
- ;
- ; draw_line (int x1, int y1, int x2, int y2, int color)
- ;
- PUBLIC _draw_line
-
- _draw_line proc far
-
- ; FAR PARMS
- x1 equ word ptr [bp+6]
- y1 equ word ptr [bp+8]
- x2 equ word ptr [bp+10]
- y2 equ word ptr [bp+12]
- color equ word ptr [bp+14]
-
- ; LOCAL STORAGE
- deltax_nondiag equ word ptr [bp-2]
- deltay_nondiag equ word ptr [bp-4]
- deltax equ word ptr [bp-6]
- deltay equ word ptr [bp-8]
- d equ word ptr [bp-10]
- dirx equ word ptr [bp-12]
- diry equ word ptr [bp-14]
- nondiag_inc equ word ptr [bp-16]
- swap equ word ptr [bp-18]
- diag_inc equ word ptr [bp-20]
- llength equ word ptr [bp-22]
-
-
- push bp
- mov bp,sp
- sub sp,24
- push si
- push di
-
- ;---------------------------------------------------------------------
- ; Hopefully we can save some time by always drawing in a left
- ; to right manner, so lets rearrange the end points so that
- ; x1 is always <= x2
- ;---------------------------------------------------------------------
- mov ax,x1
- cmp ax,x2
- jle no_swap_needed
- mov bx,x2
- mov x1,bx
- mov x2,ax
- mov ax,y1
- mov bx,y2
- mov y1,bx
- mov y2,ax
- no_swap_needed:
- ;---------------------------------------------------------------------
- ; The first step is to prepare the video card for SET/REST
- ; operations. This is done so that we aren't doing it with
- ; each pixel, which is expensive.
- ;---------------------------------------------------------------------
-
- push es
- mov es,_curr_vid_seg
-
- ;
- ; figure out address of this pixel
- ;
- mov cx,x1 ;set X coordinate
- mov bx,y1 ;set Y value
- call emapxy ;di = offset
-
- mov dx,GRAPHIC12
- ;
- ; enable set/reset mode
- ; then load reset register
- ;
- mov al,SETRESET ;set SET/RESET register
- out dx,al
- inc dx ;now data register
-
- mov ax,color ;what color was requested?
- out dx,al ;Set the active (set) bits
- ; that loaded the color into the SETRESET reg.
- dec dx ;now back to control register
-
- mov al,ENABLERESET ;defines which planes will be modified
- ; from the SETRESET register
- out dx,al ;
- inc dx ;and back to data register
-
- mov al,0ffh ;work with all 4 planes
- out dx,al ;0ffh should activate all planes
- dec dx ;back to control
- ;
- ; now we are ready to put the color out there
- ;
- ;
- ; build a 1-bit mask for the requested pixel
- ;
- mov cx,x1 ;get the offset within the scan line
- and cx,07h ;mod 8 - give bit within byte
- mov bl,80h ;a high bit in bl
- shr bl,cl ;slide it down to make the mask
- ;
- ;
- ;---------------------------------------------------------------------
- ; The following may look rather stilted or bereft of register useage.
- ; The reason is that it is very nearly the codr generated by the
- ; compiler, with a big dollup of video code in the middle to actually
- ; plot the pixel.
- ;---------------------------------------------------------------------
- ; Now we figure out what pixels will be modified
- ;---------------------------------------------------------------------
- ;
- ; deltax = x2 - x1;
- mov ax,x2
- sub ax,x1
- mov deltax,ax
- ; deltay = y2 - y1;
- mov ax,y2
- sub ax,y1
- mov deltay,ax
- ;
- ; /* is end to right or left of start? */
- ; dirx = 1;
- mov dirx,1
- ; if (deltax < 0) {
- cmp deltax,0
- jge deltax_greater_0
- ; deltax = -deltax;
- mov ax,deltax
- neg ax
- mov deltax,ax
- ; dirx = -1;
- mov dirx,-1
- ; }
- ;
- ; /* determine drawing driection for y */
- ; diry = 1;
-
- deltax_greater_0:
- mov diry,1
- ; if (deltay < 0) {
- cmp deltay,0
- jge deltay_greater_0
- ; deltay = -deltay;
- mov ax,deltay
- neg ax
- mov deltay,ax
- ; diry = -1;
- mov diry,-1
- ; }
- ;
- ; /* id octant containing end point */
- ; if (deltax < deltay) {
- deltay_greater_0:
- mov ax,deltay
- cmp deltax,ax
- jge deltax_greater_deltay
- ; llength= deltay
- mov llength,ax
- ; swap = deltax;
- mov ax,deltax
- mov swap,ax
- ; deltax = deltay;
- mov ax,deltay
- mov deltax,ax
- ; deltay = swap;
- mov ax,swap
- mov deltay,ax
- ; deltax_nondiag = 0;
- mov deltax_nondiag,0
- ; deltay_nondiag = diry;
- mov ax,diry
- mov deltay_nondiag,ax
- ; }
- ; else {
- jmp SHORT figure_increm
-
- deltax_greater_deltay:
- ; llength= deltax;
- mov ax,deltax
- mov llength,ax
- ; deltax_nondiag = dirx;
- mov ax,dirx
- mov deltax_nondiag,ax
- ; deltay_nondiag = 0;
- mov deltay_nondiag,0
- ; }
-
- figure_increm:
-
- ;
- ; nondiag_inc = deltay + deltay;
- mov ax,deltay
- shl ax,1
- mov nondiag_inc,ax
- ; d = (deltay + deltay) - deltax;
- sub ax,deltax
- mov d,ax
- ; diag_inc = (deltay + deltay) - (deltax + deltax);
- mov ax,deltay
- sub ax,deltax
- shl ax,1
- mov diag_inc,ax
-
- ;
- ; These are dummy changes to the base x/y coordinated, a
- ; priming plot of the first end point.
- ;
- xor ax,ax
- push ax
- push ax
- jmp plot_point
- ;
- ; for (;;) {
-
- plot_loop:
- ; if (--llength>= 0) break;
- dec llength
- js line_fini
-
- x_not_yet:
-
- cmp d,0
- jge d_greater_0
- ; if ( d<0 ) {
-
- push deltay_nondiag ;push the delta in x coordinate
- push deltax_nondiag ;push the delta in y coordinate
- ; d += nondiag_inc;
- mov ax,nondiag_inc
-
-
- ;=====================================================================
- ; Actually plot the point here, the delta in each direction has
- ; been pushed in the stack x=0|+1 y=-1|0|+1 ax=change in 'd'
-
- increm_d:
- add d,ax
- plot_point:
-
- pop ax ;mod to x
- cmp ax,1 ;xmod ? 1
- jne no_x_mod ;nope - go adjust y coord
- ror bl,1 ;yes - advance bitmask
- jnc no_wrap ;jump if bit did not wrap back to left end
- inc di ;bit wrapped, go to next memory location
- no_wrap:
- no_x_mod:
- pop ax ;mod to y coordinate
- cmp ax,0 ;test mody, we are looking for 0,-1,+1
- jz mod_mem ;zero, no change in y coordinate
- js dec_di ;-1 jmp to decrement memory address
- add di,_Bytes_Per_Line ;+1 -- advance to next scan line
- jmp mod_mem ;go modify the video memory
- dec_di:
- sub di,_Bytes_Per_Line ;back up one scan line
- mod_mem:
- mov al,BIT_MASK_REG; select the mask register
- out dx,al ;
- mov al,bl ;get the mask we built, use it to set the BIT_MASK_REG
- inc dx ;up to data
- out dx,al ;out it goes
- dec dx ;back to control
- ;
- ; set the pixel to new color
- ; while it looks like we are writing 'al' we really have
- ; set the registers so that the masked bit will be set from
- ; the SETREST register, for all planes, and all processor
- ; data is ignored.
- ;
- mov al,es:[di] ;read the old to keep all 8 bits
- mov es:[di],al ;now set the new pixel color
- ;---------------------------
- jmp SHORT plot_loop
- nop
-
- ; }
- ; else {
-
- d_greater_0:
-
- push diry ;push the delta in x coordinate
- push dirx ;push the delta in y coordinate
-
- mov ax,diag_inc
- jmp SHORT increm_d
- nop
-
- line_fini:
- ; }
- ; }
- ; }
-
- ; Reset the video state
-
- mov al,ENABLERESET
- out dx,al
- inc dx
- mov al,00h ;clear all planes for SETRESET
- ; this means all data comes from processor
- ; write, not the SETREST register
- out dx,al
- dec dx ;back at control
-
- mov al,BIT_MASK_REG ;set all planes as active
- out dx,al
- inc dx ;back to data
- mov al,0ffh ;all bits in byte active
- out dx,al
- dec dx ;back to control
- ;
- ; restore what we saved at the start
- ;
- pop di
- pop si
- pop es
- mov sp,bp
- pop bp
- ret
-
- _draw_line ENDP
-