📄 llegasup.asm
字号:
JZ LSTBYT
; Look at whole bytes within viewport range until non-paint color found.
LKPNTL:
DEC SI
MOV AL,ES:[SI]
NOT AL ;check if all bits set (all paint color)
OR AL,AL ;NOT does not affect flags
JNZ BITFDL
DEC DI
JNZ LKPNTL ;keep looking until search of complete
;bytes is exhausted
; On last byte now, mask in BH.
LSTBYT:
DEC SI
MOV AL,ES:[SI] ;do last compare
AND AL,BH ;significant bit = 0 if not paint color
XOR AL,BH ;if different, not paint
JZ NOBITL
BITFDL:
MOV CL,AL ;set change bits flag to non-zero
NOBITL:
cEnd
;***
; B$EgaTILLFT
;Purpose:
; Check for non-paint pixels left if tiling is on.
; Use READC to do bit-wise color compares with tile colors stored in
; color array ColorBits (colors of bits 0 to 7 configured left to right
; are represented in the array as elements offset 0 to 7 from base
; address).
;
;Entry:
; BL = bit mask for rightmost partial byte
; BH = bit mask for leftmost partial byte
; DI = count of whole bytes
; ES:SI = screen address
;Exit:
; CL = 0 iff no pixels to change
;Uses:
; per conv.
;Exceptions:
;****
cProc B$EgaTILLFT,<PUBLIC,NEAR>,<DX,BP>
cBegin
PUSH b$OffC
PUSH b$PenC
PUSH BX
MOV AL,BL ;copy of bit mask for rightmost byte
MOV ByteCount,DI ;store whole byte counter
OR AL,AL ;make sure at least 1 bit set
JZ TILLF5
CALL HICHK ;check first [partial] byte using mask in [AL]
JNZ TILLF1 ;exit if non-match found
TILLF5:
CMP ByteCount,0 ;check for intermediate whole bytes
JZ TILLF4 ;if not, proceed to check for last byte
TILLF2:
DEC SI ;move left on line
MOV b$OffC,SI ; store in b$OffC for READC
MOV b$MaskC,1 ;start at rightmost bit
MOV BP,7 ;rightmost element of color array
TILLF3:
CALL [b$ReadC] ;determine color of pixel (returned in AL)
CMP AL,ColorBits[BP] ;look for non-match
JNZ TILLF1 ;when we find one, we can exit
DEC BP
SHL b$MaskC,1 ;move to next bit left
JNB TILLF3 ;continue 'til we shift out of byte left
DEC ByteCount ;prepare to check next byte left
JNZ TILLF2
TILLF4:
POP BX
OR BH,BH ;see whether a "last byte"
PUSH BX
JZ TILLF6 ;if not, there was only 1 byte
MOV AL,BH ;get last byte's bit mask
DEC SI
CALL LOWCHK ;look through last [partial] byte for match
JNZ TILLF1
TILLF6:
MOV CL,-1
TILLF1:
INC CL ;non-zero if pixels changed
POP BX
POP b$PenC
POP b$OffC
cEnd
;***
; HICHK
;Purpose:
; Check partial byte for tile pattern match, where byte may be
; partial in that some low bits may be immunized from PAINT and
; therefore must be skipped during the tile pattern check.
;
;Entry:
; AL = screen byte to check
; ColorBits array contains tile pattern to check against
;Exit:
; PSW.C set iff no match found
;Uses:
; per conv.
;Exceptions:
;****
cProc HICHK,<NEAR>
cBegin
MOV CH,10000000B ;rotate will start mask at 0000/0001
MOV BP,8 ;start counter at 8
HICHK1:
ROL CH,1
DEC BP ;offset to first bit to check for color
ROR AL,1 ;shift immune bits out right
JNB HICHK1 ;if we got a 1, we found a relevant bit
MOV b$MaskC,CH
HICHK2:
PUSH AX ;store state of shift mask
MOV b$OffC,SI
CALL b$ReadC ;get color for this pixel
CMP ColorBits[BP],AL ;see if match
POP AX ;restore shift mask
JNZ HICHK3 ;our goal is just one non-matching pixel
DEC BP
ROR AL,1 ;look for additional 0's to left of first 1
JNB HICHK4
SHL b$MaskC,1
JNB HICHK2
HICHK4:
XOR BP,BP ;return ZF set if no match found
HICHK3:
cEnd
;***
; LOWCHK
;Purpose:
; Check partial byte for tile pattern match, where byte may be
; partial in that some high bits may be immunized from PAINT and
; therefore must be skipped during the tile pattern check.
;
;Entry:
; AL = screen byte to check
; ColorBits array contains tile pattern to check against
;Exit:
; PSW.C set iff no match found
;Uses:
; per conv.
;Exceptions:
;****
cProc LOWCHK,<NEAR>
cBegin
MOV CH,00000001B ;rotate will start mask at 1000/0000
XOR BP,BP
NOT BP ;counter at -1
LWCHK1:
ROR CH,1
INC BP ;offset to first bit to check for color
ROL AL,1 ;shift immune bits out left
JNB LWCHK1 ;if we got a 1, we found a relevant bit
MOV b$OffC,SI
MOV b$MaskC,CH
LWCHK2:
PUSH AX ;store state of shift mask
CALL b$ReadC ;get color for this pixel
CMP ColorBits[BP],AL ;see if match
POP AX ;restore state of shift mask
JNZ LWCHK3 ;our goal is just one non-matching pixel
ROL AL,1 ;look for any trailing 0's indicating immune
JNB LWCHK4
INC BP
SHR b$MaskC,1
JNB LWCHK2
LWCHK4:
XOR BP,BP ;set ZF
LWCHK3: ;non-zero indicates non-match
cEnd
;***
; WRTLFT
;Purpose:
; Used for tiling if in odd/even mode, during SCANL.
; Latches off-screen tile pattern at even address when DI even, and
; at odd address when DI odd, then "writes" this pattern at DI.
;
;Entry:
; ES:DI = screen address of start byte
; CX = count of bytes to write
;Exit:
; ES:DI = screen address of stop byte
;Uses:
; SI
;Exceptions:
;****
cProc WRTLFT,<NEAR>
cBegin
MOV SI,OFFSCN ;get address of off-screen location
TEST DI,1 ;see whether first byte odd
JNZ INCBYL
INC SI ;even byte, so set up for DEC loop
DECBYL:
DEC SI ;SI gets even offscreen byte address
MOV AL,ES:[SI] ;latch even byte pattern
MOV ES:[DI],AL ;dummy write puts latched byte out
DEC DI ;move left on write line
DEC CX ;decrement byte counter
JCXZ LFTEX
INCBYL:
INC SI ;point to odd offscreen byte
MOV AL,ES:[SI] ;latch odd byte pattern
MOV ES:[DI],AL ;dummy write of latched pattern
DEC DI ;move left
LOOP DECBYL
LFTEX:
cEnd
;***
; WRTRGT
;Purpose:
; Used for tiling if in odd/even mode, during SCANR.
; Latches off-screen tile pattern at even address when DI even, and
; at odd address when DI odd, then "writes" this pattern at DI.
;
;Entry:
; ES:DI = screen address of start byte
; CX = count of bytes to write
;Exit:
; ES:DI = screen address of stop byte
;Uses:
; SI
;Exceptions:
;****
cProc WRTRGT,<NEAR>
cBegin
MOV SI,OFFSCN ;get address of off-screen location
TEST DI,1 ;see whether first byte odd
JNZ INCBYR
INC SI ;even byte, so set up for DEC loop
DECBYR:
DEC SI ;SI gets even offscreen byte address
MOV AL,ES:[SI] ;latch even byte pattern
MOV ES:[DI],AL ;dummy write puts latched byte out
INC DI ;move right on write line
DEC CX ;decrement byte counter
JCXZ RGTEX
INCBYR:
INC SI ;point to odd offscreen byte
MOV AL,ES:[SI] ;latch odd byte pattern
MOV ES:[DI],AL ;dummy write of latched pattern
INC DI ;move right
LOOP DECBYR
RGTEX:
cEnd
;***
; ScanL
;Purpose:
; To scan left beginning one pixel to the left of the current
; graphics cursor setting pixels to the paint attribute until
; either edge of viewport or border is found; to return
; certain information to the calling routine.
;
; Algorithm for SCANL2 is as follows: starting next left to b$OffC
; b$MaskC:
;
; i. While (not border) AND (not viewport edge) AND (not left
; edge of byte) move left in byte.
; ii. If (left edge of byte) then
; decrement b$OffC, set up b$MaskC, go to i.
; Else
; test if on border pixel
; x. if true, exit unchanged
; xx. else
; xx1. set up bit mask for first byte
; xx2. calculate # whole bytes if any
; xx3. set up bit mask for last byte if any
; xx4. see whether any pixels in range will
; change color
; xx41. if not, exit to pixel count routine
; xx42. if so, paint all pixels
; xx5. calculate number of pixels "painted"
; xx6. exit with appropriate information
;Entry:
; b$AttrC = attribute to paint
; b$PaintBorder = border attribute which ends paint
; b$OffC, b$MaskC specify pixel one to right of first to examine
;Exit:
; BX = number of nonborder pixels tested
; CL = 0 ifF no pixels changed color
; b$OffC, b$MaskC specify location of last pixel painted, or
; unchanged if only border pixels found
;Uses:
; per conv.
;Exceptions:
;****************************************************************************
cProc B$EgaScanL,<PUBLIC,NEAR>,<ES>
cBegin
CALL B$EgaScanInit
ROL CH,1 ;see if cursor is left edge of byte
JNB VWPCK1
SUB SI,1 ;if so, start next byte left
JNC VWPCK1 ;(SUB used since DEC doesn't set carry)
JMP BRDEX1 ;if negative, hit corner of screen
VWPCK1: ;to check first for viewport edge byte
CMP SI,B$LEOFST ;see if on edge of viewport, or off to left
JNB VWPCK2 ;if viewport byte or to right,
JMP BRDEX1 ; continue, else off to left; do nothing, exit
VWPCK2: ;to check for edge bit if in edge byte
JNZ NOTEDG ;if not viewport edge byte, skip
CMP CH,B$VLMASK ;bit check else compare first pixel left with
;viewport edge bit -- if farther left, we are
; JA BRDEX1 ;are left of viewport edge and must
JNA NOTEDG ;exit
JMP BRDEX1
NOTEDG: ;exit
MOV DI,SI ;extra copy of first byte address
MOV CL,CH ;extra copy of initial bit mask
MOV BP,-1 ;this will be count of whole bytes
XOR DX,DX ;this will be #pixels painted
XOR AH,AH ;initialize this byte's viewport mask to 0
; read first byte off the screen
MOV AL,ES:[DI]
TEST AL,CH ;see whether initial pixel is border
JZ SRCHLF ;if not, start search left
XOR CL,CL ;else set pixels-changed flag back to 0
JMP SHORT BRDEX1 ;and exit gracefully
SRCHLF:
; look for border or viewport in first byte
CMP DI,B$LEOFST ;is this in fact viewport edge byte?
JNZ NOTVWL
MOV AH,B$VLMASK ;if so, set up viewport mask in AH
NOTVWL:
; while not border
TEST AL,CH
JNZ HAVPIX
; and not viewport edge
TEST AH,CH
JNZ HAVPIX
; and not off the edge of the byte
ROL CH,1
JNB NOTVWL
; keep moving left - edge of first byte
DEC DI ;next byte address left
INC BP ;count of intermediate bytes
MOV AL,ES:[DI] ;read next byte left
JMP SHORT SRCHLF ;check next byte
HAVPIX:
; Here when border or viewport edge found.
; Set up bit mask for first (possibly only) byte.
; SI = rightmost byte
; DI = leftmost byte (possibly same byte)
; CL = mask for rightmost bit in rightmost byte
; If viewport edge was found, AH will contain the viewport bit
; mask, and DI is the viewport edge byte. If SI=DI=viewport edge
; byte, we need to retain the viewport mask in AH. Otherwise
; clear AH and fetch the mask again later if needed for DI.
CMP SI,B$LEOFST ;see if rightmost byte is LEFT viewport
JZ SINOTV ;if so, don't clear viewport mask
; register
XOR AH,AH ;else clear AH for B$EgaCHKBTL on
SINOTV: ; rightmost byte
MOV CH,CL ;initial bit position in CH
MOV AL,ES:[SI] ;get border bits if any
CALL B$EgaCHKBTL ;set up bit mask for first byte
MOV BL,BH ;store in BL
XOR BH,BH ;there may be only one byte
; see if more than 1 byte to paint
PUSH SI ;save a copy of rightmost address
INC BP ;see if still -1
JZ ONEBYT
DEC BP ;if not, recover real value
MOV CH,1 ;set up mask for final byte
MOV AL,ES:[DI] ;get border bits if any
CMP DI,B$LEOFST ;was this viewport byte?
JNZ DINOTV ;no -- don't need viewport mask
MOV AH,B$VLMASK ;yes -- get viewport mask for CHKTBL
DINOTV:
CALL B$EgaCHKBTL ;set up leftmost byte bit mask in BH
ONEBYT:
MOV b$OffC,DI
MOV b$MaskC,CH ;update cursor
PUSH DI ;save a copy of leftmost address
MOV DI,BP ;store whole byte count for PIXLF2
CMP b$Tiling,0
JZ COLCM5
CALL B$EgaTILLFT
JMP SHORT COLCM6
COLCM5:
CALL B$EgaSETCMP ;set color compare register to paint attribute
CALL PIXLF2 ;see whether any pixels in range will change
COLCM6:
POP SI ;restore leftmost address to SI
POP DI ;restore rightmost address to DI
OR CL,CL ;returns CL non-zero if changes needed
JZ BRDEXT
; We found at least 1 pixel to change, so set entire range
; set pixels-changed flag, set up write mode 2
XOR CH,CH
NOT CH ;set to FF as decrement flag
STD ;for SCANL, decrement from DI
CALL B$EgaPAINPX
CLD
BRDEXT:
CALL B$EgaPIXCNT ;returns # pixels "painted" in BX
BRDEX1:
CALL B$ResetEGA
cEnd
;***
; ScanR
;Purpose:
; To scan right beginning with the graphics cursor at entry
; setting certain pixels to the current graphics attribute
; (color or tile pattern); to return certain information to
; the calling routine .
;
; ScanR algorithm is as follows :
; i. Search right until
; a. DX pixels have been tested without encountering non-
; border,
; OR
; b. viewport edge is encountered without encountering non-
; border,
; OR
; c. a non-border pixel is found.
; ii. If a. or b., then exit with
; [BX] = number of pixels painted = 0
; [CL] = pixels modified flag = 0
; [DX] = border pixels skipped during successful search for
; non-border pixel = 0
; graphics cursor preserved
; CSAVE (cursor values returned by previous SCANs) preserved
;
; iii.If c., then continue searching right painting non-border
; pixels until
; a. a border pixel is found
; OR
; b. the edge of the viewport is encountered
; then exit with
; [BX] = count of pixels painted (even if no color change
; [CL] = pixels modified flag (0 if no pixels changed color)
; [DX] = entry [DX] - count of border pixels searched before
; encountering non-border
; b$OffC, b$MaskC = last pixel examined (border or viewport
; edge, painted if viewport edge
; b$SaveCa,b$SaveCm = cursor values for first non-border pixel
;
; This routin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -