📄 llcgasup.asm
字号:
; (whether or not they changed color)
; CL = 0 iff no pixels changed color
; DX = remaining border pixel count
; b$OffC, b$MaskC = the last non-border pixel examined/painted
; SI, AL = the first non-border pixel encountered
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
cProc B$CgaScanR,<PUBLIC,NEAR>,<DI,BP,ES>
cBegin
mov bp,dx ;save skip count in [bp]
call ScanInit ;init regs for scanning
scnr0:
mov al,bl ;screen byte in [al]
xor al,dl ;xor it with border
scnr1:
test al,ch ;border pixel or not ?
jnz begin_paint
dec bp ;decrement border count
jz scnrxt01 ;brif border count zero
ror ch,cl ;move right by one pixel
jnb scnr1
inc di ;move right by one byte
mov bl,es:[di] ;screen byte in [bl]
cmp di,B$REOFST ;cursor offset same as right edge offset
jnz scnr0 ;brif so....one more byte to go
cmp ch,B$VRMASK ;compare bit addresses
jae scnr0 ;brif within screen limits
xor bp,bp ;pretend to run out of skip count
scnrxt01:
jmp scnrxt0
; We begin painting here. Again the paint loop is in three
; parts: prolog, main body, and epilog.
begin_paint:
mov SaveCa,di ;saving SaveCa and
mov SaveCm,ch ; SaveCm
mov b$OffC,di ;set the cursor offset
mov b$MaskC,ch ;set the cursor mask
push bp ;save border count
xor bp,bp ;clear paint count
test ch,80h ;cursor byte aligned ?
JNZ SRMIDDLE0 ;go if so
; PROLOG
begpaint1:
call Helper ;calls helper1 increments
;paint count and sets painted flag
jz scnxtn1 ;brif border found
cmp di,B$REOFST ; cursor offset = right edge offset?
jne begpaint2 ; brif not
cmp ch,B$VRMASK ; compare bit addresses
je scnxtn1 ; brif edge of viewport
ja begpaint2 ; loop if not edge yet
xor bp,bp ; special case: nothing to paint
jmp short scnxtn1
begpaint2:
ror ch,cl ;move right by one pixel
JNC BEGPAINT1 ;go if not byte aligned
; MAIN BODY
INC DI ;to next byte
SRMIDDLE0:
cmp b$BitsPerPixel,2
je SRMIDDLE2
srmiddle:
mov bl,es:[di] ;[bl] = screen byte
cmp B$REOFST,di ;are we at the right edge ?
JBE SCNRXTCHK ;brif so or beyond
MOV AL,BL ;copy screen byte
NOT AL ;bitwise equivalence with border color
XOR AL,DL ; a bit in a pixel will be 1 if pixel
; is border color
JNZ BEGPAINT1 ;go if border color found in the byte
XOR BL,DH ;detect any differences from paint color
OR SI,BX ;combine with the already painted flag
;only LOByte is significant
ADD BP,8 ;increment paint count
INC DI ;move right by one byte
JMP SHORT srmiddle ;go do the rest
SRMIDDLE2:
MOV AH,55H
SRMIDDLE3:
MOV BL,ES:[DI] ;get screen byte
CMP B$REOFST,di ;at the right edge or beyond?
JBE SCNRXTCHK ;go if so
MOV AL,BL ;copy screen byte
NOT AL ;bitwise equivalence with border color
XOR AL,DL ; both bits in a pixel will be 1 if pixel
MOV BH,AL ; is border color
SHR BH,1 ;shift left bit in copy on to right bit
AND BH,AH ;mask off the trash
AND BH,AL ;see if both bits set in any pixel
JNZ BEGPAINT1 ;go if border color found in the byte
XOR BL,DH ;detect any differences from paint color
OR SI,BX ;combine with the already painted flag
;only LOByte is significant
ADD BP,4 ;increment paint count
INC DI ;to next byte
JMP SHORT SRMIDDLE3 ;loop until border color or edge found
; EPILOG
SCNRXTCHK:
jz scnrxt3
mov cl,b$BitsPerPixel ;[cl] = screen bits/pixel
rol ch,cl ;back up
inc di ;move right a byte
scnxtn1:
JMP SHORT scnrxt2 ;start painting
scnrxt3:
mov ch,b$MaskLeft ;set the leftmost bit/bits
scnrxt31:
call Helper ;calls helper1 increments
;paint count and sets painted flag
jz scnrxt2 ;brif border
ror ch,cl ;move right by one pixel
jb scnrxt1 ;special case ??????
CMP DI,B$REOFST ;test if on right viewport byte
JNE SCNRXT31 ;if not, then continue on
cmp ch,B$VRMASK ;compare bit addresses
jb scnrxt1 ;brif edge encountered
JMP SHORT scnrxt31
scnrxt1:
rol ch,cl ;back up
scnrxt2:
push cx
mov bx,bp ;paint count
or bx,bx ;paint count = 0 ?
jz no_nset ;branch around NSetC
call B$CgaNSetC
no_nset:
mov bx,bp ;return paint count
pop cx
mov b$OffC,di ;return cursor offset
mov b$MaskC,ch ;return cursor mask
pop dx ;return skip count
mov cx,si ;return already-painted -flag
JMP SHORT scnrxt
scnrxt0:
mov bx,bp ;paint count = 0
mov dx,bp ;skip count = 0
mov cl,bl ;already-painted-flag = 0
mov b$OffC,di ;return cursor offset
mov b$MaskC,ch ;return cursor mask
scnrxt:
mov si,SaveCa ;returning SaveCm and
mov al,SaveCm ; SaveCm
cEnd
;***
; LineSetup
;
;Purpose:
; This routine is called at the beginning of LineX, LineY, and LineV.
; It handles the buffer half splitting of the CGA and quadrant row
; splitting of the HGC.
; (See discussion of the architecture in the LLCGA and LLHGC headers).
;Entry:
; DX = negative for up, otherwise down
;Exit:
; DX = up/down move assumption
;Uses:
; none.
;Exceptions:
;******************************************************************************
cProc LineSetup,<NEAR>
cBegin
OR DX,DX ;Y difference negative? (up)
MOV DX,b$UpSub ;assume so, use UP subtractor
JS LineSetupExit ;go if correct assumption
MOV DX,b$DnSub ;no, use DOWN subtractor
LineSetupExit:
cEnd
;***
; B$CgaLineX
;
;Purpose:
; Draw an X-major line for CGA modes.
;Entry:
; AH = color (b$AttrC)
; AL = bit accumulator
; BX = point count
; CH = bit mask
; CL = trash for twiddle and pixel shift count
; DX = BP change for Y movement (UpSub or DnSub)
; SI = delta decision value
; DI = line style
; BP = video offset
; ES = video segment
; Incr1 = major axis delta update value
; Incr2 = minor axis delta update value
; UpDnAdd = corrector for DX subtraction
;Exit:
; None
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
cProc B$CgaLineX,<PUBLIC,NEAR>
cBegin
CALL LineSetup
XCHG BX,CX ;point count to BX
MOV CL,b$BitsPerPixel
LineCXloop:
ROL DI,1 ;next line style bit
JNC LineCX2 ;go if bit is 0 not to plot
OR AL,CH ;OR this bit into byte mask
LineCX2:
OR SI,SI ;time to move in Y (+ or 0 delta)?
JNS LineCX4 ;go if so
ADD SI,b$Incr1 ;update delta for X movement
ROR CH,CL ;move to next X
JC LineCX3 ;go if not still in same byte
DEC BX
JNZ LineCXloop ;go for more
JMP SHORT LineCX7 ; or exit
LineCX3:
MOV CL,AH ;get color, dump accumulated pixels
XOR CL,ES:[BP] ;change masked bits of video byte
AND CL,AL ; to color in attribute byte
XOR ES:[BP],CL ;(twiddle)
XOR AL,AL ;clear pixel accumulator
MOV CL,b$BitsPerPixel ;reload bits per pixel
INC BP ;go to next byte
DEC BX
JNZ LineCXloop ;go for more
JMP SHORT LineCX7 ; or exit
LineCX4:
ADD SI,b$Incr2 ;update delta for Y movement
MOV CL,AH ;get color, dump accumulated pixels
XOR CL,ES:[BP] ;change masked bits of video byte
AND CL,AL ; to color in attribute byte
XOR ES:[BP],CL ;(twiddle)
XOR AL,AL ;clear pixel accumulator
MOV CL,b$BitsPerPixel ;reload bits per pixel
ROR CH,CL ;move to next X
ADC BP,0 ;(+1 if next X byte)
sub BP,DX ;make the assumed Y movement
jnb LineCX5 ;go if no problem
add BP,b$UpDnAdd ;undo SUB + perform correct movement
LineCX5:
DEC BX
JNZ LineCXloop ;go for more
LineCX7: ;flush accumulated pixels
XOR AH,ES:[BP] ;change masked bits of video byte
AND AH,AL ; to color in attribute byte
XOR ES:[BP],AH ;(twiddle)
cEnd
;***
; B$CgaLineY
;
;Purpose:
; Draw a Y-major line for CGA modes.
;Entry:
; AH = color (b$AttrC)
; AL = bit mask
; BX = point count
; CH = trash for twiddle
; CL = pixel shift count
; DX = BP change for Y movement (UpSub or DnSub)
; SI = delta decision value
; DI = line style
; BP = video offset
; ES = video segment
; Incr1 = major axis delta update value
; Incr2 = minor axis delta update value
; UpDnAdd = corrector for DX subtraction
;Exit:
; None
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
cProc B$CgaLineY,<PUBLIC,NEAR>
cBegin
call LineSetup
XCHG BX,CX ;point count to BX
MOV CL,b$BitsPerPixel
LineCYloop:
ROL DI,1 ;next line style bit
JNC LineCY2 ;go if bit is 0 not to plot
MOV CH,AH ;get color, dump accumulated pixels
XOR CH,ES:[BP] ;change masked bits of video byte
AND CH,AL ; to color in attribute byte
XOR ES:[BP],CH ;(twiddle)
LineCY2:
OR SI,SI ;time to move in X (+ or 0 delta)?
JNS LineCY3 ;go if so
ADD SI,b$Incr1 ;update delta for Y movement
sub BP,DX ;make the assumed Y movement
jnb LineCY2A ;go if no problem
add BP,b$UpDnAdd ;undo SUB + perform correct movement
LineCY2A:
DEC BX
JNZ LineCYloop
ret
LineCY3:
ADD SI,b$Incr2 ;update delta for X movement
ROR AL,CL ;move to next X
ADC BP,0 ;(+1 if next X byte)
sub BP,DX ;make the assumed Y movement
jnb LineCY5 ;go if no problem
add BP,b$UpDnAdd ;undo SUB + perform correct movement
LineCY5:
DEC BX
JNZ LineCYloop ;go for more
cEnd
;***
; B$CgaLineV
;
;Purpose:
; Draw a vertical line for CGA modes.
;Entry:
; AH = color (b$AttrC)
; AL = bit mask
; BH = trash for twiddle
; BL = unused
; CX = point count
; DX = BP change for Y movement (UpSub or DnSub)
; SI = UpDnAdd = corrector for DX subtraction
; DI = line style
; BP = video offset
; ES = video segment
;Exit:
; None
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
cProc B$CgaLineV,<PUBLIC,NEAR>
cBegin
call LineSetup
MOV SI,b$UpDnAdd ;to register here
LineCVloop:
ROL DI,1 ;next line style bit
JNC LineCV2 ;go if bit is 0 not to plot
MOV BH,AH ;get color, dump accumulated pixels
XOR BH,ES:[BP] ;change masked bits of video byte
AND BH,AL ; to color in attribute byte
XOR ES:[BP],BH ;(twiddle)
LineCV2:
sub BP,DX ;make the assumed Y movement
jnb LineCV5 ;go if no problem
add BP,SI ;undo SUB + perform correct movement
LineCV5:
LOOP LineCVloop ;go for more
cEnd
sEnd GR_TEXT
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -