home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Media Share 9
/
MEDIASHARE_09.ISO
/
graphics
/
vesa24_2.zip
/
VGA24_2.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-04-09
|
26KB
|
1,272 lines
;----------------------------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