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

📄 llcgasup.asm

📁 [随书类]Dos6.0源代码
💻 ASM
📖 第 1 页 / 共 3 页
字号:
cBegin
	mov	ah,[si] 	;preload byte from array
	inc	si
	jnz	NWrOvfl1	
	call	B$BumpDS	;move array pointer over segment boundary
NWrOvfl1:
	ror	ax,cl		;align to video
	add	bp,cx
	sub	bp,8		;account for first partial byte
	jbe	NWrLast 	;go if last byte
.erre	ID_SSEQDS		;assumes ss = ds
	call	ss:[b$PutVector]   ;put the byte
	mov	dh,0FFH 	;mask for whole bytes in the middle
.erre	ID_SSEQDS		;assumes ss = ds
	mov	bx,ss:[PutVectorM]  ;preload the "full mask" put routine
	jmp	short NWrLoop2	;go for more bytes
NWrLoop:
	jmp	bx		;vector to put the byte
;
;The following Put routines are identical to those documented above but
;are optimized for the middle loop where the mask is always 0FFH
;
;
; PutAndM:
;
PutAndM:
	and	es:[di],ah	;AND WITH SCREEN
	jmp	short PutEnd
;
; PutOrM:
;
PutOrM:
	or	es:[di],ah	;OR WITH SCREEN
	jmp	short PutEnd
;
; PutPresetM/PutPsetM
;
PutPresetM:
	not	ah		;NEGATE DATA FOR PRESET
PutPsetM:
	mov	es:[di],ah	;store data for PSET
	jmp	short PutEnd
;
; PutXorM
;
PutXorM:
	xor	es:[di],ah	;OR WITH SCREEN
PutEnd:
	inc	di		;bump to next screen byte
;
NWrLoop2:
	rol	ax,cl		;re-align to array
	lodsb			;fill ax word with array bytes
	or	si,si		;did pointer overflow segment?
	jz	NWrOvfl3	;go if so
NWrOvfl2:
	xchg	ah,al		
	ror	ax,cl		;align to video
	sub	bp,8		;8 bits done
	ja	NWrLoop 	;go if bit count not exhausted
	add	bp,8		;restore BP to #bits in last byte
	cmp	cx,bp		;did we use any of the second byte?
	jb	NWrLast 	;go if so
	or	si,si		;at start of segment?
	jnz	NWrUnfl 	;go if not
	call	B$DecDS	;backup to previous segment
NWrUnfl:			
	dec	si		;move ptr back
NWrLast:
	and	dh,dl		;combine first|middle mask with end mask
.erre	ID_SSEQDS		;assumes ss = ds
	call	ss:[b$PutVector]   ;put the byte
cEnd

NWrOvfl3:			
	call	B$BumpDS	;move array pointer over segment boundary
	jmp	short NWrOvfl2	;back to loop

	ASSUME	DS:DGROUP

;***
; B$CgaNSetC
;
;Purpose:
;	Set a horizontal line of pixels to the current attribute for CGA
;	modes.	The line starts at the current cursor position and moves right.
;
;	Discussion of QCG tiling:
;	Mode 6 tiling is relatively simple; to preserve the background
;	pixels just AND the cursor mask with the byte at BKG_MASK[B$TILNDX].
;	Mode 4/5 tiling is hairy because the fill mask is 8 pixels wide.
;	This covers two bytes per row, which is wider than the current
;	paint tiling code can do.  Because QCG only lets the user supply
;	the pixel on/off mask, as opposed to the actual pixel values, the
;	tile_mask and b$AttrC values are the same for both bytes (actually,
;	for all bytes, in CGA modes).  Only the bkg_mask has to be 16-bits
;	wide -- each row takes two consecutive bytes of bkg_mask.
;
;Entry:
;	b$AddrC specifies start pixel
;	b$PenC = cursor mask and attribute
;	BX	= number of pixels to set
;Exit:
;	None
;Uses:
;	per conv.
;Exceptions:
;******************************************************************************
cProc	B$CgaNSetC,<PUBLIC,NEAR>,<ES,DI>
cBegin
	les	di,b$AddrC	;graphics cursor address
	mov	dx,b$PenC	;dl = cursor mask, dh = attribute
	or	dl,dl		;left aligned in byte?
	js	NSet2a		;go if so, skip single-bit start
NSet1:
	xor	ah,ah		;zero out new mask accumulator
	mov	cl,b$BitsPerPixel
NSet2:
	or	ah,dl		;include this pixel in mask
	dec	bx		;decrement pixel count
	jz	NSet4		;treat as last byte if bit count exhausted
	ror	dl,cl		;move 1 pixel right
	jnb	NSet2		;continue if not right-most bit
	mov	al,dh		;copy of attribute
	xor	al,es:[di]	;get bits that need to be changed
	and	al,ah		;mask in bits that need to be changed
	xor	es:[di],al	;update pixels
	inc	di		;bump cursor byte pointer
NSet2a:
	mov	ax,bx		;remaining bit count
	mov	cl,b$DivShift	;pixels/byte divisor shift
	shr	ax,cl		;compute full byte count
	jz	NSet3		;go do remaining bits if no full bytes
	xchg	ax,cx		;byte count to cx
	mov	al,dh		;attribute byte
	rep	stosb		;block write full bytes
NSet3:
	and	bx,b$ModMask	;mask in remaining bit count
	jz	NSet5		;no bits remaining - exit
	jmp	NSet1		;go do remaining bits
NSet4:				;update last byte
	xor	dh,es:[di]	;get bits that need to be changed
	and	dh,ah		;mask in bits that need to be changed
	xor	es:[di],dh	;update pixels
NSet5:
cEnd


;***
; B$CgaSetTile
;
;Purpose:
;	This routine stores the internal form of the current tile attribute.
;	This routine is called each time a row is to be painted in CGA modes.
;Entry:
;	BL = tile attribute
;Exit:
;	_bAttrC set to tile attribute
;Uses:
;	per conv.
;Exceptions:
;******************************************************************************
cProc	B$CgaSetTile,<PUBLIC,NEAR>
cBegin
	MOV	b$AttrC,BL	 ;set attribute to the tile attribute
cEnd

;***
; ScanInit
;
;Purpose:
;	This routine does some initialization for both ScanL and ScanR
;	for CGA modes.
;Entry:
;	None
;Exit:
;	ES:DI = Video segment address (b$AddrC)
;	CH = cursor mask	      (b$MaskC)
;	DL = border attribute	      (b$PaintBorder)
;	DH = paint attribute	      (b$AttrC)
;	SI = already painted flag     (0)
;	BL = screen byte	      (read from ES:DI)
;	CL = b$BitsPerPixel
;Uses:
;	per conv.
;Exceptions:
;******************************************************************************
cProc	ScanInit,<NEAR>
cBegin
	les	di,b$AddrC	    ;di=cursor offset, es=video seg
	mov	ch,b$MaskC	    ;ch=cursor mask
	mov	dl,b$PaintBorder   ;dl=border attribute
	mov	dh,b$AttrC	    ;dh=paint attribute
	mov	cl,b$BitsPerPixel  ;shift count
	mov	bl,es:[di]	    ;load the screen byte or word
	xor	si,si		    ;clear already-painted-flag
cEnd

;***
; Helper
;
;Purpose:
;	This routine is used by the beginning and ending parts of
;	SCANL and SCANR. It returns with ZF set if a border pixel was
;	found, else it sets the already-painted-flag appropriately.
;Entry:
;	BL = screen byte
;	DL = border attribute
;	CH = pixel mask
;Exit:
;	If border found
;	    PSW.C set
;	else
;	    AL = screen byte with non-masked pixels set to attribute
;	    SI = non-zero value
;	    BP (paint count) incremented
;Uses:
;	per conv.
;Exceptions:
;******************************************************************************
cProc	Helper,<NEAR>
cBegin
	mov	al,bl		;get screen byte
	xor	al,dl		;xor with border
	and	al,ch		;mask out unwanted bits
	jz	helpxt1 	;quit if border
	mov	al,bl		;get screen byte in [al]
	xor	al,dh		;xor it with paint attribute
	and	al,ch		;mask out other bits
	or	si,ax		;set already painted flag
	inc	bp		;increment paint count
helpxt1:
cEnd

;***
; B$CgaScanL
;
;Purpose:
;	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, b$MaskC = pixel to right of starting pixel
;	b$PaintBorder	   = attribute of paint region border
;	b$AttrC	   = attribute to paint
;	B$LEOFST, B$VLMASK   = left viewport edge
;Exit:
;	BX		   = number of pixels scanned
;	CL		   = 0 iff no pixels changed color
;	b$OffC, b$MaskC  = the last non-border pixel examined/painted
;Uses:
;	per conv.
;Exceptions:
;******************************************************************************
cProc	B$CgaScanL,<PUBLIC,NEAR>,<SI,DX,DI,BP,ES>
cBegin
	call	ScanInit	;init regs for scanning
	mov	bp,si		;clear paint count

;	Prolog

	cmp	di,B$LEOFST	;cursor offset same as left edge offset ?
	jz	exit4		;Brif so and do the ending
	rol	ch,cl		;move left one pixel
begin1:
	JC	MIDDLE		;go if byte aligned
	call	Helper		;check if this pixel is a border pixel
				;else set the already painted flag
	jz	exit1		;brif if border pixel found
	rol	ch,cl		;move left by one pixel
	JMP	SHORT begin1	;else test the other pixels in this byte
middle:

;	Middle paint loop
;	Middle is used by all screen modes
middle0:

	sub	di,1		;move left one byte
	jb	exit2		;brif underflow
	mov	bl,es:[di]	;get the screen byte
	cmp	di,B$LEOFST	;are we at left edge ?
	je	exit3		;brif so
	mov	al,bl		;screen byte in [al]
	xor	al,dl		;xor it with border
tstbdr1:
	test	al,ch		;border encountered ?
	jz	exit3		;brif border
	rol	ch,cl		;prepare mask to test next pixel
	jnb	tstbdr1 	;test the next pixel
	mov	al,bl		;[al] = screen byte ****
	xor	al,dh		;xor screen byte with paint attribute
	or	si,ax		;set the already-painted-flag
	add	bp,b$PixelsPerByte ;increment paint count by # of
				;pixels in a byte
	JMP	SHORT middle0	;go do the rest

;	Epilog
;	branches here from the beginning part

exit1:
	ror	ch,cl		;back up so not on border
	jnb	final_exit	;brif no carry
	JMP	SHORT exit21

;	branches here if [di] goes < 0

exit2:
	mov	ch,b$MaskLeft	;set mask with the leftmost
				;bit/bits equal to 1
exit21:
	inc	di		;back up
	JMP	SHORT final_exit

;	branches here if [di] is same as B$LEOFST or
;	if a border pixel was found in the middle loop

exit3:
	mov	cl,b$BitsPerPixel
	mov	ch,b$MaskRight ;make the rightmost bit/bits equal to 1
exit31:
	call	Helper
	jz	exit1		;brif border found
	rol	ch,cl		;move left by one pixel
	jb	exit41		;this is a special case
	cmp	ch,B$VLMASK	;compare bit addresses
	ja	exit1		;brif done
	JMP	SHORT exit31	;else continue

;	branches here if we start with cursor offset equal
;	to B$LEOFST (right at the beginning)

exit4:
	rol	ch,cl		;move left by one pixel
;	jnb	exit31		;continue if not the left most pixel
	JB	EXIT41		;if leftmost pixel, then jump
	CMP	CH,B$VLMASK	;test if past the viewport on left
	JNA	EXIT31		;if not, then jump
exit41:
	ror	ch,cl

;	this is where NSetC gets called to do the actual painting

final_exit:
	mov	bx,bp		;paint count in [bx]
	or	bx,bx		;is paint count 0 ?
	jz	fexit1		;branch around NSetC if so
	mov	b$OffC,di	;return cursor offset
	mov	b$MaskC,ch	;return cursor mask
	call	B$CgaNSetC	;paint them
fexit1:
	mov	bx,bp		;return paint count
	mov	cx,si		;return already-painted-flag
cEnd

;***
; B$CgaScanR
;
;Purpose:
;	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, b$MaskC = starting pixel
;	b$PaintBorder	   = attribute of paint region border
;	b$AttrC	   = attribute to paint
;	B$REOFST, B$VRMASK   = right viewport edge
;Exit:
;	BX		   = number of pixels painted

⌨️ 快捷键说明

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