home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / v / vesavga.zip / VGA.ASM < prev   
Assembly Source File  |  1992-06-19  |  14KB  |  855 lines

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;
  3. ; Title: vga.asm
  4. ; Date: 6/18/92
  5. ; Author: Randy Buckland (randy@ncsu.edu)
  6. ;
  7. ; Description: 
  8. ;    This is a VERY basic set of routines to provide high speed SVGA
  9. ; graphics for IBM-PC compatibiles that have a VGA interface that supports
  10. ; a VESA driver. These routines assume a 256-color mode and will not work
  11. ; for any type of mode. The following routines are provided:
  12. ;
  13. ; vgainit(int vesa_mode)
  14. ; vgapoint(int row, int column, int pixel_value)
  15. ; vgahline(int row, int start_column, int end_column, int pixel_value)
  16. ; vgaline(int x1, int y1, int x2, int y2, int pixel_value)
  17. ; vgasetcolor(char *colors, int start, int count)
  18. ; vgafill(int row, int column, int width, int height, int pixel_value)
  19. ; vgarect(char *source, int source_width, int row, int column,
  20. ;        int width, int height)
  21. ;
  22. ; Copyright (c) 1992 by Randy Buckland
  23. ; Permission is given to use this code in any manner desired with the 
  24. ; following provisions:
  25. ;    1. The user of the code is totally responsible for any damages
  26. ;        that may be caused by it's use.
  27. ;    2. The author has no control or responsibility for any damages
  28. ;        that may be caused by it's use.
  29. ;    3. This copyright notice must remain a part of this source file.
  30. ;
  31. .model    large,c
  32. include macros.asm
  33.  
  34. ;
  35. ; Global data for the VGA support routines
  36. ;
  37. vgadata    segment word public 'VGADATA'
  38.  
  39. Block        dw    1        ; Current video memory block accessable
  40. BlockSz        dw    0        ; Size of a video block in K
  41. BlockShift    dw    0        ; Amount to shift bits by
  42. BlockEnd    dw    0        ; Last valid address in block
  43. BlockMask    dw    0        ; Mask used for block/offset operations
  44.  
  45. WinAddr        dw    0        ; Segment addr of window A block
  46. ;WinFunc        dd    0        ; Far pointer to windowing function
  47. ScanWidth    dw    0        ; Width of a scan line
  48.  
  49. vgadata    ends
  50.  
  51. vgacode    segment word public 'VGACODE'
  52.     assume    cs:vgacode,ds:vgadata
  53.  
  54. ;
  55. ; Set current video memory block. This procedure assumes that ds already
  56. ; points to the vgadata segment. This routine will not modify any registers.
  57. ;
  58. ; Parameters:
  59. ;    - block number to change to
  60. ;
  61. vgablock proc near
  62.     push bp
  63.     mov bp,sp
  64.     push dx
  65.  
  66.     mov dx,[bp+4]    ; Start of video memory
  67.     cmp dx,Block
  68.     je l1
  69.     mov Block,dx
  70.  
  71.     push ax
  72.     push bx
  73.  
  74.     mov ax,4f05h    ; VESA set memory block
  75.     mov bx,0000h    ; Set window A
  76.     int 10h
  77.  
  78.     pop bx
  79.     pop ax
  80. l1:
  81.     pop dx
  82.     mov sp,bp
  83.     pop bp
  84.     ret
  85. vgablock endp
  86.  
  87.  
  88.  
  89. ;
  90. ; Calculate block and offset values for a given row/column. Assumes that ds
  91. ; points to vgadata. Does NOT preserve registers. Returns block value in
  92. ; dx and offset in ax.
  93. ;
  94. ; Parameters:
  95. ;    - row value
  96. ;    - column value
  97. ;
  98. vgaoffset proc near
  99.     push bp
  100.     mov bp,sp
  101.  
  102.     mov ax,[bp+4]    ; Get row
  103.     mul ScanWidth    ; Get starting block and offset in dx:ax
  104.  
  105.     add ax,[bp+6]    ; Add start column offset
  106.     jnc l1
  107.     inc dx        ; Just crossed block boundery
  108. l1:
  109.     mov cx,BlockShift ; Get block size mask
  110.     cmp cx,0        ; Is block size 64K?
  111.     je l2           ; Yes, skip this section
  112.  
  113.     mov bx,ax    ; Save old ax
  114.     rol ax,cl
  115.     and ax,BlockMask ; Save high bits
  116.     rol dx,cl
  117.     add dx,ax    ; Add high bits to block value.
  118.  
  119.     mov ax,bx
  120.     rol ax,cl
  121.     or ax,BlockMask    ; Set undesirable bits
  122.     xor ax,BlockMask ; Clear bad bits
  123.     ror ax,cl
  124. ;
  125. ; Set active block to calculated block if needed
  126. ;
  127. l2:
  128.     cmp dx,Block
  129.     je l3
  130.     push dx
  131.     call vgablock
  132.     pop dx
  133. l3:
  134.  
  135.     mov sp,bp
  136.     pop bp
  137.     ret
  138. vgaoffset endp
  139.  
  140.  
  141.  
  142. ;
  143. ; Initialize the display
  144. ; Parameters:
  145. ;    Mode value to use
  146. ;
  147. public vgainit
  148. vgainit    proc far
  149. ;
  150. ; Set up call frame
  151. ;
  152.     Prefix
  153.     sub sp,256    ; Make local variable space
  154. ;
  155.     mov ax,vgadata    ; Load address of data segment
  156.     mov ds,ax    ; Set DS register
  157.  
  158. ;
  159. ; Get VGA information and set desired mode
  160. ;
  161.     mov ax,4f02h    ; VESA set mode function
  162.     mov bx,[bp+6]    ; 640x480 mode
  163.     int 10h
  164.  
  165.     push ss
  166.     pop es        ; Load es with value of ss
  167.     mov di,sp    ; Point index at 256 byte temp space
  168.     mov cx,[bp+6]
  169.     mov ax,4f01h    ; VESA get Super VGA mode information
  170.     int 10h
  171.  
  172.     mov ax,es:[di+6]
  173.     mov BlockSz,ax
  174.  
  175.     mov ax,es:[di+8]
  176.     mov WinAddr,ax
  177.  
  178. ;    mov ax,es:[di+12]
  179. ;    mov word ptr WinFunc,ax
  180.  
  181. ;    mov ax,es:[di+14]
  182. ;    mov word ptr WinFunc+2,ax
  183.  
  184.     mov ax,es:[di+16]
  185.     mov ScanWidth,ax
  186.  
  187. ;
  188. ; Calculate block shift and end values
  189. ;
  190.     mov ax,BlockSz
  191.     mov bx,10
  192.     mov cx,03ffh
  193. l1:
  194.     sar ax,1
  195.     inc bx
  196.     sal cx,1
  197.     inc cx
  198.     cmp ax,1
  199.     ja l1
  200.  
  201.     mov ax,16
  202.     sub ax,bx
  203.     mov BlockShift, ax
  204.     mov BlockEnd, cx
  205.     not cx
  206.     xchg ax,cx
  207.     rol ax,cl
  208.     mov BlockMask,ax
  209.  
  210. ;
  211. ; Set to start block 
  212. ;
  213.     xor ax,ax
  214.     push ax
  215.     call vgablock
  216.     pop ax
  217.  
  218. ;
  219. ; Remove call frame and exit
  220. ;
  221.     add sp,256
  222.     Postfix
  223. vgainit    endp
  224.  
  225.  
  226. ;
  227. ; Draw a single point
  228. ;
  229. ; Parameters:
  230. ;    - Row of point
  231. ;    - Column of point
  232. ;    - Pixel value to use
  233. ;
  234. vgapoint proc far
  235.     Prefix
  236.  
  237.     mov ax,vgadata    ; Load address of data segment
  238.     mov ds,ax    ; Set DS register
  239. ;
  240. ; Load window pointers
  241. ;
  242.     mov ax,WinAddr
  243.     mov es,ax    ; Set ES to point to video memory
  244.  
  245.     push [bp+8] ; Column
  246.     push [bp+6] ; Row
  247.     call vgaoffset
  248.     add sp,4
  249.  
  250. ;
  251. ; Draw point
  252. ;
  253.     mov di,ax    ; Put offset in index regester
  254.     mov ax,[bp+10]    ; bl has pixel value
  255.     cld
  256.     stosb
  257.  
  258.     Postfix
  259. vgapoint endp
  260.  
  261.  
  262.  
  263. ;
  264. ; Draw a horizontal line. Line is assumed to start on even boundry and 
  265. ; have length be an even value for speed.
  266. ;
  267. ; Parameters:
  268. ;    - Row for line
  269. ;    - Start column
  270. ;    - End column
  271. ;    - Pixel value
  272. ;
  273. vgahline proc far
  274.     Prefix
  275. ;
  276.     mov    ax,vgadata    ; Load address of data segment
  277.     mov    ds,ax        ; Set DS register
  278. ;
  279. ; Load window pointers
  280. ;
  281.     mov ax,WinAddr
  282.     mov es,ax        ; Set ES to point to video memory
  283.  
  284.     push [bp+8]
  285.     push [bp+6]
  286.     call vgaoffset
  287.     add sp,4
  288.  
  289. ;
  290. ; Setup control parameters for line draw.
  291. ;
  292.     mov di, ax        ; Offset in di
  293.     mov ax,[bp+12]
  294.     mov ah,al        ; ax has duplicated pixel value in bl and bh
  295.  
  296.     mov cx,BlockEnd        ; Last point in counter
  297.     sub cx,di        ; cx has number of legal bytes-1
  298.  
  299.     mov bx,[bp+10]
  300.     sub bx,[bp+8]        ; bx has number to write - 1
  301.  
  302.     cmp bx,cx
  303.     ja l1
  304.     mov cx,bx        ; Won't need a block change
  305. l1:
  306.     sub bx,cx        ; ax has number of words after block change
  307.     inc cx
  308.     ror cx,1
  309.     ror bx,1
  310.  
  311. ;
  312. ; Draw the line
  313. ;
  314.     even
  315. l4:
  316.     cld
  317.     rep stosw
  318.  
  319.     cmp bx,0
  320.     je l5
  321.  
  322. ;
  323. ; Handle block change and continue
  324. ;
  325.     inc dx
  326.     push dx
  327.     call vgablock
  328.     pop dx
  329.  
  330.     mov cx,bx
  331.     xor bx,bx
  332.     xor di,di
  333.     jmp l4
  334.  
  335. ;
  336. ; Finish up
  337. ;
  338. l5:
  339.     Postfix
  340. vgahline endp
  341.  
  342.  
  343.  
  344. ;
  345. ; Draw a line using bresenham's algorithm.
  346. ;
  347. ; Parameters:
  348. ;    - x1
  349. ;    - y1
  350. ;    - x2
  351. ;    - y2
  352. ;    - Pixel value
  353. ;
  354. ; Locals:
  355. ;    [bp-10] DX
  356. ;    [bp-12] DY
  357. ;    [bp-14] incr1
  358. ;    [bp-16] incr2
  359. ;
  360. vgaline proc far
  361.     Prefix
  362.     sub sp,8
  363. ;
  364.     mov    ax,vgadata    ; Load address of data segment
  365.     mov    ds,ax        ; Set DS register
  366. ;
  367. ; Load window pointers
  368. ;
  369.     mov ax,WinAddr
  370.     mov es,ax        ; Set ES to point to video memory
  371.  
  372.     push [bp+8]
  373.     push [bp+6]
  374.     call vgaoffset
  375.     add sp,4
  376.     mov di,ax
  377.  
  378. ;
  379. ; Initialize for line draw
  380. ;
  381.     mov ax,[bp+6]        ; Get x1
  382.     sub ax,[bp+10]        ; Sub x2
  383.     jg l1            ; Skip if positive
  384.     neg ax
  385. l1:    mov [bp-10],ax        ; Save DX
  386.  
  387.     mov ax,[bp+8]        ; Get y1
  388.     sub ax,[bp+12]        ; sub y2
  389.     jg l2            ; Skip if positive
  390.     neg ax
  391. l2:    mov [bp-12],ax        ; Save DY
  392.  
  393.     cmp ax,[bp-10]        ; See if DY>DX
  394.     jle xline        ; Go do X oriented version
  395.     jmp yline        ; Go do Y oriented version
  396.  
  397. ;
  398. ; X oriented version of draw line. Slope must be between -1 and 1 inclusive
  399. ;
  400. xline:
  401.     mov cx, [bp-10]        ; cx has increment control
  402.  
  403.     sal ax,1        ; DY*2
  404.     mov [bp-14],ax        ; Save incr1
  405.     sub ax,[bp-10]        ; 2*dy - dx
  406.     mov bx,ax        ; bx has D value
  407.  
  408.     mov ax,[bp-12]        ; Get DY
  409.     sub ax,[bp-10]        ; (DY-DX)
  410.     sal ax,1        ; 2*(DY-DX)
  411.     mov [bp-16],ax        ; Save incr2
  412.  
  413.     mov word ptr [bp-10],0  ; Assume going to left
  414.     mov ax,[bp+6]        ; Get x1
  415.     sub ax,[bp+10]        ; x1-x2
  416.     jg l3
  417.     mov word ptr [bp-10],1    ; Going to right
  418. l3:
  419.     mov word ptr [bp-12],0    ; Assume going up
  420.     mov ax,[bp+8]        ; Get y1
  421.     sub ax,[bp+12]        ; y1-y2
  422.     jg l5
  423.     mov word ptr [bp-12],1    ; Going down
  424. l5:
  425.  
  426. ;
  427. ; Main X oriented drawing loop.
  428. ;    ax = pixel value
  429. ;    bx = d
  430. ;    cx = loop control
  431. ;    dx = block number
  432. ;    di = block offset
  433. ;
  434.     mov ax,[bp+14]
  435.     mov es:[di],al        ; Write first pixel
  436.     cmp cx,0        ; Check if done
  437.     je xloopend
  438.  
  439. xloop:
  440.     cmp word ptr [bp-10],0    ; See if going left?
  441.     je l7
  442.     inc di            ; going right
  443.     jnc l8
  444.     inc dx
  445.     push dx
  446.     call vgablock
  447.     pop dx
  448.     jmp l8
  449. l7:
  450.     dec di            ; going left
  451.     jnc l8
  452.     dec dx
  453.     push dx
  454.     call vgablock
  455.     pop dx
  456. l8:
  457.     cmp bx,0        ; test d<0
  458.     jge l9
  459.     add bx,[bp-14]        ; d = d + incr1
  460.     jmp l11
  461. l9:
  462.     add bx,[bp-16]        ; d = d + incr2
  463.     cmp word ptr [bp-12],0    ; See if going up
  464.     je l10
  465.     add di,ScanWidth    ; Go to next line
  466.     jnc l11
  467.     inc dx
  468.     push dx
  469.     call vgablock
  470.     pop dx
  471.     jmp l11
  472. l10:
  473.     sub di,ScanWidth    ; Go to previous line
  474.     jnc l11
  475.     dec dx
  476.     push dx
  477.     call vgablock
  478.     pop dx
  479. l11:
  480.     mov es:[di],al        ; Write next pixel
  481.     loop xloop
  482. xloopend:
  483.     jmp done
  484.  
  485.  
  486. ;
  487. ; Y oriented version of draw line. Slope must be outside -1 and 1 inclusive
  488. ;
  489. yline:
  490.     mov cx, [bp-12]        ; cx has increment control
  491.  
  492.     mov ax, [bp-10]
  493.     sal ax,1        ; DX*2
  494.     mov [bp-14],ax        ; Save incr1
  495.     sub ax,[bp-12]        ; 2*dx - dy
  496.     mov bx,ax        ; bx has D value
  497.  
  498.     mov ax,[bp-10]        ; Get DX
  499.     sub ax,[bp-12]        ; (DX-DY)
  500.     sal ax,1        ; 2*(DX-DY)
  501.     mov [bp-16],ax        ; Save incr2
  502.  
  503.     mov word ptr [bp-10],0  ; Assume going to left
  504.     mov ax,[bp+6]        ; Get x1
  505.     sub ax,[bp+10]        ; x1-x2
  506.     jg l12
  507.     mov word ptr [bp-10],1    ; Going to right
  508. l12:
  509.     mov word ptr [bp-12],0    ; Assume going up
  510.     mov ax,[bp+8]        ; Get y1
  511.     sub ax,[bp+12]        ; y1-y2
  512.     jg l13
  513.     mov word ptr [bp-12],1    ; Going down
  514. l13:
  515.  
  516. ;
  517. ; Main Y oriented drawing loop.
  518. ;    ax = pixel value
  519. ;    bx = d
  520. ;    cx = loop control
  521. ;    dx = block number
  522. ;    di = block offset
  523. ;
  524.     mov ax,[bp+14]
  525.     mov es:[di],al        ; Write first pixel
  526.     cmp cx,0        ; Check if done
  527.     je yloopend
  528.  
  529. yloop:
  530.     cmp word ptr [bp-12],0    ; See if going up?
  531.     je l14
  532.     add di,ScanWidth    ; going down
  533.     jnc l15
  534.     inc dx
  535.     push dx
  536.     call vgablock
  537.     pop dx
  538.     jmp l15
  539. l14:
  540.     sub di,ScanWidth    ; going up
  541.     jnc l15
  542.     dec dx
  543.     push dx
  544.     call vgablock
  545.     pop dx
  546. l15:
  547.     cmp bx,0        ; test d<0
  548.     jge l16
  549.     add bx,[bp-14]        ; d = d + incr1
  550.     jmp l18
  551. l16:
  552.     add bx,[bp-16]        ; d = d + incr2
  553.     cmp word ptr [bp-10],0    ; See if going left
  554.     je l17
  555.     inc di            ; Go right
  556.     jnc l18
  557.     inc dx
  558.     push dx
  559.     call vgablock
  560.     pop dx
  561.     jmp l18
  562. l17:
  563.     dec di            ; Go left
  564.     jnc l18
  565.     dec dx
  566.     push dx
  567.     call vgablock
  568.     pop dx
  569. l18:
  570.     mov es:[di],al        ; Write next pixel
  571.     loop yloop
  572. yloopend:
  573.  
  574. ;
  575. ; Clear stack and exit
  576. ;
  577. done:
  578.     add sp,8
  579.     Postfix
  580. vgaline endp
  581.  
  582.  
  583.  
  584. ;
  585. ; Set colors from an array of rgb values.
  586. ;
  587. ; Parameters:
  588. ;    - Array of colors
  589. ;    - Start index
  590. ;    - Number of colors
  591. ;
  592. vgasetcolor proc far
  593.     Prefix
  594.     
  595.     les dx,[bp+6]        ; Get address of colormap
  596.     mov bx,[bp+10]        ; Get first color index
  597.     mov cx,[bp+12]        ; Get Number of indexes
  598.     mov ax,1012h        ; Set block of color registers function
  599.     int 10h
  600.  
  601.     Postfix
  602. vgasetcolor endp
  603.  
  604.  
  605.  
  606. ;
  607. ; Fill a rectangular region with a given pixel value. Region is assumed to
  608. ; start on a even address and be an even width. Width and height values
  609. ; must be positive. Width and height values get modified.
  610. ;
  611. ; Parameters:
  612. ;    - Row for upper left corner
  613. ;    - Column for upper left corner
  614. ;    - Width of rectangle
  615. ;    - Height of rectangle
  616. ;    - Pixel value
  617. ;
  618. ; Locals
  619. ;    [bp-10] LineSkip
  620. ;
  621. vgafill proc far
  622.     Prefix
  623.     sub sp,2
  624. ;
  625.     mov    ax,vgadata    ; Load address of data segment
  626.     mov    ds,ax        ; Set DS register
  627.  
  628. ;
  629. ; Load window pointers
  630. ;
  631.     mov ax,WinAddr
  632.     mov es,ax        ; Set ES to point to video memory
  633.  
  634.     push [bp+8]
  635.     push [bp+6]
  636.     call vgaoffset
  637.     add sp,4
  638.  
  639. ;
  640. ; Setup control parameters for line draw.
  641. ;
  642.     mov bx,ScanWidth
  643.     sub bx,[bp+10]
  644.     mov [bp-10], bx        ; Amount to skip to get to next line
  645.  
  646.     mov di, ax        ; Offset in di
  647.     mov ax,[bp+14]
  648.     mov ah,al        ; ax has duplicated pixel value in al and ah
  649.  
  650.     even
  651. linestart:
  652.     mov cx,BlockEnd        ; Last point in counter
  653.     sub cx,di               ; cx has number of bytes till block change
  654.  
  655.     mov bx,[bp+10]        ; bx has number of bytes in line
  656.     dec bx
  657.  
  658.     cmp bx,cx
  659.     ja l1
  660.     mov cx,bx        ; Won't need a block change
  661. l1:
  662.     sub bx,cx        ; ax has number of words after block change
  663.     inc cx
  664.     ror cx,1
  665.     ror bx,1
  666.  
  667. ;
  668. ; Draw the line
  669. ;
  670.     even
  671. l4:
  672.     cld
  673.     rep stosw
  674.  
  675.     cmp di,0        ; Check for exact alignment
  676.     je l5
  677.     cmp bx,0
  678.     je l6
  679.  
  680. ;
  681. ; Handle block change and continue
  682. ;
  683. l5:
  684.     inc dx
  685.     push dx
  686.     call vgablock
  687.     pop dx
  688.  
  689.     cmp bx,0
  690.     je l6
  691.  
  692.     mov cx,bx
  693.     xor bx,bx
  694.     xor di,di
  695.     jmp l4
  696.  
  697. ;
  698. ; Set up for next line
  699. ;
  700. l6:
  701.     dec word ptr [bp+12]
  702.     je l7
  703.  
  704.     add di,[bp-10]        ; Go to start of next line
  705.     jnc linestart
  706.  
  707.     inc dx            ; Bump block pointer
  708.     push dx
  709.     call vgablock
  710.     pop dx
  711.     jmp linestart
  712.  
  713. ;
  714. ; Finish up
  715. ;
  716. l7:
  717.     add sp,2
  718.     Postfix
  719. vgafill endp
  720.  
  721.  
  722. ;
  723. ; Copy a given rectangle into display memory at the specified address.
  724. ; All pixels from the source rectangle are copied with no masking. 
  725. ; Coordinates are assumed to be correct and wraparound accounted for by
  726. ; the calling routine. The start address and rectangle width are assumed
  727. ; to be even values to permit faster copy. The passed values may be modified
  728. ; and should not be retained by the calling routine.
  729. ;
  730. ; Parameters:
  731. ;    - Far pointer to source rectangle
  732. ;    - Total width of source memory
  733. ;    - Row for upper left corner
  734. ;    - Column for upper left corner
  735. ;    - Width of rectangle
  736. ;    - Height of rectangle
  737. ;
  738. ; Locals
  739. ;    [bp-10] LineSkip
  740. ;
  741. vgarect proc far
  742.     Prefix
  743.     sub sp,2
  744. ;
  745.     mov    ax,vgadata    ; Load address of data segment
  746.     mov    ds,ax        ; Set DS register
  747.  
  748. ;
  749. ; Load window pointers
  750. ;
  751.     mov ax,WinAddr
  752.     mov es,ax        ; Set ES to point to video memory
  753.  
  754.     push [bp+14]
  755.     push [bp+12]
  756.     call vgaoffset
  757.     add sp,4
  758.  
  759. ;
  760. ; Setup control parameters for line draw.
  761. ;
  762.     mov di, ax        ; Offset for output memory in di
  763.  
  764.     mov bx,ScanWidth
  765.     sub bx,[bp+16]
  766.     mov [bp-10], bx        ; Amount to skip to get to next line on output
  767.  
  768.     mov bx,[bp+10]
  769.     sub bx,[bp+16]
  770.     mov [bp+10], bx        ; Amount to go to next line on input data
  771.  
  772.     mov si, [bp+6]        ; Offset for input memory
  773.  
  774.     even
  775. linestart:
  776.     mov cx,BlockEnd        ; Last point in counter
  777.     sub cx,di               ; cx has number of bytes till block change
  778.  
  779.     mov bx,[bp+16]        ; bx has number of bytes in line
  780.     dec bx
  781.  
  782.     cmp bx,cx
  783.     ja l1
  784.     mov cx,bx        ; Won't need a block change
  785. l1:
  786.     sub bx,cx        ; bx has number of words after block change
  787.     inc cx
  788.     ror cx,1
  789.     ror bx,1
  790.  
  791.  
  792. ;
  793. ; Draw the line
  794. ;
  795.     even
  796. l4:
  797.     push ds            ; Save segment for vgadata
  798.     mov ax, [bp+8]
  799.     mov ds,ax        ; Set segment for source rectangle
  800.  
  801.     cld
  802.     rep movsw
  803.  
  804.     pop ds            ; Get segment for vgadata
  805.     cmp di,0        ; Check for exact alignment
  806.     je l5
  807.     cmp bx,0
  808.     je l6
  809.  
  810. ;
  811. ; Handle block change and continue
  812. ;
  813. l5:
  814.     inc dx
  815.     push dx
  816.     call vgablock
  817.     pop dx
  818.  
  819.     cmp bx,0
  820.     je l6
  821.  
  822.     mov cx,bx
  823.     xor bx,bx
  824.     xor di,di
  825.     jmp l4
  826.  
  827. ;
  828. ; Set up for next line
  829. ;
  830. l6:
  831.     dec word ptr [bp+18]
  832.     je l7
  833.  
  834.     add si,[bp+10]        ; Goto next line in input
  835.     add di,[bp-10]        ; Go to start of next line on output
  836.     jnc linestart
  837.  
  838.     inc dx            ; Bump block pointer
  839.     push dx
  840.     call vgablock
  841.     pop dx
  842.     jmp linestart
  843.  
  844. ;
  845. ; Finish up
  846. ;
  847. l7:
  848.     add sp,2
  849.     Postfix
  850. vgarect endp
  851.  
  852.  
  853. vgacode    ends
  854.     end
  855.