home *** CD-ROM | disk | FTP | other *** search
/ Frostbyte's 1980s DOS Shareware Collection / floppyshareware.zip / floppyshareware / VORX / SUPER_C.ARC / RECT.ASM < prev    next >
Assembly Source File  |  1980-01-01  |  19KB  |  417 lines

  1. ;               Rectangle Drawing Routine
  2.  
  3. _TEXT   segment byte public 'CODE'
  4.         assume CS:_TEXT
  5.  
  6. ; rect(left,top,right,bottom,pattern,globalPatt,mode) 
  7. ;
  8. ; Function: Draw a rectangle consisting of the bits (left,top) up to but 
  9. ; not including (right,bottom), filling the rectangle with the pattern 
  10. ; pointed to by pattern; if globalPatt is true, lock the pattern to a
  11. ; global reference otherwise start it at (left,top). mode specifies which 
  12. ; type of operation to use to combine the new and old dots: 0 for copy, 
  13. ; 1 for exclusive-or, 2 for bit-set (or), and 3 for bit-clear.
  14. ;
  15. ; Algorithm: First, clip the rectangle to the display. Second, figure out
  16. ; the start and end words and word masks. Third, rotate the pattern as
  17. ; needed. Fourth, branch to and perform the appropriate type of copying.
  18. ; Finally, restore the saved registers and exit.
  19.  
  20.         public _rect            ; Routine is available to other modules
  21.  
  22. ; Parameters:
  23.  
  24.         left = 4                ; Offset from BP to parameter left
  25.         top = 6                 ; Offset to parameter top
  26.         right = 8               ; Offset to right
  27.         bottom = 10             ; Offset to bottom
  28.         pattern = 12            ; Offset to pattern
  29.         globPatt = 14           ; Offset to globPatt
  30.         mode = 16               ; Offset to mode
  31.  
  32. ; Local variables:
  33.  
  34.         lStrt = 2               ; Offset from BP to lStrt local variable
  35.         lEnd = 4                ; Offset to lEnd local variable
  36.         lSMask = 6              ; Offset to lSMask
  37.         lEMask = 8              ; Offset to lEMask
  38.         lCnt = 10               ; Offset to lCnt
  39.         pattCnt = 12            ; Offset to pattCnt
  40.         clipLeft = 14           ; Offset to clipLeft
  41.         clipTop = 16            ; Offset to clipTop
  42.         clipRight = 18          ; Offset to clipRight
  43.         clipBottom = 20         ; Offset to clipBottom
  44.         pattRot = 52            ; Offset to pattRot
  45.  
  46. _rect   proc near               ; NEAR type subroutine
  47.         push    bp              ; Save BP register
  48.         mov     bp,sp           ; Set BP to SP; to allow access to parameters
  49.                                 ;   and local variables
  50.         sub     sp,52           ; Allocate space on the stack for loca vars
  51.         push    di              ; Save the DI register
  52.         push    si              ; Save SI register
  53.         push    es              ; Save ES register
  54.         mov     ax,0B800H       ; Set ES to the base of the graphics display
  55.         mov     es,ax
  56. ;
  57. ; Clip left to produce clipLeft:
  58. ;
  59.         mov     ax,[bp+left]    ; AX = left
  60.         cmp     ax,640          ; Is AX >= 640 (i.e., off screen right)?
  61.         jge     getOut1         ; If yes, there's nothing to do -- exit
  62.         or      ax,ax           ; Is AX < 0 (i.e., off screen left)?
  63.         jns     clip1           ; If no, leave it alone
  64.         xor     ax,ax           ; If yes, set it to zero
  65. clip1:  mov     [bp-clipLeft],ax ; Set clipLeft
  66. ;
  67. ; Clip top to produce clipTop:
  68. ;
  69.         mov     ax,[bp+top]     ; AX = top
  70.         cmp     ax,200          ; Is AX >= 200 (i.e., off screen bottom)?
  71.         jge     getOut1         ; If yes, there's nothing to do, so exit
  72.         or      ax,ax           ; Is AX < 0 (i.e., off screen top)?
  73.         jns     clip2           ; If no, leave it alone
  74.         xor     ax,ax           ; If yes, set it to zero
  75. clip2:  mov     [bp-clipTop],ax ; Set clipTop
  76. ;
  77. ; Clip right to produce clipRight:
  78. ;
  79.         mov     ax,[bp+right]   ; AX = right
  80.         or      ax,ax           ; Is AX < 0 (i.e., off screen left)?
  81.         js      getOut1         ; If yes, there's nothing to do, so just exit
  82.         cmp     ax,640          ; Is AX > 640 (i.e., off screen right)?
  83.         jle     clip3           ; If no, leave it alone
  84.         mov     ax,640          ; If yes, set it to 640
  85. clip3:  mov     [bp-clipRight],ax ; Set clipRight
  86. ;
  87. ; Clip bottom to produce clipBottom:
  88. ;
  89.         mov     ax,[bp+bottom]  ; AX = bottom
  90.         or      ax,ax           ; Is AX < 0 (i.e., off screen top)?
  91.         jns     clip4           ; If no, continue clipping
  92. getOut1: jmp    getOut          ; If yes, there's nothing to do -- exit
  93. clip4:  cmp     ax,200          ; Is AX > 200 (i.e., off screen bottom)?
  94.         jle     clip5           ; If no, leave it alone
  95.         mov     ax,200          ; If yes, set it to 200
  96. clip5:  mov     [bp-clipBottom],ax ; Set clipBottom
  97. ;
  98. ; Compute lCnt:
  99. ;
  100.         sub     ax,[bp-clipTop] ; AX = clipBottom - clipTop
  101.         jz      getOut1         ; If lCnt is zero, exit (nothing to do)
  102.         js      getOut1         ; If lCnt is negative, also exit
  103.         mov     [bp-lCnt],ax    ; Set lCnt
  104. ;
  105. ; Compute lSMask:
  106. ;
  107.         mov     cl,[bp-clipLeft]; CL = clipLeft & 15 (i.e., bottom 4 bits)
  108.         and     cl,15
  109.         xor     ax,ax           ; AX = FFFF
  110.         not     ax
  111.         shr     ax,cl           ; Shift AX right according to CL
  112.         mov     bl,ah           ; BX = AX byte-reversed
  113.         mov     bh,al
  114.         mov     [bp-lSMask],bx  ; lSMask = BX
  115. ;
  116. ; Compute lEMask:
  117. ;
  118.         mov     cl,[bp-clipRight] ; CL = clipRight & 15 (bottom 4 bits)
  119.         and     cl,15
  120.         xor     ax,ax           ; AX = FFFF
  121.         not     ax
  122.         shr     ax,cl           ; Shift AX right according to CL
  123.         not     ax
  124.         mov     bl,ah           ; BX = AX byte-reversed
  125.         mov     bh,al
  126.         mov     [bp-lEMask],bx  ; lEMask = BX
  127. ;
  128. ; Compute pattCnt (assuming globalPatt is FALSE):
  129. ;
  130.         mov     ax,[bp-clipTop] ; AX = clipTop - top
  131.         sub     ax,[bp+top]
  132.         shl     ax,1            ; AX = 2 * AX
  133.         mov     [bp-pattCnt],ax ; pattCnt = AX
  134. ;
  135. ; Transfer pattern to pattRot, rotated as specified by globalPatt (and, if
  136. ; globalPatt is TRUE, replace pattCnt with a recomputed value):
  137. ;
  138.         mov     ch,16           ; CH = 16 (number of words to transfer)
  139.         mov     bl,[bp+left]    ; BL = left & 15 (bottom four bits)
  140.         and     bl,15
  141.         mov     ax,[bp+globPatt]; Is globalPatt TRUE?
  142.         or      ax,ax
  143.         jz      locPat          ; If not, branch
  144.         mov     ax,[bp-clipTop] ; If yes, recompute pattCnt = 2 * clipTop
  145.         shl     ax,1
  146.         mov     [bp-pattCnt],ax
  147.         xor     bl,bl           ; And set BL = 0
  148. locPat: mov     si,[bp+pattern] ; SI = pattern
  149.         lea     di,[bp-pattRot] ; DI = pattRot
  150.         xor     ax,ax           ; AX = FFFF (used when pattern == 0)
  151.         not     ax
  152. nxtPat: or      si,si           ; Is SI (from pattern) == 0?
  153.         jz      rotIt           ; If yes, use the FFFF already in AX
  154.         lods    word ptr [si]   ; Otherwise, AX = *SI++
  155. rotIt:  mov     cl,bl           ; Rotate the pattern according to BL
  156.         ror     ax,cl
  157.         mov     dl,ah           ; DX = AX byte-reversed
  158.         mov     dh,al
  159.         mov     [di],dx         ; *DI = DX
  160.         inc     di              ; DI++
  161.         inc     di
  162.         dec     ch              ; CH--
  163.         jnz     nxtPat          ; If more pattern left, go back and do it again
  164. ;
  165. ; Compute the initial lStrt:
  166. ;
  167.         mov     ax,[bp-clipTop] ; AX = clipTop
  168.         xor     bx,bx           ; BX = 0
  169.         shr     ax,1            ; AX = AX/2, with the bottom bit going to CF
  170.         mov     cl,14           ; Shift CL into BX
  171.         rcl     bx,cl
  172.         mov     cl,80           ; AX = 80 * AX (multiple by # of columns)
  173.         mul     cl
  174.         add     ax,bx           ; Add in the bit in BX
  175.         mov     bx,[bp-clipLeft]; BX = clipLeft
  176.         mov     cl,3            ; BX = BX/8 (convert from bits to bytes)
  177.         shr     bx,cl
  178.         and     bx,0FFFEH       ; Convert to word address (clear bottom bit)
  179.         add     bx,ax           ; BX += AX
  180.         mov     [bp-lStrt],bx   ; lStrt = BX
  181. ;
  182. ; Compute the initial lEnd:
  183. ;
  184.         mov     bx,[bp-clipRight]; BX = clipRight
  185.         mov     cl,3            ; BX = BX/8 (convert to word)
  186.         shr     bx,cl
  187.         and     bx,0FFFEH       ; Convert to word address (clear bottom bit)
  188.         add     ax,bx           ; AX += BX (AX had column offset from above)
  189.         mov     [bp-lEnd],ax    ; lEnd = AX
  190. ;
  191. ; Set up for processing:
  192. ;
  193.         mov     di,[bp-lStrt]   ; DI = lStrt
  194.         mov     si,[bp-lEnd]    ; SI = lEnd
  195. ;
  196. ; Switch on mode:
  197. ;
  198.         mov     ax,[bp+mode]    ; AX = mode
  199.         dec     ax              ; AX == 0 (COPY)?
  200.         jns     tryXor          ; If not, go try XOR
  201. ;
  202. ; Do COPY mode:
  203. ;
  204. cpNxt:  push    di              ; Save DI (line start)
  205.         mov     di,[bp-pattCnt] ; DI = pattCnt
  206.         and     di,31           ; DI &= 31 (get bottom five bits)
  207.         mov     bx,[bp-pattRot+di] ; BX = pattRot[DI] (the pattern word)
  208.         inc     di              ; DI++
  209.         inc     di              ; DI++
  210.         mov     [bp-pattCnt],di ; pattCnt = DI
  211.         pop     di              ; Restore line start DI
  212.         mov     ax,[bp-lSMask]  ; AX = lSMask
  213.         cmp     di,si           ; Line start == line end?
  214.         je      cpLast          ; If yes, go process it as one word
  215.         mov     dx,ax           ; If not, copy line start mask to DX
  216.         not     ax              ; Complement start mask in AX
  217.         and     ax,es:[di]      ; AX &= *DI (old word with new bits cleared)
  218.         and     dx,bx           ; DX &= BX (new word, with old bits cleared)
  219.         or      ax,dx           ; AX |= DX (combine new and old)
  220.         stos    word ptr es:[di]; *DI++ = AX (store processed word)
  221.         mov     cx,si           ; CX = (SI-DI)/2 (converted from byte to word)
  222.         sub     cx,di
  223.         shr     cx,1
  224.         jz      cpLast2         ; If CX == 0 (SI and DI in same word), branch
  225.         mov     ax,bx           ; AX = BX (the pattern)
  226.         rep stos word ptr es:[di] ; Block move the words between the 1st & last
  227. cpLast2: xor    ax,ax           ; AX = FFFF
  228.         not     ax
  229. cpLast: and     ax,[bp-lEMask]  ; AX &= lEMask (AX is now mask of last word)
  230.         mov     dx,ax           ; Copy mask to DX
  231.         not     ax              ; Complement mask in AX
  232.         and     ax,es:[di]      ; AX &= *DI (AX = old word with new bits clear)
  233.         and     dx,bx           ; DX &= BX (DX = new word with old bits clear)
  234.         or      ax,dx           ; AX |= DX (combine the two)
  235.         mov     es:[di],ax      ; *DI = AX (put the processed word back)
  236. ;
  237. ; Increment line start and line end pointers to next line:
  238.         mov     di,[bp-lStrt]   ; DI = lStrt
  239.         xor     si,2000H        ; Toggle even/odd line bit in SI and DI
  240.         xor     di,2000H
  241.         mov     ax,di           ; DI & 0x2000?
  242.         and     ax,2000H
  243.         jnz     cpOdd           ; If yes (odd), don't add in 80
  244.         add     si,80           ; If no (even), add 80 to the start and end
  245.         add     di,80
  246. cpOdd:  mov     [bp-lStrt],di   ; lStrt = DI
  247.         dec     word ptr [bp-lCnt] ; lCnt--
  248.         jnz     cpNxt           ; If we're not done, go back a do another line
  249.         jmp     getOut          ; Otherwise, exit
  250. ;
  251. ; Try exclusive-or:
  252. ;
  253. tryXor: dec     ax              ; Exclusive-or mode?
  254.         jns     tryBst          ; If not, go try bit set
  255. ;
  256. ; Do EXCLUSIVE-OR mode:
  257. ;
  258. xrNxt:  push    di              ; Save DI (line start)
  259.         mov     di,[bp-pattCnt] ; DI = pattCnt
  260.         and     di,31           ; DI &= 31 (get bottom five bits)
  261.         mov     bx,[bp-pattRot+di] ; BX = pattRot[DI] (the pattern word)
  262.         inc     di              ; DI++
  263.         inc     di              ; DI++
  264.         mov     [bp-pattCnt],di ; pattCnt = DI
  265.         pop     di              ; Restore line start DI
  266.         mov     ax,[bp-lSMask]  ; AX = lSMask
  267.         cmp     di,si           ; Line start == line end?
  268.         je      xrLast          ; If yes, go process it as one word
  269.         and     ax,bx           ; AX &= BX (clip pattern to mask into AX)
  270.         xor     ax,es:[di]      ; AX ^= *DI (exclusive-or in old word)
  271.         stos    word ptr es:[di]; *DI++ = AX (store processed word)
  272.         mov     cx,si           ; CX = (SI-DI)/2 (converted from byte to word)
  273.         sub     cx,di
  274.         shr     cx,1
  275.         jz      xrLast2         ; If CX == 0 (SI and DI in same word), branch
  276. xrLoop: mov     ax,es:[di]      ; AX = *DI (get next word to process)
  277.         xor     ax,bx           ; AX ^= BX (exclusive-or word with pattern)
  278.         stos    word ptr es:[di]; *DI++ = AX (store processed word)
  279.         loopnz  xrLoop          ; Repeat until all word are processed
  280. xrLast2: xor    ax,ax           ; AX = FFFF
  281.         not     ax
  282. xrLast: and     ax,[bp-lEMask]  ; AX &= lEMask (AX is now mask of last word)
  283.         and     ax,bx           ; AX &= BX (clip pattern to mask into AX)
  284.         xor     ax,es:[di]      ; AX ^= *DI (exclusive-or word into AX)
  285.         mov     es:[di],ax      ; *DI = AX (put the processed word back)
  286. ;
  287. ; Increment line start and line end pointers to next line:
  288.         mov     di,[bp-lStrt]   ; DI = lStrt
  289.         xor     si,2000H        ; Toggle even/odd line bit in SI and DI
  290.         xor     di,2000H
  291.         mov     ax,di           ; DI & 0x2000?
  292.         and     ax,2000H
  293.         jnz     xrOdd           ; If yes (odd), don't add in 80
  294.         add     si,80           ; If no (even), add 80 to the start and end
  295.         add     di,80
  296. xrOdd:  mov     [bp-lStrt],di   ; lStrt = DI
  297.         dec     word ptr [bp-lCnt] ; lCnt--
  298.         jnz     xrNxt           ; If we're not done, go back a do another line
  299.         jmp     getOut          ; Otherwise, exit
  300.  
  301. ;
  302. ; Try bit set:
  303. ;
  304. tryBst: dec     ax              ; Bit set mode?
  305.         jns     tryBcl          ; If not, go try bit clear
  306. ;
  307. ; Do BIT SET mode:
  308. ;
  309. bsNxt:  push    di              ; Save DI (line start)
  310.         mov     di,[bp-pattCnt] ; DI = pattCnt
  311.         and     di,31           ; DI &= 31 (get bottom five bits)
  312.         mov     bx,[bp-pattRot+di] ; BX = pattRot[DI] (the pattern word)
  313.         inc     di              ; DI++
  314.         inc     di              ; DI++
  315.         mov     [bp-pattCnt],di ; pattCnt = DI
  316.         pop     di              ; Restore line start DI
  317.         mov     ax,[bp-lSMask]  ; AX = lSMask
  318.         cmp     di,si           ; Line start == line end?
  319.         je      bsLast          ; If yes, go process it as one word
  320.         and     ax,bx           ; AX &= BX (clip pattern to mask into AX)
  321.         or      ax,es:[di]      ; AX |= *DI (or in old word)
  322.         stos    word ptr es:[di]; *DI++ = AX (store processed word)
  323.         mov     cx,si           ; CX = (SI-DI)/2 (converted from byte to word)
  324.         sub     cx,di
  325.         shr     cx,1
  326.         jz      bsLast2         ; If CX == 0 (SI and DI in same word), branch
  327. bsLoop: mov     ax,es:[di]      ; AX = *DI (get next word to process)
  328.         or      ax,bx           ; AX |= BX (or word with pattern)
  329.         stos    word ptr es:[di]; *DI++ = AX (store processed word)
  330.         loopnz  bsLoop          ; Repeat until all word are processed
  331. bsLast2: xor    ax,ax           ; AX = FFFF
  332.         not     ax
  333. bsLast: and     ax,[bp-lEMask]  ; AX &= lEMask (AX is now mask of last word)
  334.         and     ax,bx           ; AX &= BX (clip pattern to mask into AX)
  335.         xor     ax,es:[di]      ; AX ^= *DI (exclusive-or word into AX)
  336.         mov     es:[di],ax      ; *DI = AX (put the processed word back)
  337. ;
  338. ; Increment line start and line end pointers to next line:
  339.         mov     di,[bp-lStrt]   ; DI = lStrt
  340.         xor     si,2000H        ; Toggle even/odd line bit in SI and DI
  341.         xor     di,2000H
  342.         mov     ax,di           ; DI & 0x2000?
  343.         and     ax,2000H
  344.         jnz     bsOdd           ; If yes (odd), don't add in 80
  345.         add     si,80           ; If no (even), add 80 to the start and end
  346.         add     di,80
  347. bsOdd:  mov     [bp-lStrt],di   ; lStrt = DI
  348.         dec     word ptr [bp-lCnt] ; lCnt--
  349.         jnz     bsNxt           ; If we're not done, go back a do another line
  350.         jmp     getOut          ; Otherwise, exit
  351. ;
  352. ; Try bit clear:
  353. ;
  354. tryBcl: dec     ax              ; Bit clear mode?
  355.         jns     tryBcl          ; If not, exit (not a legal mode)
  356. ;
  357. ; Do BIT CLEAR mode:
  358. ;
  359. bcNxt:  push    di              ; Save DI (line start)
  360.         mov     di,[bp-pattCnt] ; DI = pattCnt
  361.         and     di,31           ; DI &= 31 (get bottom five bits)
  362.         mov     bx,[bp-pattRot+di] ; BX = pattRot[DI] (the pattern word)
  363.         inc     di              ; DI++
  364.         inc     di              ; DI++
  365.         mov     [bp-pattCnt],di ; pattCnt = DI
  366.         pop     di              ; Restore line start DI
  367.         mov     ax,[bp-lSMask]  ; AX = lSMask
  368.         cmp     di,si           ; Line start == line end?
  369.         je      bcLast          ; If yes, go process it as one word
  370.         and     ax,bx           ; AX &= BX (clip pattern to mask into AX)
  371.         not     ax              ; AX = ~AX (prepare to clear bits)
  372.         and     ax,es:[di]      ; AX &= *DI (clear bits in old word)
  373.         stos    word ptr es:[di]; *DI++ = AX (store processed word)
  374.         mov     cx,si           ; CX = (SI-DI)/2 (converted from byte to word)
  375.         sub     cx,di
  376.         shr     cx,1
  377.         jz      bcLast2         ; If CX == 0 (SI and DI in same word), branch
  378. bcLoop: mov     ax,bx           ; AX = BX (make a copy of the pattern)
  379.         not     ax              ; AX = ~AX (prepare to clear bits)
  380.         and     ax,es:[di]      ; AX &= *DI (clear bits in next word)
  381.         stos    word ptr es:[di]; *DI++ = AX (store processed word)
  382.         loopnz  bcLoop          ; Repeat until all word are processed
  383. bcLast2: xor    ax,ax           ; AX = FFFF
  384.         not     ax
  385. bcLast: and     ax,[bp-lEMask]  ; AX &= lEMask (AX is now mask of last word)
  386.         and     ax,bx           ; AX &= BX (clip pattern to mask into AX)
  387.         xor     ax,es:[di]      ; AX ^= *DI (exclusive-or word into AX)
  388.         mov     es:[di],ax      ; *DI = AX (put the processed word back)
  389. ;
  390. ; Increment line start and line end pointers to next line:
  391.         mov     di,[bp-lStrt]   ; DI = lStrt
  392.         xor     si,2000H        ; Toggle even/odd line bit in SI and DI
  393.         xor     di,2000H
  394.         mov     ax,di           ; DI & 0x2000?
  395.         and     ax,2000H
  396.         jnz     bcOdd           ; If yes (odd), don't add in 80
  397.         add     si,80           ; If no (even), add 80 to the start and end
  398.         add     di,80
  399. bcOdd:  mov     [bp-lStrt],di   ; lStrt = DI
  400.         dec     word ptr [bp-lCnt] ; lCnt--
  401.         jnz     bcNxt           ; If we're not done, go back a do another line
  402.         jmp     getOut          ; Otherwise, exit
  403. ;
  404. ; Save registers and return:
  405. ;
  406. getOut: pop     es              ; Restore the ES register
  407.         pop     si              ; Restore the SI register
  408.         pop     di              ; Restore the DI register
  409.         mov     sp,bp           ; Free the local variable stack space
  410.         pop     bp              ; Restore the BP register
  411.         ret                     ; Return to calling program
  412. _rect   endp                    ; End of subroutine
  413.  
  414. _TEXT   ends                    ; End of code segment
  415.         end                     ; End of assembly code
  416.  
  417.