home *** CD-ROM | disk | FTP | other *** search
- ;==================================================================
- ;
- ;
- ; egamplot(int x, int y, far *picture, far *mask, int rule);
- ;
- ; In the following code, you will not find the creation of
- ; bit mask for the left and right ends of the image, as in
- ; 'eplot'. This is because the mask you supply will be used
- ; to determine which bits are set. DON'T get SLOPPY and leave
- ; the right end (padding) of the bitmask as garbage, it will cause
- ; probably black dits at the end of the image. Set the pad to 0s.
- ;
- ;===================================================================
- ; large parms
- pX0 equ [bp+6]
- pY0 equ [bp+8]
- pIoffs equ [bp+10]
- pIseg equ [bp+12]
- pMoffs equ [bp+14]
- pMseg equ [bp+16]
- pRule equ [bp+18]
- ; local stack storage
- lHigh equ WORD PTR [bp-2]
- lWide equ WORD PTR [bp-4]
- lPlane equ BYTE PTR [bp-6]
- lIseg equ WORD PTR [bp-8]
- lMoffs equ WORD PTR [bp-10]
- lMwork equ WORD PTR [bp-12]
- lWwrk equ WORD PTR [bp-14]
- lHwrk equ WORD PTR [bp-16]
- lBitsLO equ WORD PTR [bp-18] ; bit left after alignment shift
- lBwide equ WORD PTR [bp-20]
-
-
-
- _EgaMPlot proc far
- public _EgaMPlot
-
- push bp ; <1>
- mov bp,sp
- sub sp,22 ;space for local storage + fudge
- pushf
- cld ; correct string function
- push si ; <2>
- push di ; <3>
- mov cx,pX0 ; get x
- mov bx,pY0 ; get y
- mov ax,pMoffs
- mov lMoffs,ax ; save offset to bitMask
- mov ax,pIseg ; get ptr to Images
- mov lIseg,ax
- mov si,pIoffs ; get ptr to Images
- mov ax,pRule ; get rule
- ;
- ; re-map the coordinates to an origin in the
- ; lower left corner.
- ;
- call emapxy
- ;
- ; set the segment reg to access the video screen
- ; but first set addressability to screen width in bytes
- mov ax,_bytes_per_line
- mov lBwide,ax
-
- push es ; <4>
- mov es,_curr_vid_seg
- push ds ; <5>
- 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 EgaMPlotCzero
- mov lWide,ax
- lodsw
- cmp ax,0
- jz EgaMPlotCzero
- mov lHigh,ax
- jmp EgaMPlotCok ;Both wide & high are > 0
- EgaMPlotCzero:
- jmp EgaMPlotZero
- EgaMPlotCok:
- ;
- ; 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 to the next byte boundry
- mov lBitsLO,cx
- neg cx
- and cx,7 ; cl = number of bits to the next byte boundry
- jnz EgaMPlotNotByteAligned
- mov cl,8 ; using all 8 bits since byte aligned.
- EgaMPlotNotByteAligned:
- ;
- ; We don't need to worry about the right bit mask, since the
- ; fill at the end should be 0's.
-
- ;
- ; set the logical function - default is FORCE, otherwise XOR
- 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
-
- EgaMPlotFunc:
- GR12_FUNCTION ah
- ;
- ; set the plane to be worked on (2^ 1..4)
- ;
- mov lPlane,1 ; init plane counter
- ;
- EgaMPlotPlane:
- EgaMPlotLeft:
- ; Do the left partial bits
- ;
- push di ; <6>save start of image stroreg area for next
-
- SEQ_PLANE lPlane
-
- mov dx,lHigh ; set depth counter
- mov lHwrk,dx ; init depth counter
-
- mov ax,lMoffs ; and now the bitMask working offset
- mov lMwork,ax ; set initial working offset of bitMask
-
- EgaMPlotScan:
- push di ; <7>save start of line screen image
- mov dx,lWide ; set width counter
- mov lWwrk,dx ; init width counter
- ;
- ; The left bit mask must be computed for each row of data
- ; rather than jus once as with the non-masked approach
- ;
- xor bx,bx ; clear BX
- call EgaMPlotNxtMsk
- shl bx,cl ; shift what we need into BH
- xchg bh,bl ; swap it down into BL, leftover on BH
-
- ; Now merge the left mask with the left bit mask portion.
- ; if the result is 0, there is nothing to plot in this byte
-
- GR12_BITMASK bl ; use result of 'and' as bit mask
-
- 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
- ;
- ; Now adjust the bit mask stuff - we will use the BX for this
- ; The part to be used for the byte aligned is an ?H as we start
- ; through byte aligned. Fetch the high part from the manual calc.
- ;
- ; Adjust counter of pixels / scan row
- ;
- sub lWwrk,cx ; lWwrk -= CX
- cmp lWwrk,8 ; lWwrk < 8 bits left ?
- jl EgaMPlotRite ; wcount < 8
- ;
- ; Now we are working with byte aligned portion of the scan line
- ;
-
- EgaMPlotByte:
- ; Compute this bit mask
- ;
- call EgaMPlotNxtMsk
-
- shr bh,cl ; shift old down low in BH
- shl bx,cl ; shift all up be count
- xchg bh,bl ; swap them around
- ;
- ; Use this bit mask to determine which pixels are to be maintained
- ;
- GR12_BITMASK bl ; use BL as the mitmask for updating screen
-
- ; 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 lWwrk,8 ; last byte?
- jz EgaMPlotEndScan ; exact match - no more bits
- cmp lWwrk,8 ; More than 8 bits left ??
- jge EgaMPlotByte ; jif yes
-
- EgaMPlotRite:
- ; Now we handle the bits that were left over in the right
- ; mask from the original computation
- ;
- ;
- ; If dx (bits left to plot) is > LBitsLO, (bit left over after shift)
- ; we need to get that last byte, and mix it in.
- ;
- mov dx,lWwrk
- cmp dx,lBitsLO
- jle EgaMPlotNoByte ; enuf bits in AH to finish job
- ;
- ; pick up last bytes of image and bitmask
- ;
- lodsb ; get that last byte (image) into AL
- shr ah,cl ; get leftover bits back in position
- shl ax,cl ; mix bits with leftovers
-
- call EgaMPlotNxtMsk ; get that last byte (bitmask) into BL
- shr bh,cl ; get leftover bits back in position
- shl bx,cl ; mix bits with leftovers
-
- EgaMPlotNoByte:
-
- GR12_BITMASK bh ; remaining part of bitmask
-
- xchg al,ah ; get the bits left over from the last
- ; shift and xchg run back down into AL
- mov dl,es:[di] ; latch current data
- stosb ; update with new
- EgaMPlotEndScan:
- pop di ; <6>mov back to start of screen line
- add di,lBwide ; mov to next line
- dec lHwrk ; last line?
- jz EgaMPlotEndPlane; jif no, do next line
- jmp EgaMPlotScan ; 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.
- ;
- EgaMPlotEndPlane:
- pop di ; <5>mov back to start of screen image
- shl lPlane,1 ; mov to next plane
- test lPlane,16 ; done?
- jnz EgaMPlotDone ; jif no
- jmp EgaMPlotPlane
-
- EgaMPlotDone:
- GR12_FUNCTION 0
- GR12_BITMASK 0ffh
- SEQ_PLANE 0fh
- EgaMPlotZero:
- mov ax,0 ; return 0
- pop ds ; <4>
- pop es ; <3>
- pop di ; <2>
- pop si ; <1>
- popf
- mov sp,bp
- pop bp ; <0>
- ret
-
- ;==============================================================
- ; This saves the DS:[SI] set, retrieves the next byte
- ; of the bitmask, then resores the pointer to the
- ; image
- ;
- ; exit BL = next byte of bit mask
- ;
- EgaMPlotNxtMsk proc near
- push ds ; <8>addressability
- push si ; <9>
- mov ds,pMseg
- mov si,lMwork
- mov bl,[si] ; AL = initial left mask
- inc si
- mov lMwork,si
- pop si ; <8)
- pop ds ; <7>
- ret
- EgaMPlotNxtMsk endp
- _EgaMPlot endp
-
-