⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vga24_2.asm

📁 汇编小程序.TOO.初学者用还行,大虾勿扰!1VESA24_2asm.rar
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;----------------------------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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -