paint.asm
资源名称:DOS系统的源代码.rar [点击查看]
上传用户:xiaoan1112
上传日期:2013-04-11
资源大小:19621k
文件大小:27k
源码类别:
操作系统开发
开发平台:
Visual C++
- 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
- JMP SHORT MAT3LP ;Loop
- MATC3X:
- RET
- CMPST:
- PUSH SI ;Save tile string pointer
- MOV BX,3
- PUSH ES
- PUSH DS
- POP ES
- CMPST2:
- MOV CL,DL ;Look for 3 in a row matches of B$GRPLAN bytes
- XOR CH,CH
- CMPST0: CMPSB ;Compare [SI],[DI]
- JNE CMPST1 ;Different already, exit with Z clear
- CALL WRAPSI
- LOOP CMPST0 ;Matched B$GRPLAN in a row yet?
- MOV DI,WORD PTR B$BGTLOC ;Yes: reset background pointer
- DEC BX ;Matched 3 sets of B$GRPLAN in a row?
- JNZ CMPST2 ;No:
- ;Yes: exit with Z set
- CMPST1:
- POP ES
- POP SI
- RET
- WRAPSI:
- CMP SI,AX ;Wrap around to beginning of tile string yet?
- JBE NoWrap ;No:
- MOV SI,WORD PTR B$TILLOC ;Yes: back to go
- NoWrap: RET
- ;***
- ; TILATR
- ; Set ATRBYT from tile and set B$TIPROG if current tile
- ; attribute equals BG tile attribute.
- ; USES BX,DI
- ;****
- TILATR:
- CMP B$TILFLG,0
- MOV BL,B$TILPTR
- JNZ B$TILAT1 ;Update ATRBYT
- RET ;do nothing if not tile
- ;***
- ; TILNDD
- ; Decrement Tile index
- ; and store tile in ATRBYT if B$TILFLG True...
- ; USES AX,BX
- ;****
- TILNDD:
- CMP B$TILFLG,0
- JNZ TILNDD1 ;do nothing if not tile
- RET
- TILNDD1:
- DEC B$TILNDX ;index is one less
- MOV BL,B$TILPTR ;get offset to fground tile string
- OR BL,BL ;At beginning of tile string?
- JNZ TILDN1 ;Brif not underflowing
- MOV BL,B$TILHGT ;get tile height
- DEC BL ;make 0-relative
- MOV B$TILNDX,BL ;put into index
- MOV BL,B$TILLEN ;else wrap to top end
- INC BL ;make 1 based
- TILDN1:
- SUB BL,B$GRPLAN ;Decrement index to beginning of prev tile
- JMP SHORT TILND2 ;Update index, ATRBYT
- PNTERR:
- MOV B$TILFLG,0 ;Turn Tiling off
- JMP B$ERR_FC
- ;***
- ; TILNDI
- ; Increment Tile index (called after DOWNC)
- ; and store tile in ATRBYT if B$TILFLG True...
- ; USES AX,BX
- ;****
- TILNDI:
- CMP B$TILFLG,0
- JNZ TILNDI1 ;do nothing if not tile
- RET
- TILNDI1:
- INC B$TILNDX ;increment tile pixel index
- MOV BL,B$TILPTR ;get fground tile byte offset
- ADD BL,B$GRPLAN ;Increment index to beginning of next tile
- CMP BL,B$TILLEN
- JBE TILND2 ;Brif not overflowing
- XOR BL,BL ;else wrap to bottom end
- MOV B$TILNDX,BL ;also clear tile pixel index
- TILND2:
- MOV B$TILPTR,BL ;update tile byte offset pointer
- ;***
- ; B$TILAT1
- ;
- ;****
- cProc B$TILAT1,<NEAR>,<SI>
- cBegin
- MOV BH,0 ;[BL]=[BL]*GRPLAN, [BH]=0
- ADD BX,WORD PTR B$TILLOC
- MOV SI,BX ;SI points into tile string
- MOV DI,WORD PTR B$BGTLOC ;DI points into background string
- MOV B$TIPROG,0 ;Clear progress flag
- XOR BH,BH
- TILAT2: INC BH
- CMP BH,B$GRPLAN
- JA TILAT4 ;For BH = 1 to gplanes
- MOV BL,[SI] ;Get curr tile attr
- PUSH BX
- CALL [b$SetTile] ;Set OEM's 'ATRBYT' to tile attr
- POP BX
- CMP BL,[DI] ;Compare FG attr to BG attr
- JNZ TILAT3 ;Brif not equal
- INC B$TIPROG ;Count matches
- TILAT3:
- INC SI ;Check next planes bytes
- INC DI
- JMP SHORT TILAT2 ;next BH
- TILAT4:
- MOV BL,B$TIPROG
- MOV B$TIPROG,0
- CMP BL,B$GRPLAN ;Did all FG match BG?
- JNE TILAT6 ;No: not all matched so say none did.
- MOV B$TIPROG,1 ;Yes: flag all matched
- TILAT6:
- cEnd
- PAGE
- SUBTTL PAINT QUEUE ROUTINES
- cProc B$INTQNOCPCT,<PUBLIC,NEAR>,<BX,DX>
- cBegin
- ; PUSH BX ;save registers...
- ; PUSH DX
- ; cCALL B$STGETFRESIZ ;get size of free string
- ; OR BX,BX ;test if no free string
- ; JZ PQOMER ;if not, give out of memory error
- ; cCALL B$STALCTMP ; Allocate all string space as temporary
- cCALL B$STALCMAXTMPNC ; Allocate max-string w/o compaction
- JMP SHORT INTQUE_COMMON ;jump to common code point
- cEnd <nogen> ; End of B$INTQNOCPCT
- PUBLIC B$INTQUE
- B$INTQUE:
- PUSH BX ;Save x coord
- PUSH DX ;SAVE Y COORD
- CALL B$STALCMAXTMP ;allocate maximum temporary string
- INTQUE_COMMON:
- MOV AX,0[BX] ;AX:=size of free string space
- MOV CX,2[BX] ;CX:=location of free string space
- CMP AX,9 ;is temp string too small?
- JB TEMP_TOO_SMALL ;if so, do not subtract
- SUB AX,9 ;give string room for test
- TEMP_TOO_SMALL:
- ;Note: B$GY_OLD is the previous x coord accumulator. Since this variable is
- ;never used in the PAINT statement, it is used here to save the location
- ;of the temporary string being used for the paint queue.
- MOV B$GY_OLD,CX ;save string location in B$GY_OLD
- ADD CX,AX ;CX points just past end of free string
- DEC CX ;CX=highest byte of in-use string space
- ;omit check for overflow
- ;Note: B$GX_OLD is the previous y coord accumulator. Since this variable is
- ;never used in the PAINT statement, it is used here to save the pointer to
- ;the end of the temporary string being used for the paint queue.
- MOV B$GX_OLD,CX ;Save this value in B$GX_OLD
- CALL B$STDALCTMP ;mark temp string as deallocated
- CMP AX,18d
- JNB INTQU3 ;Ok if at least 18 bytes (2 entries)
- PQOMER:
- JMP B$ERR_OM ; else Out of Memory
- INTQU3:
- MOV WORD PTR B$PQLEN,AX ;len is free size
- MOV WORD PTR B$PQNUM,0 ;present number is 0
- XCHG AX,DX ;AX:=beginning of usable free space
- MOV WORD PTR B$PQGET,AX ;Init head
- MOV WORD PTR B$PQPUT,AX ; and tail
- POP DX ;Restore y coord
- POP BX ;Restore X coord
- RET
- ; PUTQ - Enqueue entry in paint queue
- ; Entry - AX,BX,CX = OEM's graphics cursor
- ; SI = B$SKPCNT
- ; DL = Direction (and tiling) flag
- ; Exit - B$PQNUM,B$PQPUT updated
- ; AX,DI Used
- DbPub PUTQ
- PUTQ:
- PUSH ES
- PUSH DS
- POP ES
- PUSH DX
- ;added 1 line
- PUSH SI
- PUSH CX
- PUSH BX
- ;added 1 line
- PUSH AX
- ADD WORD PTR B$PQNUM,9d ;len= len+9
- MOV AX,WORD PTR B$PQLEN
- CMP WORD PTR B$PQNUM,AX
- JNB PQOMER ;Out of Memory if at end or higher
- MOV AX,WORD PTR B$PQPUT ;[AX]= queue ptr
- CALL WRAP ;check wrap
- MOV DI,AX ;[DI]= queue ptr
- POP AX
- CLD
- STOS WORD PTR [SI] ;Graphics cursor
- POP AX
- STOS WORD PTR [SI] ;Graphics cursor
- POP AX
- STOS WORD PTR [SI] ;Graphics cursor
- POP AX
- STOS WORD PTR [SI] ;B$SKPCNT
- ;added 2 lines
- POP AX
- STOSB ;Direction flag
- MOV WORD PTR B$PQPUT,DI
- POP ES
- RET
- WRAP:
- PUSH AX
- ADD AX,9
- ;Note: B$GX_OLD is the previous x coord accumulator. Since this variable is
- ;never used in the PAINT statement, it is used here to save the location
- ;of the temporary string being used for the paint queue.
- CMP AX,WORD PTR B$GX_OLD ;Are we at end of free space?
- POP AX ;Restore AX
- JB WRAPX ;Brif not off end of queue
- ;Note: B$GY_OLD is the previous y coord accumulator. Since this variable is
- ;never used in the PAINT statement, it is used here to save the pointer to
- ;the end of the temporary string being used for the paint queue. This
- ;value is set at the beginning of B$INTQUE.
- MOV AX,B$GY_OLD ;else set to beginning of queue
- WRAPX:
- RET
- ; GETQ - Dequeue entry from paint queue
- ; Entry - none
- ; Exit - AX,BX,CX = OEM's graphics cursor
- ; SI = B$SKPCNT
- ; DL = Direction (and tiling) flag
- ; B$PQNUM,B$PQGET updated
- ; No other registers used.
- DbPub GETQ
- GETQ:
- MOV DL,0 ;preset "Direction=0" in case no entries
- CMP WORD PTR B$PQNUM,0
- JZ GETQX ;Brif empty
- SUB WORD PTR B$PQNUM,9d ;len = len-9
- MOV AX,WORD PTR B$PQGET ;[AX]= dequeue ptr
- CALL WRAP ;check wrap
- MOV SI,AX ;[SI]= dequeue ptr
- ;added 3 lines
- CLD
- LODS WORD PTR [SI] ;Graphics cursor
- PUSH AX
- LODS WORD PTR [SI] ;Graphics cursor
- MOV BX,AX
- LODS WORD PTR [SI] ;Graphics cursor
- MOV CX,AX
- LODS WORD PTR [SI] ;B$SKPCNT
- PUSH AX
- ;added 2 lines
- LODSB ;Direction flag
- MOV DL,AL
- MOV WORD PTR B$PQGET,SI
- ;added 2 lines
- POP SI ;SI = B$SKPCNT
- POP AX
- GETQX:
- RET
- PAGE
- SUBTTL COMPILER ENTRY POINTS FOR PAINT
- ; PAINT - FILL AN AREA WITH COLOR
- ;
- ; SYNTAX: PAINT [STEP](X,Y)[,<iexp>[,iexp]]|[,<sexp>[,<iexp>[,<sexp>]]]
- ; where <iexp>=integer expression, <sexp>=string expression
- ;
- ;***
- ;B$PAIN - Process PAINT statement without tiling
- ;
- ;Purpose:
- ; This routine will be called by the parsing routine PAINT in PRSG86
- ; in the interpreter version or by the compiler in the compiler version
- ; if the PAINT statement scanned does not contain a paint tile
- ; attribute but uses a integer paint color instead. The call to
- ; BNDS_CHK tests the start coordinates of the PAINT against the current
- ; viewport boundaries. The paint and border colors are checked for
- ; validity before the jump to B$PAINTBEG begins the actual painting.
- ;
- ;Entry:
- ; Color = paint color spec or -1 if default
- ; Border = border color spec or -1 if default
- ;Exit:
- ; None.
- ;Uses:
- ; Per convention
- ;Exceptions:
- ; Control may be transfered to B$ERR_FC
- ;****
- cProc B$PAIN,<PUBLIC,FAR>,<SI,DI>
- parmW Color
- parmW Border
- cBegin
- CALL B$SCINIT ; init screen if not already done
- cCall B$COORD1 ;do any necessary translations
- MOV BX,Color ;[BX] = paint color
- MOV DX,Border ;[DX] = border color
- CALL OLD_PA1 ; Perform
- cEnd
- OLD_PA1: ; Entry point for PAINT with no tiling
- MOV B$TILFLG,0 ;tiling is not active
- MOV B$TIPROG,0
- CALL B$INTQUE ;Init the Queue
- PUSH DX ;Save border color
- CALL BNDS_CHK ;Check if coordinates are inside
- ;screen or viewport
- JC MAPIT
- JMP DONT_PAINT ;Don't PAINT if coordinates out of bounds
- MAPIT:
- push bx ;preserve bx across call to MapXYC
- CALL [b$MapXYC] ;Graphics Cursor:=(CX,DX)
- pop ax ;restore paint color
- POP DX ;Restore border color
- CALL B$CLRATR ;Returns paint color attribute in AL
- CMP DX,-1 ;Is border color defaulted?
- JZ BRDCHK ;Yes: AL contains valid paint color which is
- ;border color default when no tiling
- MOV AX,DX ;AX:=border color
- BRDCHK: ;check for valid border color
- CALL B$PaintInit ;OEM check for legal border color
- JC ERR_PAINT ;carry set if invalid border color
- JMP B$PAINTBEG ;Go begin painting
- ;***
- ;B$PNTC - Process PAINT statement with tiling option
- ;
- ;Purpose:
- ; This routine will be called if the PAINT statement scanned contains
- ; a paint tile attribute instead of an integer paint color. The
- ; call to BNDS_CHK checks to see if the PAINT coordinates are within
- ; bounds of the current viewport (the screen if there is no viewport).
- ; The call to FGSTRINI initializes a buffer area (b$Buf1) to the tile
- ; specified in the PAINT statement or to the default value. B$ClrBgStr
- ; initializes the default background string. TILEINIT checks for a
- ; valid border color, initializes B$TILNDX to index the appropriate byte
- ; of the tile string, initializes ATRBYT (variable containing tile
- ; mask) and checks for three consecutive matches between the foreground
- ; and background tiles. If everything is ok the jump to B$PAINTBEG is
- ; taken to begin the actual painting procedure.
- ;Entry:
- ; sdTile = sd for tiling string
- ; Border = border spec or -1 if default
- ; sdBkgd = sd for background string or -1 if none
- ;Exit:
- ; None.
- ;Uses:
- ; None.
- ;Exceptions:
- ; B$ERR_FC
- ;****
- cProc B$PNTC,<PUBLIC,FAR>,<ES,SI,DI>
- parmSD sdTile
- parmW Border
- parmSD sdBkgd
- cBegin
- CALL B$SCINIT ; init screen if not already done
- cCall B$COORD1 ;do any necessary translations
- GetpSD BX,sdTile ;[BX] = psdTile
- GetpSD CX,sdBkgd ;[CX] = psdBkgd
- MOV DX,Border ;[DX] = border color
- PUSH DS ; set es=ds
- POP ES
- CALL OLD_PA2 ; Perform
- cEnd
- ERR_PAINT:
- MOV B$TILFLG,0 ;Turn Tiling off
- JMP B$ERR_FC
- OLD_PA2: ; Entry point for PAINT with tiling
- MOV B$TILFLG,-1 ;Tile is active
- PUSH DX ;Save border color
- PUSH CX ;Save ptr to backgrd string descriptor
- CALL B$INTQUE ;Init the Queue
- CALL BNDS_CHK ;Check if coordinates are inside screen or viewport
- JNC POPNRET ;coords out of bounds: don't do PAINT
- push bx ;preserve bx across mapxyc call
- CALL [b$MapXYC] ;Graphics Cursor:=(CX,DX)
- pop bx ;restore ptr to fg string desc
- CALL FGSTRINI ;Initialize foreground paint string
- POP BX ;Restore ptr to background string descriptor
- CALL B$ClrBgStr ;initialize null string for background
- CMP BX,-1 ;is background string defaulted?
- JZ TILEINIT ;yes: branch to tile ATRBYT initialization
- CALL BGSTRINI ;initialize background string
- CALL MATCH3 ;check for three consecutive matching
- ;bytes in paint tile and background
- ;tile and abort if found
- JC ERR_PAINT ;Three matches found: issue error
- TILEINIT: ;Tile initialization
- POP AX ;Restore border color attribute
- CMP AX,-1 ;Is border color defaulted?
- JNZ BORDER_CHK ;NO: Go check for valid border color
- STC ;Set carry
- CALL B$GETFBC ;Get foreground color in AL
- BORDER_CHK:
- CALL B$PaintInit ;OEM routine to check for valid border color
- MOV DX,WORD PTR B$GYPOS ;DX:=current y coord
- CALL B$SetTileIndex ;set B$TILNDX to proper byte of tile string
- CALL TILATR ;set up tiling mask in ATRBYT
- JMP B$PAINTBEG ;Valid border: go begin painting
- POPNRET: ;Pop stack and abort PAINT statement
- POP CX ;pop backgrd string ptr
- DONT_PAINT:
- POP DX ;pop border color
- MOV B$TILFLG,0 ;clear tiling flag
- RET ;Return
- ;***
- ; BNDS_CHK - routine checks for valid PAINT coordinates,
- ; Purpose:
- ; To see if the coordinates specified in the PAINT statement
- ; are within the current viewport. May be called from B$PAIN
- ; or B$PNTC.
- ;
- ; If clipping is supported:
- ; If the coordinates are inside the viewport, then continue
- ; to process the PAINT statement, otherwise, return with
- ; carry clear to indicate that PAINT statement should be
- ; aborted without issuing an error message.
- ; If clipping is not supported:
- ; If the coordinates are inside the viewport, then continue
- ; to process the PAINT statement, otherwise, issue a
- ; function call error.
- ;
- ; Entry:
- ; None.
- ; Exit:
- ; Graphics cursor updated if coordinates inside current viewport.
- ; Modifies:
- ; AX,CX,DX.
- ;****
- BNDS_CHK:
- MOV CX,WORD PTR B$GXPOS ;CX:=Graphics accumulator x position
- MOV DX,WORD PTR B$GYPOS ;DX:=Graphics accumulator y position
- PUSH BX ;Save paint parameter
- CALL B$INVIEW ;Returns carry set if coords within
- ;current viewport
- POP BX ;Restore paint parameter
- RET ;return with carry flag
- sEnd GR_TEXT
- END