;----------------------------vga.asm-------------------------------- ; Modified for CIRRUS bank set and rgb input values 12/30/92 ; ; Title: vga.asm ren vga41.asm ren vga24.asm by Don Lewis ; Date: 6/18/92 ; Author: Randy Buckland (randy@ncsu.edu) ; ; Description: ; This is a VERY basic set of routines to provide high speed SVGA ; graphics for IBM-PC compatibiles that have a VGA interface that supports ; a VESA driver. These routines assume a 256-color mode and will not work ; for any type of mode. The following routines are provided: ; ; vgainit(int vesa_mode) ; vgapoint(int row, int column, int pixel_value) ; vgahline(int row, int start_column, int end_column, int pixel_value) ; vgaline(int x1, int y1, int x2, int y2, int pixel_value) ; vgasetcolor(char *colors, int start, int count) ; vgafill(int row, int column, int width, int height, int pixel_value) ; vgarect(char *source, int source_width, int row, int column, ; int width, int height) ; ;******** ADDED by Don Lewis, (djlewis@ualr.edu or djlewis@spider.ualr.edu) ; This works fine with 8bit VGA. Just pass color in red and rest is ignored. ; The original vgafill() was simply modified and vgapoint probably will be to. ; These modifications works with 8,15,16 and 24 bit VESA modes. ; ; vga_point(int,int,uchar r,uchar g,uchar b) ; vgapoint_rgb(int row, int column, uchar r, uchar g, uchar b) ; vgafill(int,int,int,int,uchar r,uchar g,uchar b) ; vgaline(int,int,int,int,uchar r,uchar g,uchar b) ; .model large,c include macros.asm ; ; Global data for the VGA support routines ; vgadata segment word public 'VGADATA' Block dw 0 ; Current video memory block accessable BlockSz dw 0 ; Size of a video block in K BlockShift dw 0 ; Amount to shift bits by BlockEnd dw 0 ; Last valid address in block BlockMask dw 0 ; Mask used for block/offset operations WinAddr dw 0 ; Segment addr of window A block WinGran dw 0 ; Window Granularity 12/10/92 djl ;WinFunc dd 0 ; Far pointer to windowing function ScanWidth dw 0 ; Width of a scan line BytesPerPixel dw 0 ; BytesPerPixel 12/30/92 djl BitsPerPixel dw 0 ; BitsPerPixel value ShiftMask dw 0 ; pixel shift mask 15 and 16bit modes shift dw 0 ; pixel adjustment 15 and 16 bit modes public screen_width,screen_height screen_width dw 640 ; Width of screen screen_height dw 480 ; Height of screen public mouse_x, mouse_y mouse_x dw 0 mouse_y dw 0 public text_height, text_drop text_height dw 16 text_drop dw 4 vgadata ends vgacode segment word public 'VGACODE' assume cs:vgacode,ds:vgadata ; ; Set current video memory block. This procedure assumes that ds already ; points to the vgadata segment. This routine will not modify any registers. ; ; Parameters: ; - block number to change to ; vgablock proc near push bp mov bp,sp push cx ; stay with no register modification. djl push dx mov dx,[bp+4] ; Start of video memory cmp dx,Block je l1 ;Window Granularity must be used to adjust bank. djl mov cx,WinGran ;BankNum offset adjustment for cards of shl dl,cl ;varying window granularity. djl mov Block,dx push ax push bx mov ax,4f05h ; VESA set memory block mov bx,0000h ; Set window A int 10h pop bx pop ax l1: pop dx pop cx ; stay with no register modification. djl mov sp,bp pop bp ret vgablock endp ; ; Calculate block and offset values for a given row/column. Assumes that ds ; points to vgadata. Does NOT preserve registers. Returns block value in ; dx and offset in ax. ; ; Parameters: ; - row value ; - column value ; vgaoffset proc near push bp mov bp,sp mov ax,[bp+4] ; Get row mul ScanWidth ; Get starting block and offset in dx:ax ; New code for 24bit pixel offset push dx mov bx,ax ; Save old ax xor ax,ax mov ax,[bp+6] ; get column ; mul word PTR BytesPerPixel mul BytesPerPixel and ax,7FFFh add ax,bx ; Add column offset pop dx ;add ax,[bp+6] ; Add start column offset jnc la1 inc dx ; Just crossed block boundery la1: mov cx,BlockShift ; Get block size mask cmp cx,0 ; Is block size 64K? je la2 ; Yes, skip this section mov bx,ax ; Save old ax rol ax,cl and ax,BlockMask ; Save high bits rol dx,cl add dx,ax ; Add high bits to block value. mov ax,bx rol ax,cl or ax,BlockMask ; Set undesirable bits xor ax,BlockMask ; Clear bad bits ror ax,cl ; ; Set active block to calculated block if needed ; la2: cmp dx,Block je la3 push dx call vgablock pop dx la3: mov sp,bp pop bp ret vgaoffset endp ; ; Draw a single point in Red, Green, Blue for 15, 16 and 24 bit colour ; Added by Don Lewis to work with internal functions ; Parameters: ; - Row of point ; - Column of point ; - r,g,b ; ; 24bit format bit pattern 'bbbbbbbbggggggggrrrrrrrr' 3 bytes ; 16bit '00000000bbbbbggggggrrrrr' 2 bytes ; 15bit ' 0bbbbbgggggrrrrr' 2 bytes ; draw_rgb proc near Prefix push bx push cx push dx ; ; Draw point ; cmp BitsPerPixel,24 ; Is it 24bits per pixel jne isit15_16 ; if not goto isit15_16 mov ax,[bp+8] ; al has blue pixel value cld ; clear direction flag to increment stosb ; write a byte in al to address in es:di mov ax,[bp+6] ; al has green pixel value stosb mov ax,[bp+4] ; al has red pixel value stosb jmp fini ; All three bytes written. Finish ; isit15_16: cmp BitsPerPixel,16 ; Is it 16bits per pixel mov Shift,3 ; adjust red bits shift factor mov ShiftMask,255 ; adjust red/green bits mask je drawit ; Go write the color data else its 15bit mov Shift,2 ; adjust for 15bits per pixel mov ShiftMask,127 ; adjust red/green bit mask drawit: mov cl,5 ; shift bits up factor xor ax,ax ; clear reg mov bx,[bp+6] ; get green value and bx,00ffh shl bx,cl ; shift green up 5bits mov ax,[bp+8] ; get blue value and ax,00FFh add ax,bx ; put portion of green with blue cld stosb ; write the blue green value mov ax,[bp+4] ; get red value and ax,00FFh mov cx,Shift ; get 15 or 16 bit shift factor shl ax,cl ; move red to correct position add al,bh ; put remaining green value with red and ax,Shiftmask ; mask unwanted bits stosb ; write the red green value fini: pop dx ; Clean house and leave pop cx pop bx Postfix draw_rgb endp ; ; Initialize the display ; Parameters: ; Mode value to use ; public vgainit vgainit proc far ; ; Set up call frame ; Prefix sub sp,256 ; Make local variable space ; mov ax,vgadata ; Load address of data segment mov ds,ax ; Set DS register ; ; Get VGA information and set desired mode ; mov ax,4f02h ; VESA set mode function mov bx,[bp+6] ; Any mode I want ! int 10h push ss pop es ; Load es with value of ss mov di,sp ; Point index at 256 byte temp space mov cx,[bp+6] mov ax,4f01h ; VESA get Super VGA mode information int 10h mov ax,es:[di+4] ;WinGranularity in k added 12/10/1992 djl mov WinGran,ax mov ax,es:[di+6] ;WinSize in k mov BlockSz,ax mov ax,es:[di+8] mov WinAddr,ax ;WinASegment usually a000h ; mov ax,es:[di+12] ;was rem ed from here by R.B. ; mov word ptr WinFunc,ax ; ; mov ax,es:[di+14] ; ; mov word ptr WinFunc+2,ax ; to here mov ax,es:[di+16] mov ScanWidth,ax ;BytesPerScanLine mov ax,es:[di+25] ;BitsPerPixel added 12/30/92 djl and ax,255 ; djl mov BitsPerPixel,ax ; djl cmp ax,15 ;is it a 15 bit mode? djl jne lb0 ;skip if not 15 bit mode. djl inc al ;else force 15 bit modes to 16 bit modes. djl lb0: ; shr al,3 ;convert BitsPerPixel to BytesPerPixel, djl mov BytesPerPixel,ax ;end of addition 12/30/92 djl ; ; Calculate block shift and end values ; mov ax,BlockSz ;ax = WinSize mov bx,10 mov cx,03ffh lb1: sar ax,1 ;divide ax by 2 inc bx ;bx + 1 sal cx,1 ;multiply cx by 2 inc cx ;cx + 1 cmp ax,1 ;compare ax to 1 ja lb1 ;jump short if above(CF=0 and ZF=0) mov ax,16 sub ax,bx ;ax - bx = ax mov BlockShift, ax mov BlockEnd, cx not cx xchg ax,cx rol ax,cl mov BlockMask,ax ; ; Set to start block ; xor ax,ax push ax call vgablock pop ax ; ; Remove call frame and exit ; add sp,256 Postfix vgainit endp ; ; Draw a single point ; ; Parameters: ; - Row of point ; - Column of point ; - Pixel value to use ; public vgapoint vgapoint proc far Prefix mov ax,vgadata ; Load address of data segment mov ds,ax ; Set DS register ; ; Load window pointers ; mov ax,WinAddr mov es,ax ; Set ES to point to video memory push [bp+8] ; Column push [bp+6] ; Row call vgaoffset add sp,4 ; ; Draw point in 8bit modes ; mov di,ax ; Put offset in index regester mov ax,[bp+10] ; bl has pixel value cld stosb ; Postfix vgapoint endp ; ; Draw a single point Red, Green, Blue. BY Don Lewis ; to be called from external C routine ; ; Parameters: ; - Row of point ; - Column of point ; - r,g,b ; public vgapoint_rgb vgapoint_rgb proc far Prefix mov ax,vgadata ; Load address of data segment mov ds,ax ; Set DS register ; ; Load window pointers ; mov ax,WinAddr ; Get video memory start mov es,ax ; Set ES to point to video memory push [bp+8] ; Column push [bp+6] ; Row call vgaoffset add sp,4 ; ; Draw point ; mov di,ax ; Put offset in index regester push [bp+14] push [bp+12] push [bp+10] call draw_rgb add sp,6 ; mov di,ax ; Put offset in index regester ; cmp BitsPerPixel,24 ; Is it 24bits per pixel ; jne dr1516 ; if not goto dr1516 ; mov ax,[bp+14] ; bl has blue pixel value ; cld ; stosb ; mov ax,[bp+12] ; bl has green pixel value ; stosb ; mov ax,[bp+10] ; bl has red pixel value ; stosb ; jmp finish ;dr1516: ; cmp BitsPerPixel,16 ; Is it 16bits per pixel ; mov Shift,3 ; adjust red bits shift factor ; mov ShiftMask,255 ; adjust red bits mask ; je draw ; mov Shift,2 ; adjust for 15bits per pixel ; mov ShiftMask,127 ;draw: ; mov cl,5 ; shift up factor ; xor ax,ax ; clear reg ; mov bx,[bp+12] ; get green value ; shl bx,cl ; shift green up 5bits ; mov ax,[bp+14] ; get blue value ; add ax,bx ; put portion of green with blue ; cld ; stosb ; write the blue green value ; mov ax,[bp+10] ; get red value ; mov cx,Shift ; get 15 or 16 bit shift factor ; shl ax,cl ; move red to correct position ; add al,bh ; put remaining green value with red ; and ax,Shiftmask ; mask unwanted bits ; stosb ; write the red green value finish: Postfix vgapoint_rgb endp ; ; Draw a horizontal line. Line is assumed to start on even boundry and ; have length be an even value for speed. ; ; Parameters: ; - Row for line ; - Start column ; - End column ; - Pixel value ; public vgahline vgahline proc far Prefix ; mov ax,vgadata ; Load address of data segment mov ds,ax ; Set DS register ; ; Load window pointers ; mov ax,WinAddr mov es,ax ; Set ES to point to video memory push [bp+8] ; Beginning Column push [bp+6] ; Row call vgaoffset add sp,4 ; ; Setup control parameters for line draw. ; mov di, ax ; Offset in di mov ax,[bp+12] ; Pixel color mov ah,al ; ax has duplicated pixel value in bl and bh mov cx,BlockEnd ; Last point in counter sub cx,di ; cx has number of legal bytes-1 mov bx,[bp+10] ; Ending column sub bx,[bp+8] ; bx has number to write - 1 cmp bx,cx ja lc1 mov cx,bx ; Won't need a block change lc1: sub bx,cx ; ax has number of words after block change inc cx ror cx,1 ror bx,1 ; ; Draw the line ; even lc4: cld rep stosw cmp bx,0 je lc5 ; ; Handle block change and continue ; inc dx push dx call vgablock pop dx mov cx,bx xor bx,bx xor di,di jmp lc4 ; ; Finish up ; lc5: Postfix vgahline endp ; ; Draw a line using bresenham's algorithm. ; ; Parameters: ; - x1 ; - y1 ; - x2 ; - y2 ; - Pixel value ; ; Locals: ; [bp-10] DX ; [bp-12] DY ; [bp-14] incr1 ; [bp-16] incr2 ; public vgaline vgaline proc far Prefix sub sp,8 ; mov ax,vgadata ; Load address of data segment mov ds,ax ; Set DS register ; ; Load window pointers ; mov ax,WinAddr mov es,ax ; Set ES to point to video memory push [bp+8] push [bp+6] call vgaoffset add sp,4 mov di,ax ; ; Initialize for line draw ; mov ax,[bp+8] ; Get x1 sub ax,[bp+12] ; Sub x2 jg ld1 ; Skip if positive neg ax ld1: mov [bp-10],ax ; Save DX mov ax,[bp+6] ; Get y1 sub ax,[bp+10] ; sub y2 jg ld2 ; Skip if positive neg ax ld2: mov [bp-12],ax ; Save DY cmp ax,[bp-10] ; See if DY>DX jle xline ; Go do X oriented version jmp yline ; Go do Y oriented version ; ; X oriented version of draw line. Slope must be between -1 and 1 inclusive ; xline: mov cx, [bp-10] ; cx has increment control sal ax,1 ; DY*2 mov [bp-14],ax ; Save incr1 sub ax,[bp-10] ; 2*dy - dx mov bx,ax ; bx has D value mov ax,[bp-12] ; Get DY sub ax,[bp-10] ; (DY-DX) sal ax,1 ; 2*(DY-DX) mov [bp-16],ax ; Save incr2 mov word ptr [bp-10],0 ; Assume going to left mov ax,[bp+8] ; Get x1 sub ax,[bp+12] ; x1-x2 jg ld3 mov word ptr [bp-10],1 ; Going to right ld3: mov word ptr [bp-12],0 ; Assume going up mov ax,[bp+6] ; Get y1 sub ax,[bp+10] ; y1-y2 jg ld5 mov word ptr [bp-12],1 ; Going down ld5: ; ; Main X oriented drawing loop. ; ax = pixel value ; bx = d ; cx = loop control ; dx = block number ; di = block offset ; cmp BitsPerPixel,8 ; If 8bit mode continue else goto jne drwrgb1 ; draw_rgb routine mov ax,[bp+14] mov es:[di],al ; Write first pixel jmp ldd5 drwrgb1: push [bp+18] push [bp+16] push [bp+14] call draw_rgb add sp,6 ldd5: cmp cx,0 ; Check if done je xloopend xloop: cmp word ptr [bp-10],0 ; See if going left? je ld7 ; inc di ; going right add di,BytesPerPixel jnc ld8 inc dx push dx call vgablock pop dx jmp ld8 ld7: ; dec di ; going left sub di,BytesPerPixel jnc ld8 dec dx push dx call vgablock pop dx ld8: cmp bx,0 ; test d<0 jge ld9 add bx,[bp-14] ; d = d + incr1 jmp ld11 ld9: add bx,[bp-16] ; d = d + incr2 cmp word ptr [bp-12],0 ; See if going up je ld10 add di,ScanWidth ; Go to next line jnc ld11 inc dx push dx call vgablock pop dx jmp ld11 ld10: sub di,ScanWidth ; Go to previous line jnc ld11 dec dx push dx call vgablock pop dx ld11: cmp BitsPerPixel,8 ; If 8bit continue else jne drwrgb2 ; call draw_rgb mov es:[di],al ; Write next pixel jmp ldd11 drwrgb2: push [bp+18] push [bp+16] push [bp+14] call draw_rgb add sp,6 ldd11: loop xloop xloopend: jmp done ; ; Y oriented version of draw line. Slope must be outside -1 and 1 inclusive ; yline: mov cx, [bp-12] ; cx has increment control mov ax, [bp-10] sal ax,1 ; DX*2 mov [bp-14],ax ; Save incr1 sub ax,[bp-12] ; 2*dx - dy mov bx,ax ; bx has D value mov ax,[bp-10] ; Get DX sub ax,[bp-12] ; (DX-DY) sal ax,1 ; 2*(DX-DY) mov [bp-16],ax ; Save incr2 mov word ptr [bp-10],0 ; Assume going to left mov ax,[bp+8] ; Get x1 sub ax,[bp+12] ; x1-x2 jg ld12 mov word ptr [bp-10],1 ; Going to right ld12: mov word ptr [bp-12],0 ; Assume going up mov ax,[bp+6] ; Get y1 sub ax,[bp+10] ; y1-y2 jg ld13 mov word ptr [bp-12],1 ; Going down ld13: ; ; Main Y oriented drawing loop. ; ax = pixel value ; bx = d ; cx = loop control ; dx = block number ; di = block offset ; cmp BitsPerPixel,8 ; Is it 8bit mode jne drwrgb3 ; no. call draw_rgb mov ax,[bp+14] mov es:[di],al ; Write first pixel jmp ldd13 drwrgb3: push [bp+18] push [bp+16] push [bp+14] call draw_rgb add sp,6 ldd13: cmp cx,0 ; Check if done je yloopend yloop: cmp word ptr [bp-12],0 ; See if going up? je ld14 add di,ScanWidth ; going down jnc ld15 inc dx push dx call vgablock pop dx jmp ld15 ld14: sub di,ScanWidth ; going up jnc ld15 dec dx push dx call vgablock pop dx ld15: cmp bx,0 ; test d<0 jge ld16 add bx,[bp-14] ; d = d + incr1 jmp ld18 ld16: add bx,[bp-16] ; d = d + incr2 cmp word ptr [bp-10],0 ; See if going left je ld17 ; inc di ; Go right add di,BytesPerPixel jnc ld18 inc dx push dx call vgablock pop dx jmp ld18 ld17: ; dec di ; Go left sub di,BytesPerPixel jnc ld18 dec dx push dx call vgablock pop dx ld18: cmp BitsPerPixel,8 ; Is it 8bit mode jne drwrgb4 mov es:[di],al ; Write next pixel jmp ld18 drwrgb4: push [bp+18] push [bp+16] push [bp+14] call draw_rgb add sp,6 ldd18: loop yloop yloopend: ; ; Clear stack and exit ; done: add sp,8 Postfix vgaline endp ; ; Set colors from an array of rgb values. ; ; Parameters: ; - Array of colors ; - Start index ; - Number of colors ; public vgasetcolor vgasetcolor proc far Prefix les dx,[bp+6] ; Get address of colormap mov bx,[bp+10] ; Get first color index mov cx,[bp+12] ; Get Number of indexes mov ax,1012h ; Set block of color registers function int 10h Postfix vgasetcolor endp ; ; Fill a rectangular region with a given pixel value. Region is assumed to ; start on a even address and be an even width. Width and height values ; must be positive. Width and height values get modified. ; ; Parameters: ; - Row for upper left corner ; - Column for upper left corner ; - Width of rectangle ; - Height of rectangle ; - Pixel value ; ; Locals ; [bp-10] LineSkip ; public vgafill vgafill proc far Prefix sub sp,2 ; mov ax,vgadata ; Load address of data segment mov ds,ax ; Set DS register ; ; Load window pointers ; mov ax,WinAddr mov es,ax ; Set ES to point to video memory push [bp+8] push [bp+6] call vgaoffset add sp,4 mov di, ax ; Offset in di ; ; Setup control parameters for line draw. ; mov bx,ScanWidth ; Get BytesPerScanLine ; push dx ; save for later ; added 1/2/92, djl, Adjust line offset value mov ax,[bp+10] ; added to adjust for 15 16 or 24bit modes mul BytesPerPixel ; columns times BytesPerPixel, djl sub bx,ax ; mov [bp-10], bx ; Amount to skip to get to next line mov ax,[bp+14] ; Get 8bit pixel value mov ah,al ; ax has duplicated pixel value in al and ah pop dx even linestart: mov cx,BlockEnd ; Last point in counter sub cx,di ; cx has number of bytes till block change ; mov bx,[bp+10] ; bx has number of bytes in line cmp BitsPerPixel,8 ; If 8bit mode skip counter adjustment, djl je lee1 ; skip if 8bit, djl shl bx,1 ; else multiply width of fill by two, djl lee1: dec bx ; cmp bx,cx ; ja le1 mov cx,bx ; Wont need a block change le1: sub bx,cx ; ax has number of words after block change inc cx ror cx,1 ror bx,1 ; ; Draw the line ; even le4: cmp BitsPerPixel,8 jne drwit cld rep stosw jmp lee4 drwit: ; mov cx,[bp+10] loopit: push [bp+18] push [bp+16] push [bp+14] call draw_rgb add sp,6 add di,BytesPerPixel loop loopit lee4: cmp di,0 ; Check for exact alignment je le5 cmp bx,0 je le6 ; ; Handle block change and continue ; le5: inc dx push dx call vgablock pop dx cmp bx,0 je le6 mov cx,bx xor bx,bx xor di,di jmp le4 ; ; Set up for next line ; le6: dec word ptr [bp+12] je le7 add di,[bp-10] ; Go to start of next line jnc linestart inc dx ; Bump block pointer push dx call vgablock pop dx jmp linestart ; ; Finish up ; le7: add sp,2 Postfix vgafill endp ; ; Copy a given rectangle into display memory at the specified address. ; All pixels from the source rectangle are copied with no masking. ; Coordinates are assumed to be correct and wraparound accounted for by ; the calling routine. The start address and rectangle width are assumed ; to be even values to permit faster copy. The passed values may be modified ; and should not be retained by the calling routine. ; ; Parameters: ; - Far pointer to source rectangle ; - Total width of source memory ; - Row for upper left corner ; - Column for upper left corner ; - Width of rectangle ; - Height of rectangle ; ; Locals ; [bp-10] LineSkip ; public vgarect vgarect proc far Prefix sub sp,2 ; mov ax,vgadata ; Load address of data segment mov ds,ax ; Set DS register ; ; Load window pointers ; mov ax,WinAddr mov es,ax ; Set ES to point to video memory push [bp+14] push [bp+12] call vgaoffset add sp,4 ; ; Setup control parameters for line draw. ; mov di, ax ; Offset for output memory in di mov bx,ScanWidth sub bx,[bp+16] mov [bp-10], bx ; Amount to skip to get to next line on output mov bx,[bp+10] sub bx,[bp+16] mov [bp+10], bx ; Amount to go to next line on input data mov si, [bp+6] ; Offset for input memory even flinestart: mov cx,BlockEnd ; Last point in counter sub cx,di ; cx has number of bytes till block change mov bx,[bp+16] ; bx has number of bytes in line dec bx cmp bx,cx ja lf1 mov cx,bx ; Won't need a block change lf1: sub bx,cx ; bx has number of words after block change inc cx ror cx,1 ror bx,1 ; ; Draw the line ; even lf4: push ds ; Save segment for vgadata mov ax, [bp+8] mov ds,ax ; Set segment for source rectangle cld rep movsw pop ds ; Get segment for vgadata cmp di,0 ; Check for exact alignment je lf5 cmp bx,0 je lf6 ; ; Handle block change and continue ; lf5: inc dx push dx call vgablock pop dx cmp bx,0 je lf6 mov cx,bx xor bx,bx xor di,di jmp lf4 ; ; Set up for next line ; lf6: dec word ptr [bp+18] je lf7 add si,[bp+10] ; Goto next line in input add di,[bp-10] ; Go to start of next line on output jnc flinestart inc dx ; Bump block pointer push dx call vgablock pop dx jmp flinestart ; ; Finish up ; lf7: add sp,2 Postfix vgarect endp ; ; Copy a given rectangle into display memory at the specified address. ; All pixels from the source rectangle are copied unless they have the ; value 0. Coordinates are assumed to be correct and wraparound accounted ; for by the calling routine. The passed values may be modified ; and should not be retained by the calling routine. ; ; Parameters: ; - Far pointer to source rectangle ; - Total width of source memory ; - Row for upper left corner ; - Column for upper left corner ; - Width of rectangle ; - Height of rectangle ; ; Locals ; [bp-10] LineSkip ; public vgarect2 vgarect2 proc far Prefix sub sp,2 ; mov ax,vgadata ; Load address of data segment mov ds,ax ; Set DS register ; ; Load window pointers ; mov ax,WinAddr mov es,ax ; Set ES to point to video memory push [bp+14] push [bp+12] call vgaoffset add sp,4 ; ; Setup control parameters for line draw. ; mov di, ax ; Offset for output memory in di mov bx,ScanWidth sub bx,[bp+16] mov [bp-10], bx ; Amount to skip to get to next line on output mov bx,[bp+10] sub bx,[bp+16] mov [bp+10], bx ; Amount to go to next line on input data mov si, [bp+6] ; Offset for input memory even glinestart: mov cx,BlockEnd ; Last point in counter sub cx,di ; cx has number of bytes till block change mov bx,[bp+16] ; bx has number of bytes in line dec bx cmp bx,cx ja lg1 mov cx,bx ; Won't need a block change lg1: sub bx,cx ; bx has number of bytes after block change inc cx ; ; Draw the line ; even lg4: push ds ; Save segment for vgadata mov ax, [bp+8] mov ds,ax ; Set segment for source rectangle cld lg8: lodsb or al,al ; Test for 0 jz lg9 stosb jmp lg10 lg9: inc di lg10: loop lg8 pop ds ; Get segment for vgadata cmp di,0 ; Check for exact alignment je lg5 cmp bx,0 je lg6 ; ; Handle block change and continue ; lg5: inc dx push dx call vgablock pop dx cmp bx,0 je lg6 mov cx,bx xor bx,bx xor di,di jmp lg4 ; ; Set up for next line ; lg6: dec word ptr [bp+18] je lg7 add si,[bp+10] ; Goto next line in input add di,[bp-10] ; Go to start of next line on output jnc glinestart inc dx ; Bump block pointer push dx call vgablock pop dx jmp glinestart ; ; Finish up ; lg7: add sp,2 Postfix vgarect2 endp ; ; Handle mouse and keyboard I/O ; If a keyboard key or mouse button is pressed, return a value indicating ; what was pressed. Also, maintain the mouse position values for external ; reference. ; vgagetbutton proc far mov ah,0 int 16h xor ah,ah ; Don't want scan code ret vgagetbutton endp ; ; Display a text string at a given location ; ; Parameters: ; - row ; - column ; - character string ; - pixel value for foreground ; vgatext proc far ret vgatext endp vgacode ends end