home *** CD-ROM | disk | FTP | other *** search
- ;==================================================================
- ;
- ;
- ; egabplot(x, y, picture, rule);
- ;
- ;===================================================================
- ; large parms
- pX0 equ [bp+6]
- pY0 equ [bp+8]
- pIoffs equ [bp+10]
- pIseg equ [bp+12]
- pRule equ [bp+14]
- ; local stack storage
- lHigh equ WORD PTR [bp-2] ; value from image structure
- lWide equ WORD PTR [bp-4] ; value from image structure
- lLmask equ BYTE PTR [bp-6] ; computed left bit mask
- lRmask equ BYTE PTR [bp-8] ; computed right bit mask
- lPlane equ BYTE PTR [bp-10] ; shifted value to indicate plane
- lIseg equ WORD PTR [bp-12] ; image segment passed
- lLsize equ BYTE PTR [bp-14] ; count of bits in left mask
- lHwrk equ WORD PTR [bp-16] ; working copy as scan line are used
- lWwrk equ WORD PTR [bp-18] ; working copy across scan line
- lBitsLO equ WORD PTR [bp-20] ; bit left after alignment shift
- lBwide equ WORD PTR [bp-22] ; bytes wide of svan line
-
-
- _EgaPlot proc far
- public _EgaPlot
-
- push bp
- mov bp,sp
- sub sp,24 ;space for local storage
- pushf ; save the direction flag
- cld ; correct string function
- push si
- push di
-
- ; Pick up and strore the local versions of args
-
- mov cx,pX0 ; get x
- mov bx,pY0 ; get y
- mov si,pIoffs ; get ptr to Images
- ; We pick up the segment later.
- ;
- ; compute the offset in the video memory
- ;
- call emapxy
- ;
- ; set the segment reg to access the video screen
- ; and the segment for the image to be plotted
- ;
- mov ax,_bytes_per_line ;but first save this befor we destroy DS
- mov lBwide,ax
-
- push es
- mov es,_curr_vid_seg
- push ds
- mov ds,pIseg
- ;
- ; get the image size from the image struct
- ; check for a zero size image, if so just quit.
- ;
- lodsw
- cmp ax,0
- jz EgaPlotCzero
- mov lWide,ax
- lodsw
- cmp ax,0
- jz EgaPlotCzero
- mov lHigh,ax
- jmp EgaPlotCok ;Both wide & high are > 0
- EgaPlotCzero:
- jmp EgaPlotZero
- EgaPlotCok:
- ;
- ; Compute bit masks for the work on the left and right ends
- ; that may not be byte aligned in the video memory
- ;
- mov cx,pX0 ; init shift count
- and cx,7 ; cl = number of bits into this byte -1
- mov lBitsLO,cx ; save # of empty hi bits
- neg cx ; number of active bits
- and cx,7 ; get rid of all but last 3 bits
- jnz EgaPlotNByte ; !=0 := NotByte aligned
- mov cx,8 ; Byte aligned, need 8 bits
- EgaPlotNByte:
- mov ax,0ffh ; init left/right masks
- shl ax,cl ; al 1=bits to be shifted up into AH
- mov lLmask,ah ; left bit mask
- ;
- ; Now compute the mask for the right end since the mask is the
- ; result of ((start pixel + scan width -1) mod 8)+1
- ; A value of 0 implies the leftmost bit ; which is why '+1'
- ;
- push cx ; save CX=# of bits in rotation for alignment
-
- mov cx,pX0 ; Add the width to the start x1
- add cx,lWide ; start + width
- dec cx ; minus 1
- and cx,7 ; mod 8
- inc cx ; + 1
- mov bx,0ff00h
- shr bx,cl
- mov lRmask,bl ; Save it
-
- pop cx ; get back offset from byte alignment
-
- ; Now that we have computed both the leading and trailing
- ; bit masks, we have to check to see if they are both in the
- ; same byte. If they are, they must be combined.
-
- mov ax,pX0 ;start pixel offset
- mov bx,ax ;
- add bx,lWide ;how many pixels
- dec bx ;end = (start + length) -1
- xor ax,bx ;if the not same byte, some bits from 3-15
- ; will be set
- and ax,0fff8h ;keep all but the low 3 bits
- jnz EgaPlotNotSameByte ;not zero, not the same byte
- ; same byte - build combined mask
- mov al,lLmask
- and al,lRmask ;keep only bit in both masks
- mov lLmask,al
- EgaPlotNotSameByte:
- ;
- ; set the logical function
- ;
- mov ah,pRule ; default logical function
- shl ah,1 ; shift up to bit 1,2
- shl ah,1 ; shift up to bit 2,3
- shl ah,1 ; shift up to bit 3,4
- ;
- ; AX = bits read from video memory
- ; BX = width of scan line
- ; CX = number of bits (shifts) to align video memory to storage
- ; DX = work register (used to address Video controller ports)
- ;
-
- EgaPlotFunc:
- GR12_FUNCTION ah
- ;
- ; set the plane to be worked on (2^ 1..4)
- ;
- mov lPlane,1 ; init plane counter
- ;
- EgaPlotPlane:
- EgaPlotLeft:
- ; Do the left partial bits
- ;
- push di ; save start of image screen ptr
-
- SEQ_PLANE lPlane
-
- mov dx,lHigh
- mov lHwrk,dx ; init height counter
- EgaPlotScan:
- push di ; save start of line screen ptr
- mov bx,lWide ; init scan line width
-
- GR12_BITMASK lLmask
-
- xor ah,ah ; init upper bits to zeros
-
- lodsb ; get first byte of image line in AL (AX=00xx)
-
- shl ax,cl ; rotate it AX = 0xx0
- xchg al,ah ; get bits shifted into AH back down to AL
- mov dl,es:[di] ; latch current screen data into ega controller
- stosb ; write new data (AL) according to rule
-
- sub bx,cx ; scan width -= shift amount
- jz EgaPlotEndScan ; 0 bits left - on to next scan line
- js EgaPlotEndScan ; sign set, went negative
- cmp bx,8 ; remaining < 8 bits left ?
- jl EgaPlotRite ; (signed) YES - right partial end
-
- ;
- ; Now we are working with byte aligned portion of the scan line
- ;
- GR12_BITMASK 0ffh
-
- EgaPlotByte:
- ; This loop is done for each part of the image line that
- ; is on a full byte boundry.
- ;
- lodsb ; got next byte of image data in AL
- ; AX = leftover in that was in AH
- ; (xchg from AL) followed by new byte in AL
- shr ah,cl ; get leftover bits back in position
- ; that shifted them back down to the
- ; AH/AL boundry
- shl ax,cl ; mix bits with leftovers
- ; and now back up again by the shift count
- xchg al,ah ; get ms bits
- mov dl,es:[di] ; latch previous data
- stosb ; update with new data
-
- sub bx,8 ; last byte?
- jz EgaPlotEndScan ; exact match - no more bits
- cmp bx,8 ; More than 8 bits left ??
- jge EgaPlotByte ; jif yes
-
- EgaPlotRite:
- ; Now we handle the bits that were left over in the right
- ; mask from the original computation
- ;
-
- GR12_BITMASK lRmask
- ;
- ; If bx (bits left to plot) is > LBitsLO, (bit left over after shift)
- ; we need to get that last byte, and mix it in.
- ; the leftover bit are in the top of AH.
- cmp bx,lBitsLO
- jle EgaPlotNoByte ; enuf bits in AH to finish job
-
- lodsb ; get that last byte into AL
- shr ah,cl ; get leftover bits back in position
- ; that shifted them back down to the
- ; AH/AL boundry
- shl ax,cl ; mix bits with leftovers
- ; and now back up again by the shift count
-
- EgaPlotNoByte:
-
- xchg al,ah ; get ms bits
- ; shift and xchg run back down into AL
- mov dl,es:[di] ; latch current data
- stosb ; update with new
- EgaPlotEndScan:
- pop di ; mov back to start of screen line
- add di,lBwide ; move to next line
- dec lHwrk ; last line?
- jnz EgaPlotScan ; jif no, do next line
- ;
- ; Now we have completed one plane of the image.
- ; Reset the DI pointer to the start of the video image,
- ; but keep going in the memory image to be written.
- ; Move on to the next plane as needed.
- ;
- EgaPlotEndPlane:
- pop di ; mov back to start of screen image
- shl lPlane,1 ; mov to next plane
- test lPlane,16 ; done?
- jnz EgaPlotDone ; jif no
- jmp EgaPlotPlane
-
- EgaPlotDone:
- GR12_FUNCTION 0
- GR12_BITMASK 0ffh
- SEQ_PLANE 0fh
- EgaPlotZero:
- mov ax,0 ; return 0
- pop es
- pop ds
- pop di
- pop si
- popf
- mov sp,bp
- pop bp
- ret
- _EgaPlot endp
-