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

📄 llvga.asm

📁 [随书类]Dos6.0源代码
💻 ASM
📖 第 1 页 / 共 3 页
字号:
;	current attribute.  This is identical to SetC_13 except that
;	this routine assumes ES is set to video segment.
;Entry:
;	ES = video segment (set up by b$SetPixFirstC)
;	b$OffC specifies pixel to set
;	b$AttrC = attribute to use
;Exit:
;	None
;Uses:
;	per conv.
;Exceptions:
;******************************************************************************
DbPub	SetPixC_13
cProc	SetPixC_13,<NEAR>
cBegin
	mov	al,b$AttrC	;[al] = attribute
	mov	bx,b$OffC	;[BX] = cursor offset
				;[ES] = setup by SetPixFirstC
	mov	es:[bx],al	;set color value
cEnd

;NOTE:	SetPixFirstC, SetPixLastC use CGA

;***
; LineX_13
;
;Purpose:
;	Draw an X-major line for Screen 13.
;Entry:
;	AH    = color (b$AttrC)
;	AL    = bit accumulator (0)
;	BX    = major axis delta update value (Incr1)
;	CX    = point count
;	DX    = BP change for Y movement
;	SI    = delta decision value
;	DI    = line style
;	BP    = video offset
;	ES    = video segment
;	Incr2 = minor axis delta update value
;Exit:
;	None
;Uses:
;	per conv.
;Exceptions:
;******************************************************************************
DbPub	LineX_13
cProc	LineX_13,<NEAR>
cBegin
	mov	bx,b$Incr1	;to register here

Line13Xloop:

	ROL	DI,1		;next line style bit
	JNC	Line13X2	;go if bit is 0 not to plot

	mov	es:[bp],ah	;set this pixel
Line13X2:
	OR	SI,SI		;time to move in Y (+ or 0 delta)?
	JNS	Line13X4	;go if so
	ADD	SI,BX		;update delta for X movement
	INC	BP		;go to next byte
	loop	Line13Xloop
	ret
Line13X4:
	ADD	SI,b$Incr2	;update delta for Y movement
	inc	bp		;move to next X
	add	BP,DX		;move to next Y
	loop	Line13Xloop	;go for more
cEnd

;***
; LineY_13
;
;Purpose:
;	Draw a Y-major line for Screen 13.
;Entry:
;	AH    = color (b$AttrC)
;	BX    = major axis delta update value (Incr1)
;	CX    = point count
;	DX    = BP change for Y movement (swapped with IncrY)
;	SI    = delta decision value
;	DI    = line style
;	BP    = video offset
;	ES    = video segment
;	Incr2 = minor axis delta update value
;Exit:
;	None
;Uses:
;	per conv.
;Exceptions:
;******************************************************************************
DbPub	LineY_13
cProc	LineY_13,<NEAR>
cBegin
	mov	bx,b$Incr1	;to register here

Line13Yloop:

	ROL	DI,1		;next line style bit
	JNC	Line13Y2	 ;go if bit is 0 not to plot

	mov	es:[bp],ah	;set this pixel
Line13Y2:
	OR	SI,SI		;time to move in X (+ or 0 delta)?
	JNS	Line13Y3	;go if so
	ADD	SI,BX		;update delta for Y movement
	ADD	BP,DX		;move to next Y
	loop	Line13Yloop
	ret
Line13Y3:
	ADD	SI,b$Incr2	;update delta for X movement
	inc	bp		;move to next X
	add	BP,DX		;move to next Y
	loop	Line13Yloop	;go for more
cEnd

;***
; LineV_13
;
;Purpose:
;	Draw a vertical line for Screen 13.
;Entry:
;	AH    = color (b$AttrC)
;	CX    = point count
;	DX    = BP change for Y movement
;	SI    = IncrY = BP change for Y movement
;	DI    = line style
;	BP    = video offset
;	ES    = video segment
;Exit:
;	None
;Uses:
;	per conv.
;Exceptions:
;******************************************************************************
DbPub	LineV_13
cProc	LineV_13,<NEAR>
cBegin
	MOV	SI,b$IncrY	;to register here

Line13Vloop:

	ROL	DI,1		;next line style bit
	JNC	Line13V2	;go if bit is 0 not to plot

	mov	es:[bp],ah	;set this pixel
Line13V2:
	ADD	BP,DX		;to next Y
	LOOP	Line13Vloop	;go for more
cEnd

labelW	PutTable_13		;Put Vectors according to put action value
	DW	PutOr_13, PutAnd_13, PutPreset_13, B$BumpDS ,PutXor_13 
	;B$BumpDS entry is signal for PSET to use faster movsb and
	;becomes the array segment bumper for NRWMove

;***
; PutAction_13
;
;Purpose:
;	Set b$PutVector to appropriate PUT action routine for Screen 13.
;	Requested action is used to index into a table of entry points.
;Entry:
;	AL = PUT action [0..4] representing (OR, AND, PRESET, PSET, XOR)
;Exit:
;	b$PutVector set to entry point of appropriate PUT action routine
;Uses:
;	per conv.
;Exceptions:
;******************************************************************************
DbPub	PutAction_13
cProc	PutAction_13,<NEAR>
cBegin
	xor	ah,ah		;make word index
	shl	ax,1
	mov	bx,ax
	mov	ax,cs:PutTable_13[BX]	;get our vector
	mov	b$PutVector,ax ;save it
cEnd

	ASSUME	DS:NOTHING

;***
; NReadL_13
;
;Purpose:
;	Read a line of pixels from the screen to an array for Screen 13.
;Entry:
;	DS:SI = screen address
;	ES:DI = array address
;	BP    = count of bits (not pixels) to read
;Exit:
;	ES:DI = updated to array byte past point filled
;Uses:
;	per conv.
;Exceptions:
;******************************************************************************
DbPub	NReadL_13
cProc	NReadL_13,<NEAR>
cBegin
	mov	cx,bp		;convert bit count to byte count in cx
	shr	cx,1
	shr	cx,1
	shr	cx,1

	mov	bx,GR_TEXTOFFSET B$BumpES  ;array segment bumper
	mov	dx,di		;dx = array offset
NRWMove:			
	neg	dx		;compute space remaining in array's segment
	cmp	cx,dx		;enough room?
	ja	NRdOvl		;go if not, segment will overflow
NRWNoOvl:			
    rep movsb			;move remainder
cEnd

NRdOvl: 			
	sub	cx,dx		;compute overflow count
	xchg	cx,dx		;use remaining segment space as move count
    rep movsb			;move to end of segment
	xchg	cx,dx		;use overflow count for second move
	;NOTE: only two moves are required since a MODE 13 screen is < 64K
	;	  and could only cross one segment boundary
	call	bx		;move array pointer over segment boundary
	jmp	short NRWNoOvl	

;***
; NWriteL_13
;
;Purpose:
;	Write a line of pixels from an array to the screen for Screen 13.
;Entry:
;	ES:DI = screen address
;	DS:SI = array address
;	BP    = count of bits (not pixels) to write
;Exit:
;	DS:SI = updated to array byte past point used
;Uses:
;	per conv.
;Exceptions:
;******************************************************************************
DbPub	NWriteL_13
cProc	NWriteL_13,<NEAR>
cBegin
.erre	ID_SSEQDS		;assumes ss = ds
	mov	bx,ss:[b$PutVector]	;preload the put routine address
	mov	dx,si		;dx = array offset for NRWMove
	mov	cx,bp		;convert bit count to byte count in cx
	shr	cx,1
	shr	cx,1
	shr	cx,1
	cmp	bx,GR_TEXTOFFSET B$BumpDS  ;is this for PSET?
	jz	NRWMove 	;go if so
NWrLoop13:
	lodsb			;load byte from array
	or	si,si		;array pointer overflowed to next segment?
	jz	NWrOvfl2	;go if so
	jmp	bx		;put the byte
;
;The following Put routines perform the actual logical operation where
;	[AL]	= data value
;	[ES:DI] = screen address
;
;
; PutAnd_13
;
PutAnd_13:
	and	es:[di],al	;AND WITH SCREEN
	jmp	short PutEnd
;
; PutOr_13
;
PutOr_13:
	or	es:[di],al	;OR WITH SCREEN
	jmp	short PutEnd
;
; PutPreset_13
;
PutPreset_13:
	not	al		;NEGATE DATA FOR PRESET
	stosb			;set screen pixel
	jmp	short PutEnd2
;
; PutXor_13
;
PutXor_13:
	xor	es:[di],al	;XOR WITH SCREEN
PutEnd:
	inc	di
PutEnd2:
	loop	NWrLoop13
cEnd

NWrOvfl2:			
	call	B$BumpDS	;move array pointer over segment boundary
	jmp	bx		;put the byte

	ASSUME	DS:DGROUP

;***
; NSetC_13
;
;Purpose:
;	Set a horizontal line of pixels to the current attribute for
;	Screen 13.  The line starts at the current cursor position
;	and moves right.
;Entry:
;	b$AddrC specifies start pixel
;	b$AttrC specifies attribute to use
;	BX = pixel count
;Exit:
;	None
;Uses:
;	per conv.
;Exceptions:
;******************************************************************************
DbPub	NSetC_13
cProc	NSetC_13,<NEAR>,<ES,DI>
cBegin
	les	di,b$AddrC	;graphics cursor address
	mov	al,b$AttrC	;al = attribute
	mov	cx,bx		;cx = pixel count
	rep	stosb		;block write full bytes
NSetExit:
cEnd

;***
; PaintBound_13
;
;Purpose:
;	Called by PAINT before painting each scan line to facilitate
;	fast viewport edge detection.  Set VIEW left and right cursor
;	addresses.
;Entry:
;	b$OffC specifies current cursor position
;Exit:
;	B$LEOFST = left edge offset
;	B$REOFST = right edge offset
;Uses:
;	per conv.
;Exceptions:
;******************************************************************************
DbPub	PaintBound_13
cProc	PaintBound_13,<NEAR>
cBegin
	MOV	AX,b$OffC	 ;get cursor position

;  Compute the addr of the 1st pixel on the line by computing the
;  line number and then multiplying by BytesPerRow
;	LineNumber = INT(OffC/BytesPerRow)
;	first pixel in line = LineNumber * BytesPerRow

	xor	dx,dx
	MOV	cx,320		;LineNumber = INT(OffC/BytesPerRow)
	DIV	cx
	mov	bx,ax		;multiply y by 320 to compute row displacement
	shl	ax,1		;dx=2*Y
	shl	ax,1		;dx=4*Y
	add	ax,bx		;dx=5*Y
	mov	cl,6		
	shl	ax,cl		;dx=5*Y*64=320*Y
	mov	dx,ax

;  b$OffC addr of 1st pixel in current row is now in DX - compute boundries

	MOV	AX,B$VLOFST
	ADD	AX,DX
	MOV	B$LEOFST,AX	;Left margin= (x1,0)+b$OffC
	add	dX,B$VROFST
	MOV	B$REOFST,dx	;Right margin= (x2,0)+b$OffC
cEnd

;NOTE:	SetTile use CGA

;***
; ScanL_13
;
;Purpose:
;	For Screen 13, scan left beginning with the pixel to the left
;	of cursor, and paint pixels until:
;		(1) the viewport edge is encounteered (edge painted)
;		(2) a border pixel is encountered (border not painted)
;
;Entry:
;	b$AddrC       = pixel to right of starting pixel
;	b$PaintBorder = attribute of paint region border
;	b$AttrC       = attribute to paint
;	B$LEOFST        = left viewport edge
;Exit:
;	BX	       = number of pixels scanned
;	CL	       = 0 iff no pixels changed color
;	b$OffC        = the last non-border pixel examined/painted
;Uses:
;	per conv.
;Exceptions:
;******************************************************************************
DbPub	ScanL_13
cProc	ScanL_13,<NEAR>,<DX,DI,ES>
cBegin
	les	di,b$AddrC	;di=cursor offset, es=video seg
	mov	dl,b$PaintBorder   ;dl=border attribute
	mov	dh,b$AttrC	;dh=paint attribute
	xor	cx,cx		;cx=clear already-painted-flag
	xor	bx,bx		;bx=clear paint count

;	The registers are set up and used as follows:
;	ES:DI = Video segment address (b$AddrC)
;	DL    = border attribute
;	DH    = paint attribute
;	CL    = already painted flag
;	AL    = screen byte
;	BX    = paint count

;	Scan left beginning with the pixel to the left of the cursor,
;	and paint pixels until:
;		1. edge of screen/VIEWPORT is encountered (edge painted)
;		2. a border pixel is encountered (border not painted)

SL13Loop:
	cmp	di,B$LEOFST	;are we at left viewport edge?
	je	SL13Edge	;exit if so, can't go left
	dec	di		;move left one byte
	mov	al,es:[di]	;get the screen byte
	cmp	al,dl		;screen byte == border?
	je	SL13Border	;go if border
	xor	al,dh		;AL = 0 if screen byte == paint attribute
	or	cl,al		;set the already-painted-flag
	inc	bx		;increment paint count
	jmp	short SL13Loop	;keep going
SL13Border:
	inc	di		;back up away from the border
SL13Edge:
	mov	b$OffC,di	;paint start point
	or	bx,bx		;any pixels to paint
	jz	SL13NoSet	;go if none
	push	bx		
	push	cx		
	call	NSetC_13	;paint 'em all at once (and tile)
	pop	cx		
	pop	bx		
SL13NoSet:			

;	Scan encountered a border pixel or viewport edge,
;	now exit with:
;		BX = number of pixels scanned
;		CL = 0 iff no pixels changed color

cEnd

;***
; ScanR_13
;
;Purpose:
;	For Screen 13, starting with the current pixel, search right until:
;		(1) a non-border pixel is found
;		(2) [DX] pixels have been tested
;		(3) the viewport edge is encountered
;
;	If (2) or (3) terminated the scan, exit with:
;		DX = remaining border bount = 0
;
;	If (1) terminated the scan, scan and paint non-border pixels until:
;		(1) the viewport edge is encountered (edge painted)
;		(2) a border pixel is encountered (border not painted)
;
;Entry:
;	DX	       = count of border pixels which may be skipped
;	b$AddrC       = starting pixel
;	b$PaintBorder = attribute of paint region border
;	b$AttrC       = attribute to paint
;	B$REOFST        = right viewport edge
;Exit:
;	BX	       = number of pixels painted
;			    (whether or not they changed color)
;	CL	       = 0 iff no pixels changed color
;	DX	       = remaining border pixel count
;	b$OffC        = the last non-border pixel examined/painted
;	SI, AL	       = the first non-border pixel encountered
;Uses:
;	per conv.
;Exceptions:
;******************************************************************************
DbPub	ScanR_13
cProc	ScanR_13,<NEAR>,<DI,BP,ES>
cBegin
	mov	bx,dx		;bx=skip count
	les	di,b$AddrC	;di=cursor offset, es=video seg
	mov	dl,b$PaintBorder   ;dl=border attribute
	mov	dh,b$AttrC	;dh=paint attribute
	xor	cx,cx		;cl=clear already-painted-flag

;	The registers are set up as follows:
;	ES:DI = Video segment address (b$AddrC)
;	DL = border attribute
;	DH = paint attribute
;	CL = already painted flag
;	AL = screen byte

;	Starting with the current pixel, scan right until:
;		1. [BX] pixels have been tested
;		2. edge of screen/VIEWPORT is encountered
;		3. a non-BORDER pixel is found

SR13Loop1:
	mov	al,es:[di]	;get screen byte
	cmp	al,dl		;screen byte == border?
	jnz	SR13Paint	;go if not
	dec	bx		;decrement border count
	jz	SR13NoCnt	;brif border count zero
	inc	di		;move right one pixel
	cmp	di,B$REOFST	;past viewport edge?
	jbe	SR13Loop1	;go if not, keep scanning
	dec	di		;back to edge
	xor	bx,bx		;pretend to run out of skip count
SR13NoCnt:

;	[BX] pixels have been tested, or the viewport edge encountered,
;	now exit with:
;		BX = number of pixels painted = 0
;		CL = already painted flag     = 0
;		DX = border count	      = 0

	mov	dx,bx		;return skip count = 0, and no pixels painted
	jmp	short SR13Exit	;go exit

;	Original scan encountered a non-border pixel.
;	Now scan and paint non-border pixels until:
;		1. edge of screen/VIEWPORT is encountered (edge painted)
;		2. a border pixel is encountered (border not painted)

SR13Paint:
	mov	b$SaveCa,di	;saving _bSaveCa
	mov	b$OffC,di	;set the cursor offset for paint start
	push	bx		;save border count
	xor	bx,bx		;clear paint count
SR13Loop2:
	cmp	di,B$REOFST	;past viewport edge?
	ja	SR13Edge	;go if so
	mov	al,es:[di]	;[al] = screen byte
	cmp	al,dl		;screen byte == border?
	je	SR13Border	;go if so
	XOR	al,DH		;detect any differences from paint color
	OR	cl,al		;combine with the already painted flag
	inc	bx		;increment paint count
	INC	DI		;move right by one byte
	JMP	SHORT SR13Loop2 ;keep scanning and counting
SR13Edge:
	dec	di		;back up
SR13Border:
	or	bx,bx		;any pixels to paint
	jz	SR13NoSet	;go if none
	push	bx		
	push	cx		
	call	NSetC_13	;paint 'em all at once (and tile)
	pop	cx		
	pop	bx		
SR13NoSet:			
	pop	dx		;return skip count

;	Second scan encountered a border pixel or viewport edge,
;	now exit with:
;		BX = count of pixels painted
;		     (whether or not they changed color)
;		CL = 0 iff no pixels changed color
;		DX = count of BORDER pixels searched in the first search
;		b$OffC = the last pixel examined/painted
;		SI = specifies the first non-BORDER pixel encountered

SR13Exit:
	mov	b$OffC,di	;return cursor offset
	mov	si,b$SaveCa	;returning b$SaveCa
cEnd

;***
; B$xINITVGA - initialize VGA modes
;
;Purpose:
;	Added with revision [10].
;	Put the addresses of VGA screen mode support routines into the
;	dispatch table used by the screen statement.
;
;Entry:
;	None
;Exit:
;	ScreenTab updated
;Uses:
;	None
;Exceptions:
;******************************************************************************
cProc	B$xINITVGA,<FAR,PUBLIC> 
cBegin
	MOV	WORD PTR [b$ScreenTab + (11*2) + 1],OFFSET B$Screen11
	MOV	WORD PTR [b$ScreenTab + (12*2) + 1],OFFSET B$Screen12
	MOV	WORD PTR [b$ScreenTab + (13*2) + 1],OFFSET B$Screen13
cEnd

sEnd	GR_TEXT

	END

⌨️ 快捷键说明

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