📄 llegasup.asm
字号:
;Entry:
; b$SegC = video segment
; b$EgaWrMd = EGA write mode to set up
;Exit:
; ES = video segment
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
cProc B$EgaSetPixFirstC,<PUBLIC,NEAR>
cBegin
mov es,b$SegC ;ES = video segment for B$SetPix
MOV DX,GRPADD ;address of graphics index port
MOV AL,RWMREG ;index the graphics controller mode reg
OUT DX,AL
MOV AL,b$EgaWrMd ;write mode 2; odd/even or sequential addr.
INC DX ;address data port
OUT DX,AL
MOV AL,BMKREG ;index to the bit mask register
DEC DX ;leave bit mask register addressed so all
OUT DX,AL ; we have to do is output the mask
cEnd
;***
; B$EgaLineX
;
;Purpose:
; Draw an X-major line for EGA modes.
;Entry:
; AH = color (b$AttrC)
; AL = bit accumulator
; BH = bit mask
; BL unused
; CX = point count
; DX = EGA graphics controller data port
; 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
; IncrY = BP change for Y movement
;Exit:
; None
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
cProc B$EgaLineX,<PUBLIC,NEAR>
cBegin
MOV DX,GRPADD+1 ;graphics controller data port for bit mask
LineEXloop:
ROL DI,1 ;next line style bit
JNC LineEX2 ;go if bit is 0 not to plot
OR AL,BH ;OR this bit into byte mask
LineEX2:
OR SI,SI ;time to move in Y (+ or 0 delta)?
JNS LineEX4 ;go if so
ADD SI,b$Incr1 ;update delta for X movement
ROR BH,1 ;move to next X
JC LineEX3 ;go if not still in same byte
LOOP LineEXloop
JMP SHORT LineEX7
LineEX3:
OUT DX,AL ;output mask from accumulated pixels
MOV AL,AH ;color for write
XCHG AL,ES:[BP] ;read loads latches, write color thru mask
XOR AL,AL ;clear pixel accumulator
INC BP ;go to next byte
LOOP LineEXloop
JMP SHORT LineEX7
LineEX4:
ADD SI,b$Incr2 ;update delta for Y movement
OUT DX,AL ;output mask from accumulated pixels
MOV AL,AH ;color for write
XCHG AL,ES:[BP] ;read loads latches, write color thru mask
XOR AL,AL ;clear pixel accumulator
ROR BH,1 ;move to next X
ADC BP,b$IncrY ;move to next Y (+1 if next X byte)
LOOP LineEXloop
LineEX7: ;flush accumulated pixels
OUT DX,AL ;output mask from accumulated pixels
XCHG AH,ES:[BP] ;read loads latches, write color thru mask
cEnd
;***
; B$EgaLineY
;
;Purpose:
; Draw a Y-major line for EGA modes.
;Entry:
; AH = color (b$AttrC)
; AL = bit mask
; BH = trash for XCHG
; BL unused
; CX = point count
; DX = EGA graphics controller data port
; 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
; IncrY = BP change for Y movement
;Exit:
; None
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
cProc B$EgaLineY,<PUBLIC,NEAR>
cBegin
MOV DX,GRPADD+1 ;graphics controller data port for bit mask
LineEYloop:
ROL DI,1 ;next line style bit
JNC LineEY2 ;go if bit is 0 not to plot
OUT DX,AL ;output bit mask
MOV BH,AH ;color for write
XCHG BH,ES:[BP] ;read loads latches, write color thru mask
LineEY2:
OR SI,SI ;time to move in X (+ or 0 delta)?
JNS LineEY3 ;go if so
ADD SI,b$Incr1 ;update delta for Y movement
ADD BP,b$IncrY ;move to next Y
LOOP LineEYloop
ret
LineEY3:
ADD SI,b$Incr2 ;update delta for X movement
ROR AL,1 ;move to next X
ADC BP,b$IncrY ;move to next Y (+1 if next X byte)
LOOP LineEYloop
cEnd
;***
; B$EgaLineV
;
;Purpose:
; Draw a vertical line for EGA modes.
;Entry:
; AH = color (b$AttrC)
; AL = bit mask
; BX = IncrY = BP change for Y movement
; CX = point count
; DI = line style
; BP = video offset
; ES = video segment
;Exit:
; None
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
cProc B$EgaLineV,<PUBLIC,NEAR>
cBegin
MOV DX,GRPADD+1 ;graphics controller data port for bit mask
OUT DX,AL ;output mask
MOV BX,b$IncrY ;to register here
LineEVloop:
ROL DI,1 ;next line style bit
JNC LineEV2 ;go if bit is 0 not to plot
MOV AL,AH ;color for write
XCHG AL,ES:[BP] ;read loads latches, write color thru mask
LineEV2:
ADD BP,BX ;to next Y
LOOP LineEVloop
cEnd
;***
; PutPreset/PutOther
;
;Purpose:
; Support routine for EGA PUT. Write to the specified screen byte
; the specified attribute (after NOTing it if entry point is Preset).
; Write will apply bit-wise logic as defined by the contents of
; DTRREG, which is set up in PUT action routines which then branch
; to PutOther.
;Entry:
; AH = attribute
; ES:DI = screen address
;Exit:
; DI incremented to next screen address
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
cProc PutPreset,<NEAR>
cBegin
not ah ;NEGATE DATA FOR PRESET
labelNP PutOther
xchg ah,es:[di] ;read loads latches, write sets data according
inc di ; to EGA function set in DTRREG
cEnd
labelW PutTable ;EGA write function according to put action
DB 10000B ;Or
DB 01000B ;And
DB 00000B ;Preset (data unmodified, but NOT before)
DB 00000B ;Pset (data unmodified)
DB 11000B ;Xor
;***
; B$EgaPutAction_64K
;
;Purpose:
; Set b$PutVector to appropriate PUT action routine for Screen 9/64K.
; Set up DTRREG according to PUT action table values so that next
; screen write will apply the requested PUT action to the data.
;Entry:
; AL = PUT action [0..4] representing (OR, AND, PRESET, PSET, XOR)
;Exit:
; b$PutVector set to entry point of appropriate PUT action routine
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
cProc B$EgaPutAction_64K,<PUBLIC,NEAR>
cBegin
mov bl,11001100B ;setup for first plane pair (after two shifts)
SKIP 2 ;fall thru to normal PutAction
cEnd <nogen>
;***
; B$EgaPutAction_F
;
;Purpose:
; Set b$PutVector to appropriate PUT action routine for Screen 10.
; Set up DTRREG according to PUT action table values so that next
; screen write will apply the requested PUT action to the data.
;Entry:
; AL = PUT action [0..4] representing (OR, AND, PRESET, PSET, XOR)
;Exit:
; b$PutVector set to entry point of appropriate PUT action routine
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
cProc B$EgaPutAction_F,<PUBLIC,NEAR>
cBegin ;(NOTE: SKIP above!!)
mov bl,01000100B ;setup for first plane (after two shifts)
SKIP 2 ;fall thru to normal PutAction
cEnd <nogen>
;***
; B$EgaPutAction
;
;Purpose:
; Set b$PutVector to appropriate PUT action routine for EGA modes.
; Set up DTRREG according to PUT action table values so that next
; screen write will apply the requested PUT action to the data.
;Entry:
; AL = PUT action [0..4] representing (OR, AND, PRESET, PSET, XOR)
;Exit:
; b$PutVector set to entry point of appropriate PUT action routine
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
cProc B$EgaPutAction,<PUBLIC,NEAR>
cBegin
;(NOTE: SKIPs above!!)
mov bl,10001000B ;setup for first plane (after 1 shift)
mov b$PlaneMask,bl
;NOTE: the plane mask is replicated in both nibbles for wrap-around
; shift, but will be masked to the low nibble for map-enabling
mov bx,GR_TEXTOFFSET PutPreset ;assume preset
cmp al,2 ;is it?
je IsPreset ;go if so
mov bx,GR_TEXTOFFSET PutOther ;all others use same code and
IsPreset: ; rely on EGA for operation
mov b$PutVector,bx ;save vector
mov bx,GR_TEXTOFFSET PutTable ;EGA function table
xlat cs:[bx] ;convert put action to EGA func
mov ah,al
MOV DX,GRPADD ;address graphics controller
mov al,DTRREG ;data rotate/function register
OutWord ;select EGA logical operation
cEnd
ASSUME DS:NOTHING
;***
; B$EgaNReadL_F
;
;Purpose:
; Read a line of pixels from the screen to an array for Screen 10.
;Entry:
; ES:DI = screen address
; DS:SI = array address
; CL = array align shift count
; BP = count of bits (not pixels) to read
; BH = plane to read from
;Exit:
; DS:SI = updated to array byte past point filled
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
cProc B$EgaNReadL_F,<PUBLIC,NEAR>
cBegin
shl bh,1 ;logical plane 0 = physical plane 0
;logical plane 1 = physical plane 2
cEnd <nogen> ;fall thru to regular NReadL
;***
; B$EgaNReadL
;
;Purpose:
; Read a line of pixels from the screen to an array for EGA modes.
;Entry:
; DS:SI = screen address
; ES:DI = array address
; CL = array align shift count
; CH = mask for last partial byte
; BP = count of bits (not pixels) to read
; BH = plane to read from
;Exit:
; ES:DI = updated to array byte past point filled
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
cProc B$EgaNReadL,<PUBLIC,NEAR>
cBegin
MOV DX,GRPADD ;address graphics controller
MOV al,RMPREG ;read map select register
out dx,al
mov al,bh
inc dx
out dx,al
mov ah,[si] ;preload hi byte
inc si
NRdLoop:
lodsb ;fill ax word with video bytes
mov bh,al ;this lo byte will become next hi byte
rol ax,cl ;align to array
sub bp,8 ;8 bits done
jbe NRdLast ;go if bit count exhausted
mov es:[di],ah ;save full byte
inc di
mov ah,bh ;move lo byte (BH) to hi byte (AH)
jnz NRdLoop ;loop if no offset overflow
call B$BumpES ;move array pointer over segment boundary
jmp short NRdLoop ;go do another
NRdLast:
and ah,ch ;strip unused bits from last byte
mov es:[di],ah ;save last byte
inc di
jnz NRdDone
call B$BumpES ;move array pointer over segment boundary
NRdDone:
cEnd
;***
; B$EgaNWriteL_F
;
;Purpose:
; Write a line of pixels from an array to the screen for Screen 10.
;Entry:
; ES:DI = screen address
; DS:SI = array address
; CL = array align shift count
; BP = count of bits (not pixels) to write
; DL = last partial byte mask
; DH = first partial byte mask
;Exit:
; DS:SI = updated to array byte past point used
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
cProc B$EgaNWriteL_F,<PUBLIC,NEAR>
cBegin
rol b$PlaneMask,1 ;logical plane 0 = physical plane 0
;logical plane 1 = physical plane 2
;must shift plane mask twice (1 more below)
cEnd <nogen> ;fall thru to regular NWriteL
;***
; B$EgaNWriteL
;
;Purpose:
; Write a line of pixels from an array to the screen for EGA modes.
;Entry:
; ES:DI = screen address
; DS:SI = array address
; CL = array align shift count
; BP = count of bits (not pixels) to write
; DL = last partial byte mask
; DH = first partial byte mask
; BH = plane
;Exit:
; DS:SI = updated to array byte past point used
;Uses:
; per conv.
;Exceptions:
;******************************************************************************
cProc B$EgaNWriteL,<PUBLIC,NEAR>
cBegin
rol b$PlaneMask,1 ;shift plane mask by one plane
push dx
MOV BL,DH ;first byte bit mask
MOV DX,GRPADD ;address graphics controller
mov al,BMKREG ; bit mask register
OUT DX,AL ;set index register
XCHG AX,BX ;set up data in AL, plane moves to AH
INC DX
OUT DX,AL
DEC DX
MOV AL,RWMREG ;set r/w mode 0
OUT DX,AL
XOR AL,AL
INC DX
OUT DX,AL
DEC DX
MOV al,RMPREG ;read map select register
OUT DX,AL
MOV AL,AH ;[al] = plane number
INC DX
OUT DX,AL
MOV DX,SEQADD ;address the sequencer
MOV AL,MMREG ; map mask register
OUT DX,AL
mov al,b$PlaneMask ;get plane mask bit
and al,0FH ;strip to nibble
INC DX
OUT DX,AL
pop dx
mov ah,[si] ;preload byte from array
inc si
jnz NWrOvfl1
call B$BumpDS ;move array pointer over segment boundary
NWrOvfl1:
.erre ID_SSEQDS ;assumes ss = ds
mov bx,ss:[b$PutVector] ;preload PUT action vector
ror ax,cl ;align to video
add bp,cx
sub bp,8 ;account for first partial byte
jbe NWrLast ;go if last byte
call bx ;put the byte
mov dh,0FFH ;mask for whole bytes in the middle
push ax
push dx
mov ah,dh ;middle byte bit mask
MOV DX,GRPADD ;address graphics controller
mov al,BMKREG ; bit mask register
OUT DX,AL
XCHG AL,AH ;bit mask to AL and output
INC DX
OUT DX,AL
EGAINT10STI ;reenable ints if using EGAINT10
pop dx
pop ax
jmp short NWrLoop2
NWrLoop:
call bx ;put the byte via PUT action vector
NWrLoop2:
rol ax,cl ;re-align to array
lodsb ;fill ax word with array bytes
or si,si
jz NWrOvfl3 ;go if address overflow
NWrOvfl2:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -