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

📄 paint.asm

📁 这是DOS系统的源代码,汇编写的,值得看看,对开发操作系统的人员有价值
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	PAGE	56,132
	TITLE	PAINT - iAPX 88/86 PAINT STATEMENT SUPPORT
;***
; PAINT - iAPX 88/86 PAINT STATEMENT SUPPORT
;
;	Copyright <C> 1986, Microsoft Corporation
;
;Purpose:
;
; BASIC Syntax mapping to included runtime entry points:
;
; - PAINT Statement - Calls B$PAIN or B$PNTC, depending on 'paint' attribute
;
;     PAINT (x,y) [[,paint [,boundary] ,background]]
;	|     |
;	|  Coord routines	    B$PAIN (if "paint" is numeric attribute)
;	|			       or
;	|			    B$PNTC (if "paint" is tile string)
;	|			       |
;	+------------------------------+
;
;******************************************************************************
	INCLUDE switch.inc
	INCLUDE rmacros.inc	; Runtime Macro Defintions

	USESEG	_DATA		
	USESEG	_BSS		
	USESEG	GR_TEXT 	

	INCLUDE seg.inc 	;define segments
	INCLUDE baslibma.inc
	INCLUDE idmac.inc	
	INCLUDE string.inc	

sBegin	_DATA			

	externW B$AC


sEnd	_DATA			

sBegin	_BSS			
;
;****************************************************************************
; External low-level function vectors
;****************************************************************************
;
externW b$LeftC		
externW b$ChkDownC		
externW b$ChkUpC		
externW b$ScanL		
externW b$ScanR		
externW b$MapXYC		
externW b$SetTile		
externW b$PaintBound		

	externW B$C1SAVE 	;defined in GWDATA.ASM
	externW B$C2SAVE 	;defined in GWDATA.ASM
	externW B$C3SAVE 	;defined in GWDATA.ASM
	externW B$MOVCNT 	;defined in GWDATA.ASM
	externW B$SKPCNT 	;defined in GWDATA.ASM
	externB B$LFPROG 	;defined in GWDATA.ASM
	externB B$RTPROG 	;defined in GWDATA.ASM
	externB B$PDIREC 	;defined in GWDATA.ASM
	externW B$GXPOS		;defined in GWDATA.ASM
	externW B$GYPOS		;defined in GWDATA.ASM
	externW B$GX_OLD 	;defined in GWDATA.ASM
	externW B$GY_OLD 	;defined in GWDATA.ASM

	externW B$BGTLOC 	;defined in GWDATA.ASM
	externB	b$Buf3		; > 16-byte buffer, defined in GWINI.ASM
	$BGTNUL EQU b$Buf3	
	externB B$TILFLG 	;defined in GWDATA.ASM
	externB B$TIPROG 	;defined in GWDATA.ASM
	externB B$TILLEN 	;GWDATA - length of fground tile string (0-rel)
	externB B$TILNDX 	;GWDATA - index to pixel of fground tile string
	externB B$TILPTR 	;GWDATA - byte ptr to fground tile string
	externW B$TILLOC 	;GWDATA - pointer to start of fground tile str
	externB B$TILHGT 	;GWDATA - height of foreground tile
	externB B$GRPLAN 	;GWDATA - number of graphics planes
	externW B$PQLEN		;defined in GWDATA.ASM
	externW B$PQNUM		;defined in GWDATA.ASM
	externW B$PQGET		;defined in GWDATA.ASM
	externW B$PQPUT		;defined in GWDATA.ASM

	externB b$Buf1		; foreground tile string buffer
	externB b$VTYP 	;defined in GLOBAL.INC



sEnd	_BSS			

	.RADIX	10

assumes CS,GR_TEXT		
sBegin	GR_TEXT 		


	PUBLIC	B$PAINTBEG
	externNP B$STALCTMP	
	externNP B$STALCMAXTMPNC ; Allocate max string w/o compaction

	externNP B$INVIEW
	externNP B$COORD1	
	externNP B$CLRATR

;low-level routines:
	externNP B$StoreC	
	externNP B$FetchC	
	externNP B$PaintInit	

	externNP B$GETFBC
	externNP B$TileMod	
	externNP B$STALCMAXTMP
	externNP B$STDALCTMP

	externNP B$SCINIT	; Performs screen initialization

	externNP B$ERR_FC
	externNP B$ERR_OM



	PAGE
	SUBTTL	PAINT ALGORITHM


B$PAINTBEG:			;Begin painting


	CALL	[b$PaintBound] ;Set Left and Right "C" for this line
	MOV	SI,1		;ENTRY COUNT IS ONE (SKIP NO BORDER)
	CALL	SCANR1		;SCAN RIGHT FROM INITIAL POSITION
	JZ	PNTEXT		;STARTED ON BORDER - GET TXTPTR & QUIT
	PUSH	BX		;SAVE NO. OF POINTS PAINTED TO RIGHT
	CALL	SCANL1		;NOW SCAN LEFT FROM INITIAL POS.
	POP	SI		;GET RIGHT SCAN COUNT.
	ADD	SI,BX		;ADD TO LEFT SCAN COUNT
	MOV	DL,64		;MAKE ENTRY FOR GOING DOWN
	CALL	ENTST1
	MOV	DL,0C0H 	;CAUSE PAINTING UP
	OR	DL,B$TILNDX	;Add Tile index
	JMP	SHORT STPAIN	;START PAINTING.
PNTEXT: 			;Exit PAINT statement


	MOV	B$TILFLG,0	;Turn Tiling off
	RET

;Register usage: (approximately)
;	In main paint loop: SI=B$SKPCNT, BX=B$MOVCNT, DL=Direction/Tile Index
;	In SCANR1,SCANL1:   AX=Word 1 of graphics cursor,BX=Word 2,CX=Word 3

;	MAIN PAINT LOOP

PNTLOP:
PNTLP1:
	CALL	GETQ		;Get one entry from queue
	CALL	B$StoreC	
STPAIN:
	MOV	AL,DL		;GET DIRECTION

	AND	AL,63		;Isolate Tile index
	MOV	B$TILNDX,AL	;and store it
	MOV	AH,B$GRPLAN	;get number of graphics planes
	MUL	AH		;product is in AX
	MOV	B$TILPTR,AL	;get real offset to fground tile string
	MOV	AL,DL		;reget direction byte
	AND	AL,0C0H 	;Isolate direction bits
	MOV	B$PDIREC,AL
	ADD	AL,AL		;SEE WHETHER TO GO UP, DOWN, OR QUIT
	JZ	PNTEXT		;IF ZERO, ALL DONE.
	JNB	PDOWN		;IF POSITIVE, GO DOWN FIRST
	CALL	[b$ChkUpC]	;MOVE UP BEFORE SCANNING
	JB	PNTLP1		;Off viewport - get next entry
	CALL	TILNDD		;Decrement tile index
	JMP	SHORT PNTLP2
PDOWN:
	CALL	[b$ChkDownC]	;SEE IF AT BOTTOM & MOVE DOWN IF NOT
	JB	PNTLP1		;Off viewport - get next entry
	CALL	TILNDI		;Increment tile index
PNTLP2:
	CALL	[b$PaintBound] ;Set Left and Right "C" for this line
	CALL	SCANR1		;SCAN RIGHT & SKIP UP TO B$SKPCNT BORDER
	JZ	PNTLP1		;IF NO POINTS PAINTED, GET NEXT ENTRY
	CALL	SCANL1		;NOW SCAN LEFT FROM START POINT
	MOV	SI,BX		;[SI] = LEFT B$MOVCNT
	TEST	B$TIPROG,255	;Is this a background tile?
	JNZ	TPROG1		;Yes: skip already painted check
	OR	CL,CL		;SEE IF LINE WAS ALREADY PAINTED
	JZ	PNTLP3		;IT WAS - DON'T MAKE OVERHANG ENTRY
TPROG1:
	CMP	BX,1		;SEE IF LEFT B$MOVCNT WAS .GT. 1
	JLE	PNTLP3		;No: go make entry for left+right move count
				;Yes: make entry in opposite direction for
				;overhang
	MOV	AL,B$PDIREC
	XOR	AL,128
	AND	AL,0C0H 	;Isolate new direction
	OR	AL,B$TILNDX	;Reverse direction and/or tile index
;++added 1 line (faster than doing it all in DL!)
	MOV	DL,AL
	CALL	B$FetchC	;Get current point address
	CALL	PUTQ
PNTLP3:
	ADD	SI,WORD PTR B$MOVCNT ;ADD COUNT PAINTED DURING RIGHT SCAN TO LEFT B$MOVCNT
	CALL	ENTSLR		;GO MAKE ENTRY.
;added 1 line
	MOV	CX,WORD PTR B$C3SAVE
	MOV	BX,WORD PTR B$C2SAVE ;SET CURRENT LOCATION BACK TO END
	MOV	AX,WORD PTR B$C1SAVE ;OF RIGHT SCAN.
	CALL	B$StoreC	
PNTLP4:
	MOV	SI,WORD PTR B$SKPCNT ;CALC B$SKPCNT - B$MOVCNT TO SEE IF
	SUB	SI,WORD PTR B$MOVCNT ;ANY MORE BORDER TO SKIP
	JZ	GOPLOP		;NO MORE - END OF THIS SCAN
	JB	PNTLP6		;RIGHT OVERHANG - SEE IF ENTRY NEEDED
	CALL	SCANR1		;HERE IF NEED TO CONTINUE RIGHT SCAN
	JZ	GOPLOP		;NO MORE POINTS.
	TEST	B$TIPROG,255	;Is this a background tile?
	JNZ	TPROG0		;Yes: enter regardless if already painted or not
	OR	CL,CL		;SEE IF LINE ALREADY PAINTED
	JZ	PNTLP4		;YES, DON'T ENTER ANYTHING
TPROG0:
	MOV	SI,BX		;ENTRY COUNT TO [SI]
;added 1 line
	MOV	CX,WORD PTR B$C3SAVE
	MOV	BX,WORD PTR B$C2SAVE ;MAKE ENTRY AT LOCATION SAVED BY ScanR
	MOV	AX,WORD PTR B$C1SAVE ;SO WE CAN ENTER A POSITIVE B$SKPCNT
	MOV	DL,B$PDIREC
	CALL	ENTSTK		;MAKE ENTRY
	JMP	SHORT PNTLP4	;CONTINUE UNTIL B$SKPCNT .LE. 0
PNTLP6:
	CMP	SI,WORD PTR -1	;If B$SKPCNT-B$MOVCNT .LT. -1
	JGE	GOPLOP		;No: overhang too small for entry
	NEG	SI		;Yes: Make right overhang entry
	DEC	SI		;     of at least one point wide overhang
	MOV	CX,SI		; LeftC protects CX
RTOVH1:
	CALL	[b$LeftC]	;START IS -(B$SKPCNT-B$MOVCNT)-1 TO LEFT
	LOOP	RTOVH1		
	MOV	AL,B$PDIREC	;MAKE ENTRY IN OPPOSITE DIRECTION
	XOR	AL,128
;++added 1 line (faster than doing it all in DL!)
	MOV	DL,AL
	CALL	ENTST1		;MAKE ENTRY
GOPLOP:
	JMP	PNTLOP		;GO PROCESS NEXT ENTRY
ENTSLR:
	MOV	AL,B$LFPROG	;DON'T STACK IF LINE ALREADY PAINTED
	OR	AL,B$RTPROG
	OR	AL,B$TIPROG
	JNZ	ENTST0
	RET			;Z IF SCAN LINE ALREADY PAINTED

ENTST0:
	MOV	DL,B$PDIREC
ENTST1:
	CALL	B$FetchC	;LOAD REGS WITH CURRENT "C"
ENTSTK:
	OR	DL,B$TILNDX	;Add tile index to direction
ENTST9:
	JMP	PUTQ
SCANR1:
;added 1 line
	MOV	DX,SI		;Can't change entry conditions for ScanR now...
	CALL	[b$ScanR]	;PERFORM LOW LEVEL RIGHT SCAN
	MOV	WORD PTR B$SKPCNT,DX ;SAVE UPDATED B$SKPCNT
	MOV	WORD PTR B$MOVCNT,BX ;SAVE B$MOVCNT
;added 3 lines
	MOV	WORD PTR B$C1SAVE,AX ;Save the "first non-BRDATR pixel
	MOV	WORD PTR B$C2SAVE,SI ; found during scan" in temp
	MOV	WORD PTR B$C3SAVE,DI
	OR	BX,BX		;SET CC'S ON B$MOVCNT
	MOV	AL,CL		;GET ALREADY-PAINTED FLAG FROM [C]
	MOV	B$RTPROG,AL
	RET
SCANL1:
	CALL	B$FetchC	;GET CURRENT LOCATION
;added 1 line
	PUSH	CX
	PUSH	BX		;AND SWAP WITH CSV
	PUSH	AX
;added 1 line
	MOV	CX,WORD PTR B$C3SAVE
	MOV	BX,WORD PTR B$C2SAVE
	MOV	AX,WORD PTR B$C1SAVE
	CALL	B$StoreC	;REPOS AT BEGINNING OF SCAN
	POP	AX		;REGET PLACE WHERE RT SCN STOPPED
	POP	BX
;added 2 lines
	POP	CX
	MOV	WORD PTR B$C3SAVE,CX
	MOV	WORD PTR B$C2SAVE,BX ;AND SAVE IT IN TEMP LOCATION
	MOV	WORD PTR B$C1SAVE,AX
	CALL	[b$ScanL]	;NOW DO LOW LEVEL LEFT SCAN
	MOV	AL,CL		;GET ALREADY-PAINTED FLAG FROM [C]
	MOV	B$LFPROG,AL	;WHETHER IT WAS ALREADY PAINTED (faster than
				;  doing MOV B$LFPROG,CL!)
	RET

	PAGE
	SUBTTL	PAINT AND TILE SUPPORT ROUTINES
; Little helpers for PAINT and TILE

;
;FGSTRINI		initialize foreground string
;
;Purpose:
;	  Check string for validity:  its length must be less than 256 and
;	  greater than 0.  Fill string buffer b$Buf1 with paint tile padded on the
;	  right with zeros.  Initialize B$TILLOC to point at b$Buf1.  Initialize
;	  B$GRPLAN to the number of graphics planes.  Stores rounded up tile
;	  length in B$TILLEN and pixel height of tile in B$TILHGT (must be less
;	  than or equal to 64).
;
;Entry:
;		BX = ptr to string descriptor
;
;Exit:
;	variables updated as noted
;
;Modifies:
;		CX,SI,DI
;

FGSTRINI:			;initialize paint string
	MOV	CX,WORD PTR 0[BX] ;[CX]= len
	MOV	SI,WORD PTR 2[BX] ;[SI]= addr
	OR	CH,CH		;Is CH=0?
	JNE	MATERR		;Length must be .LE. 255
	MOV	DI,OFFSET DGROUP:b$Buf1 ;DI points to b$Buf1
	MOV	WORD PTR B$TILLOC,DI ;Store adr
	PUSH	CX		;Save string length
	CLD			;Clear direction flag
				;Repeat until CX=0:
	REP	MOVSB		;Put Fill String in b$Buf1
	POP	CX		;Restore  string length
	PUSH	CX		;Resave string length
	SUB	CX,256d 	;CX:=CX-256
	NEG	CX		;CX:=-CX=remainder of BUF
	XOR	AL,AL		;Clear AL
				;Repeat until CL=0:
	REP	STOSB		;Fill the rest of BUF with zeros
;tile string is now saved in the temp buffer so temp string can be deallocated
	CALL	B$STDALCTMP	; deallocate temp string pointed to by BX
;Check tile height
	CALL	B$TileMod	;Get number of graphics planes
	POP	CX		;Restore CL
	MOV	B$GRPLAN,AL	;in this screen mode
	JCXZ	MATERR		;See if at least one byte in tile string
	XCHG	AX,CX		
	DEC	AX
	DIV	CL		;AX=(B$TILLEN-1)/B$GRPLAN
	XOR	AH,AH
	INC	AX		;AX=INT((B$TILLEN-1)/B$GRPLAN)+1=height in pixels rounded up
	CMP	AL,65
	JNB	MATERR		;Tile can only be 64 pixels long (IBM compatibility)
	MOV	B$TILHGT,AL	;Save pixel height of tile (always.LE.64)
	MUL	CL		;AX=INT(((B$TILLEN-1)/B$GRPLAN)+1)*B$GRPLAN
	DEC	AX		;make 0 based, guaranteed 1 or more
	OR	AH,AH		;Rounded up length must be .le. 255
	JNZ	materr		;Yes: this must be a multiplane with four or more planes
	MOV	B$TILLEN,AL	;Store rounded up length
	RET			;return to caller

MATERR:
	MOV	B$TILFLG,0	;Turn Tiling off
	JMP	B$ERR_FC

;***
; BGSTRINI - initialize background tile string
; Purpose:
;	Insures that string length is between 1 and 255 inclusive.
;	Initializes background string to specified background string.
;
; Entry:
;	BX = ptr to string descriptor
;	$BGTNUL = ptr to background tile string area
; Exit:
;	None.
; Modifies:
;	SI,DI,CX
;****

BGSTRINI:
	MOV	CX,[BX] 	;[CX]= len
	OR	CH,CH
	JNE	materr		;Max len is 255
	JCXZ	materr		;See if at least one byte in background string
	CMP	CL,B$GRPLAN	;Ignore any extra bytes
	JBE	FILL_BGSTR
	MOV	CL,B$GRPLAN
FILL_BGSTR:			;Fill background string
	MOV	SI,WORD PTR 2[BX] ;[SI]= addr
	MOV	DI,OFFSET DGROUP:$BGTNUL ;Point DI at backgrd tile area
	CLD			;Clear direction flag
	REP	MOVSB		;Fill with as much as user gave,
				;rest are chr$(0)
	JMP	B$STDALCTMP	; deallocate temp string pointed to by BX

;***
; B$ClrBgStr - clear background string area
; Purpose:
;	Initialize background string area by filling with zeros.
;	Make sure there are no more than 16 graphics planes.
;
; Entry:
;	$BGTNUL points to background string area
; Exit:
;	None.
; Modifies:
;	CX,DI,AX.
;****

cProc	B$ClrBgStr,<NEAR>	;Clear background string
cBegin				
	MOV	CX,16
	CMP	CL,B$GRPLAN	;Only allocated space for at most 16 planes
	JB	MATERR		;function call error
	MOV	DI,OFFSET DGROUP:$BGTNUL
	XOR	AL,AL
	CLD
	REP	STOSB		;Fill 16 bytes with CHR$(0)
	MOV	B$BGTLOC,OFFSET DGROUP:$BGTNUL ;No BG tile, use null (00)
cEnd				

;	Set starting tile index to Starting Y axis and
;	store in B$TILNDX.
;	Set B$TILNDX to (Y MOD pixel height)*B$GRPLAN
;
;Entry - [DX] = Starting Y line
;
;	Uses:	[BX]

cProc	B$SetTileIndex,<NEAR>	
cBegin				
	CMP	B$TILFLG,0
	JZ	STIND2		;nothing if not tile
	PUSH	AX
	PUSH	DX		;Protect DX
	MOV	BX,DX		;[BX]=Y coord
	MOV	DL,B$TILHGT	;[DX]= height of tile
	XOR	DH,DH
STIND1:
	SUB	BX,DX
	JNB	STIND1		;Find Y MOD pixel height
	ADD	BX,DX		;+len since overflowed
	MOV	B$TILNDX,BL	;get index of tile pixel
	MOV	AL,B$GRPLAN
	XOR	AH,AH
	MUL	BL		;AX=(Y MOD pixel height)*B$GRPLAN
	MOV	B$TILPTR,AL	;store fground tile string offset
	POP	DX		;get  Y coord
	POP	AX
STIND2:
cEnd				

;	Scan Fill argument,  set Fill color attr if numeric
;	or set up tile attr if string.
;	If string, check that its length .LE. 64*number of graphics planes
;	and round up length to even multiple of number of graphics planes.

; MATCH3	Checks 3 consecutive lines in TILE$ for match
;		with the background color or tile.  If 3 lines
;		are there, then give Illegal Function Call error.
;		If this was not done, PAINT might infinite loop.

; Uses	AX,BX,CX,DX,SI,DI

MATCH3:
	CMP	B$TILFLG,0
	JZ	MATC3X		;Do nothing if Tile wasn't given
	XOR	DH,DH
	MOV	DL,B$GRPLAN	;DX=tile "width"
	MOV	SI,WORD PTR B$TILLOC ;SI=pointer to tile string
	XOR	AH,AH
	MOV	AL,B$TILLEN
	ADD	AX,SI		;AX=end of tile string
	CLD
MAT3LP:
	CMP	SI,AX		;Done entire tile string yet?
	JA	MATC3X		;Yes:
	MOV	DI,WORD PTR B$BGTLOC
	CALL	CMPST		;Matched 3 tiles in a row?
	JE	PNTERR		;Yes: barf
	ADD	SI,DX		;No: look at next set in tile string

⌨️ 快捷键说明

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