📄 llegasup.asm
字号:
CALL TILSET ;set up for copy of off-screen tile
; NOTE: This call has the effect of immunizing all bits from
; processor writes therefore, we must clear the bit mask
; following the write if tiling is on.
; QCG tiling always does slow loop, so 2-plane hack isn't needed?
TEST b$Planes,4 ;check for four-plane graphics mode
JNZ WRITE4 ;if 2 planes, need byte-by-byte write routine
; QCG: would need to fix bkg mask here if using this code
OR BH,BH ;see whether SCANR or SCANL
JNZ CALLFT ;non-zero flag indicates move left
CALL WRTRGT ;zero indicates move right
JMP SHORT CLRBT2
CALLFT:
CALL WRTLFT
JMP SHORT CLRBT2
WRITE4:
REP STOSB
CLRBT2:
EGAINT10STI ; reenable interrupts at common exit
MOV CL,1 ;single pixels counted in B$EgaCHKBTR calls
;non-zero as pixels changed flag
cEnd
;***
; WRTTIL
;Purpose:
; Used for writing first and last bytes, possibly partial bytes,
; to the screen when tiling is on for EGA modes.
; At entry, the bit mask has been set up for the byte to write, and the
; contents have been latched.
; This routine writes the relevant bits to each plane one at a time,
; using the map mask register to enable the planes from 3 to 0 and
; writing from AttrTile from offset 3 down to 0.
;
;Entry:
; ES:DI = screen address
; AttrTile = tile value to write
;Exit:
; None
;Uses:
; per conv.
;Exceptions:
;*******************************************************************************
WRTTIL:
PUSH DX
PUSH BX
MOV DX,SEQADD ;index port for sequencer
MOV AL,LOW MMREG ;index to Map Mask Register
OUT DX,AL
INC DX
MOV AL,8H ;start with plane 3
MOV BX,3
WRTPLN:
OUT DX,AL ;set up for one plane
MOV AH,AttrTile[BX] ;get tile pattern for that plane
MOV ES:[DI],AH ;write to one plane
MOV AH,ES:[DI] ;latch that write
DEC BX
SHR AL,1 ;next plane down the list
JNB WRTPLN ;repeat 3,2,1,0
DEC DX ;back to SEQADD
MOV AL,MMREG
OUT DX,AL ;index the register
XCHG AL,AH
MOV AL,0FH ;reeanable all planes
INC DX ;to data port
OUT DX,AL
POP BX
POP DX
RET
;***
; TILSET
;Purpose:
; Prepares for write of whole tile bytes to the screen in the following
; fashion :
;
; i. uses the routine WRTTIL to write the tile pattern, plane by
; plane, at the first offscreen address (6D60H); and, if we are
; in odd/even mode, writes it at the second offscreen address also
; ii. sends 0 to Bit Mask Register to indicate all bits immune
; iii.reenables write to all planes
;
; This sets up the card so that it will always write not from processor
; data but from the latches. If more than 64K, mode 10H, we can perform
; one latch read at the off-screen address and then write on-screen bytes
; in the tile pattern simply by changing the address back on-screen and
; asking for writes to the screen.
; If we are in odd/even mode, we must perform a latch for each byte
; written, at the even address for even bytes, at the odd address for odd
; bytes. These reads occur within the routines WRTRGT and WRTLFT, which
; then write to the screen from the latches, byte by byte.
;Entry:
; ES:DI = screen address
;Exit:
; None
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
TILSET: ;this routine altered for Modes D,E support
TEST b$Planes,4 ;see if 4-plane tile
JNZ TILST4 ;if so, just write first whole byte,latch,exit
PUSH DI ;for odd/even mode, save on-screen byte address
MOV DI,OFFSCN ;and substitute offscreen address (fancy
CALL WRTTIL ;monitor only)
INC DI ;if 2-plane, move to odd offscreen address
CALL WRTTIL ;and write to the 2 odd planes
POP DI ;restore on-screen address
JMP SHORT TILSEX ;no need to latch for 2-plane tile
TILST4:
CALL WRTTIL
MOV AL,ES:[DI] ;latch
TILSEX:
MOV AL,BMKREG ;send 0 to Bit Mask Register
OUT DX,AL ;index the bit mask register
XOR AL,AL ;disable all bits
INC DX ;to data port
OUT DX,AL
DEC DX ;back to index port
RET
;***
; B$EgaPIXCNT
;Purpose:
; Whether or not we actually change any pixels, we have to send
; the number "painted".
;
;Entry:
; BP = number of whole bytes painted
; DX = number of single pixels painted
;Exit:
; BX = total number of pixels painted
;Uses:
; BP, DX
;Exceptions:
;***************************************************************************
cProc B$EgaPIXCNT,<PUBLIC,NEAR>
cBegin
SHL BP,1 ;no. whole bytes * 2
SHL BP,1 ; * 4
SHL BP,1 ; * 8
SCNEX1:
ADD DX,BP ;pixel count
MOV BX,DX
cEnd
;***
; B$EgaSETCMP
;Purpose:
; Set color compare register to current paint attribute.
;
; This routine os called to set up the color compare register for
; PIXLF2/PIXLF3/PIXRT2/PIXRT3. Since these routines can take more
; time than is allowed between CLI/STI, this routine must use an
; EGAINT10 call to set the reg.
;Entry:
; b$AttrC = attribute
;Exit:
; None
;Uses:
; per conv.
;Exceptions:
;*****************************************************************************
cProc B$EgaSETCMP,<PUBLIC,NEAR>,<DX>
cBegin
MOV DX,GRPADD
MOV AL,LOW CLCREG
OUT DX,AL ;index the color compare register
MOV AL,b$AttrC
INC DX ;to data port
OUT DX,AL
cEnd
;***
; CLRMSK
;Purpose:
; Clear bit mask so full bytes will be written.
;Entry:
; None
;Exit:
; None
;Uses:
; per conv.
;Exceptions:
;****************************************************************************
CLRMSK:
MOV AX,0FFH SHL 8 + BMKREG ;AH=FF,AL=8
OUT DX,AL ;index the bit mask register
XCHG AL,AH
INC DX ;to data port
OUT DX,AL
DEC DX ;back to index port
RET
;***
; B$EgaCHKBTR
;Purpose:
; Check byte right.
; Look through byte setting up bit mask.
; BX is used for bit masks, left and right bytes
;
;Entry:
; AL = border bits set
; AH = viewport edge mask if in this byte
; CH = bit mask
; DX = count of pixels painted so far
;Exit:
; BH = final bit mask
; CH = updated b$MaskC
; DX = updated to reflect pixels painted
;Uses:
; per conv.
;Exceptions:
;****************************************************************************
cProc B$EgaCHKBTR,<PUBLIC,NEAR>
cBegin
MOV BH,CH ;initial bit mask
;if viewport edge coincides with a border pixel, don't count as painted
; TEST BH,AH ;is this viewport edge pixel?
; JNZ BYTEX1 ;yes, set pixels (BH) and exit with
; current b$MaskC
BYTLP:
TEST CH,AL ;check for border pixel
JNZ BYTEXT
OR BH,CH ;add pixel to set
TEST BH,AH ;have we just OR'd in viewport edge?
JNZ BYTEX1 ;if so, exit with CH current and
; BH=bit mask
INC DX ;count pixels painted
ROR CH,1 ;move over one
JNB BYTLP ;repeat if not end of byte
ROL CH,1 ;if off edge, rotate bit in at right
BYTEXT:
; Final bit mask returned in BH.
NOT AL ;0 if border pixel(s) in AL
AND BH,AL ;cross out border pixel in bit mask
RET
; This exit only if viewport edge was encountered.
BYTEX1:
INC DX ;indicate one (more) pixel set
cEnd
;***
; B$EgaCHKBTL
;Purpose:
; Check byte left.
; Look through byte setting up bit mask.
; BX is used for bit masks, left and right bytes
;
;Entry:
; AL = border bits set
; AH = viewport edge mask if in this byte
; CH = bit mask
; DX = count of pixels painted so far
;Exit:
; BH = final bit mask
; CH = value for updating b$MaskC
; DX = updated to reflect pixels painted
;Uses:
; per conv.
;Exceptions:
;**************************************************************************
cProc B$EgaCHKBTL,<PUBLIC,NEAR>
cBegin
; First check whether least significant bit is border (thinking
; right to left). If so, we have moved one byte too far to the
; left for b$OffC, and want to set nothing in this byte.
TEST AL,CH
JZ BYTLF0
INC DI ;increment for b$OffC
JMP SHORT BYTLFX
BYTLF0:
MOV BH,CH ;initial bit mask
TEST BH,AH ;is this viewport edge pixel?
JNZ BYTLF1 ;yes, set pixels (BH) and exit with
; preexisting b$MaskC
BYTLFT:
TEST CH,AL ;check for border pixel
JNZ BYTLFX
OR BH,CH ;add pixel to set
TEST BH,AH ;test for viewport edge bit encountered
JNZ BYTLF1 ;if found, exit with CH at that bit
INC DX ;count pixels painted
ROL CH,1 ;move over one
JNB BYTLFT ;repeat if not end of byte
BYTLFX:
ROR CH,1 ;else set up as rightmost pixel
NOT AL
AND BH,AL ; final bit mask returned in BH
RET
BYTLF1: ;this exit only if viewport edge bit encountered
INC DX ;count one (more) pixel painted
cEnd
;***
; PIXRT2
;Purpose:
; Check for non-paint pixels right for 4 plane EGA modes.
; Look through entire range of non-border pixels left to right
; to determine whether any will actually change color.
; AL is used for Color Don't Care mask
;
;Entry:
; SI = byte address of leftmost byte in range
; BL = bit mask for leftmost byte
; BH = bit mask for rightmost byte
; DI = total number of whole bytes -1
; ES = video segment
;Exit:
; CL = 0 if no pixels found to change, non-zero if pixels to change
;Uses:
; per conv.
;Exceptions:
;****
cProc PIXRT2,<NEAR>
cBegin
XOR CL,CL ;maybe no bits change
; read first byte
MOV AL,ES:[SI] ;bit pattern of first byte with 0's where
;color not paint attribute
AND AL,BL ;AND now produces difference if non-paint
;bit in significant position
XOR AL,BL ;for significant bits in our first byte (bit
;set in BH), then non-paint will be one
JNZ BITFDR ;found a bit to change
OR DI,DI ;any more bytes?
JZ PIXLAST ;Brif not, test the last byte
; Look at whole bytes within viewport range until non-paint color found.
LKPNTR:
INC SI
MOV AL,ES:[SI]
NOT AL ;check if all bits set (all paint color)
OR AL,AL ;NOT does not affect flags
JNZ BITFDR
DEC DI
JNZ LKPNTR ;keep looking until search of complete
;bytes is exhausted
; On last byte now, mask in BH.
PIXLAST:
INC 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 NOBITR
BITFDR:
MOV CL,AL ;set change bits flag to non-zero
NOBITR:
cEnd
;***
; B$EgaTILRGT
;Purpose:
; Check for non-paint pixels right 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 leftmost partial byte
; BH = bit mask for rightmost 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$EgaTILRGT,<PUBLIC,NEAR>,<DX,BP>
cBegin
PUSH b$OffC
PUSH b$PenC
PUSH BX ;copy for BH check
MOV ByteCount,DI ;whole byte counter
MOV AL,BL ;copy bit mask from BL
OR AL,AL ;make sure at least 1 bit is set
JZ TILRT5
CALL LOWCHK ;check first partial byte (uses mask in AL)
JNZ TILRT1 ;if no carry, non-match was found
TILRT5:
CMP ByteCount,0 ;see whether whole bytes to check
JZ TILRT4
TILRT2:
INC SI
MOV b$OffC,SI
MOV b$MaskC,80H
XOR BP,BP ;offset to color array
TILRT3:
CALL [b$ReadC]
CMP AL,ColorBits[BP] ;check for non-match
JNZ TILRT1
INC BP
SHR b$MaskC,1 ;move to next bit
JNB TILRT3
DEC ByteCount
JNZ TILRT2 ;keep looking until all whole bytes done
TILRT4:
POP BX ;get bit mask in BH
OR BH,BH
PUSH BX
JZ TILRT6 ;BH=0 indicates no "last byte"
MOV AL,BH ;get last partial byte
INC SI
CALL HICHK
JNZ TILRT1 ;exit if non-match found
TILRT6:
MOV CL,-1
TILRT1:
INC CL ;non-zero if pixels changed
POP BX
POP b$PenC
POP b$OffC
cEnd
;***
; PIXLF2
;Purpose:
; Check for non-paint pixels left for 4 plane EGA modes.
; Look through entire range of non-border pixels right to left
; to determine whether any will actually change color.
; BH/BL = bit masks for leftmost and rightmost bytes, respectively
; DI = total whole bytes between first and last
;
;Entry:
; SI = byte address of rightmost byte in range
; BL = bit mask for rightmost byte
; BH = bit mask for leftmost byte
; DI = total number of whole bytes
; ES = video segment
;Exit:
; CL = 0 if no pixels found to change, non-zero if pixels to change
;Uses:
; per conv.
;Exceptions:
;****
cProc PIXLF2,<NEAR>
cBegin
XOR CL,CL ;maybe no bits change
; read first byte
MOV AL,ES:[SI] ;bit pattern of first byte with 0's where
;color not paint attribute
AND AL,BL ;AND now produces difference if non-paint
;bit in significant position
XOR AL,BL ;for significant bits in our first byte (bit
;set in BH), then non-paint will be one
JNZ BITFDL ;found a bit to change
OR BH,BH ;see if only one byte
JZ NOBITL ;nothing to paint
OR DI,DI ;see if only a "last byte"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -