📄 draw.asm
字号:
; ah = psw
; psw.z set if args are f.p.
; psw.z clear if args are integer
;Outputs:
; move down and left specified amount
;****
DRWGGG:
NEG DX ;MOVE -X,+Y
JMP SHORT DRWHHC ;MAKE DY POSITIVE & GO
;***
;DMOVE
;Purpose:
; Move to the specified location
;Input:
; b$fTrans TRUE if coords to be interpreted as floating point
; b$fTrans FALSE if coords to be interpreted as integer
;Outputs:
; graphics cursor position updated
;****
DMOVE:
CALL B$FETCHZ ;GET NEXT CHAR AFTER COMMA
CMP AL,'+' ;IF '+' OR '-' THEN RELATIVE
JZ MOVREL
CMP AL,'-'
MOVREL:
PUSHF ;SAVE ABS/REL FLAG ON STACK
CALL B$DECFET ;BACK UP SO B$VALSCN WILL SEE "-"
CALL B$VALSCN ;GET X VALUE
PUSH DX ;SAVE IT
GetComma:
CALL B$FETCHZ ;NOW CHECK FOR COMMA
CMP AL,',' ;COMMA?
JZ MOVRE2
JMP B$ERR_FC
MOVRE2:
CALL B$VALSCN ;[DX]= Y
POP CX ;[CX]= X
MOV BX,8080h ; x,y fraction is 1/2
POPF ;GET ABS/REL FLAG
JNZ DRWABS ;NZ - ABSOLUTE
DOMOVR:
CALL DSCLDE ;ADJUST Y OFFSET BY SCALE
PUSH DX ;SAVE Y OFFSET
MOV DX,CX ;GET X INTO [DX]
CALL DSCLDE ;GO SCALE IT.
MOV CX,DX ;[CX]= Adjusted x
POP DX ;[DX]= Adjusted y
XOR AX,AX ;Assume no low order 8 bits
CMP BYTE PTR B$COSA+2,0 ;Check for cos(ang) = 0 (poss. no turnangle)
JZ CHKSINE ; brif cos(0) = 0; if sin(ang) = 0, no TA given
CMP BYTE PTR B$COSA+3,LOW 0 ;Check for 180 with B$COSA neg., B$DSINA= 0
JNS FRCANG ;brif cos(ang) was a positive number
CHKSINE:
CMP WORD PTR B$DSINA+2,0 ;If exp 0, then Angle is 0.
JZ DRWAFN ;Skip floating stuff if no angle..
; else calculate:
; Delta y [DXAH]:= (x*B$MSINA)+(y*B$COSA)
; Delta x [CXAL]:= (x*B$COSA) +(y*B$DSINA)
FRCANG:
PUSH DX ;Save y
PUSH CX ;Save x
MOV BX,OFFSET DGROUP:B$COSA
CALL FMULDX ;ST0 = (y*B$COSA)
POP DX ;Get x
PUSH DX
MOV BX,OFFSET DGROUP:B$MSINA
CALL FADARG ;[CXAL]= (x*B$MSINA)+(y*B$COSA)
POP DX ;Get x
POP BX ;Get y
PUSH CX
PUSH AX ;Save 24 bit y delta
PUSH BX ;Save y
MOV BX,OFFSET DGROUP:B$COSA
CALL FMULDX ;ST0 = (x*B$COSA)
POP DX ;Get y
MOV BX,OFFSET DGROUP:B$DSINA
CALL FADARG ;[CXAL]= (x*B$COSA)+(y*B$DSINA)
POP DX
MOV AH,DL ;[CXAL]= x Delta
POP DX ;[DXAH]= y Delta
DRWAFN:
ADD AL,[B$DFRACX] ;incr x low
JNB DRWXNC ;Brif no ovf
INC CX ;incr x high
DRWXNC:
ADD AH,[B$DFRACY] ;incr y low
JNB ANGPOS ;Brif no ovf
INC DX ;incr y high
ANGPOS:
PUSH AX ;Save fractional x,y
CALL B$GTABSC ;[CX]= True x, [DX]= True y
POP BX ;Want fractional x,y in [BX]
DRWABS:
MOV AL,BYTE PTR B$DRWFLG ;SEE WHETHER WE PLOT OR NOT
ADD AL,AL ;CHECK HI BIT
JB DSTPOS ;JUST SET POSITION.
PUSH AX ;SAVE THIS FLAG
PUSH BX ;Save fractional x,y
PUSH CX ;SAVE X,Y COORDS
PUSH DX ;BEFORE SCALE SO REFLECT DISTANCE OFF
CALL B$CLINE2
POP DX
POP CX ;GET THEM BACK
POP BX
POP AX ;GET BACK FLAG
DSTPOS:
ADD AL,AL ;SEE WHETHER TO STORE COORDS
JB DNSTOR ;DON'T UPDATE IF B6=1
MOV B$GRPACY,DX ;UPDATE GRAPHICS AC
MOV B$GRPACX,CX
MOV WORD PTR [B$DFRACX],BX ;Store fractional x,y
DNSTOR:
MOV BYTE PTR B$DRWFLG,0 ; CLEAR SPECIAL FUNCTION FLAGS
RET
DNOMOV:
MOV AL,64 ;SET BIT SIX IN FLAG BYTE
JMP SHORT DSTFLG
DNOPLT:
MOV AL,128 ;SET BIT 7
DSTFLG:
OR BYTE PTR B$DRWFLG,AL ;STORE UPDATED BYTE
RET
DPAINT:
; Initialize the paint queue without compacting it.
cCALL B$INTQNOCPCT ; Initialize it w/o compaction
XOR AL,AL
MOV BYTE PTR B$TILNDX,AL ;Clear Tile index
MOV BYTE PTR B$TIPROG,AL ;Clear Tile proceed flag
MOV BYTE PTR B$TILFLG,AL ;Initially no FG_TILE
MOV BYTE PTR $BGTNUL,AL ;Setup Null BG FG_TILE pattern
CALL B$VALSCN ;GET Fill color
PUSH DX ;SAVE IT
CALL B$FETCHZ ;NOW CHECK FOR COMMA
CMP AL,',' ;COMMA?
JZ DPAIN2
JMP B$ERR_FC
DPAIN2:
CALL B$VALSCN ;[DX]= Border Color
POP AX ;[AL]= fill color
PUSH DX ;In case SetAttr trashes DX
CALL [b$SetAttr] ;Set Fill attribute
POP DX
JB NCFCER ;Brif illegal
MOV AL,DL ;[AL]= Border color
CALL B$PaintInit ;Init Paint, check border attr
JB NCFCER ;Brif illegal
MOV CX,[B$GRPACX] ;[CX]= x
MOV DX,[B$GRPACY] ;[DX:= y
;The label PNTDRW no longer exists due to restructuring of PAINT statement
;12/7/83 JMB
; JMP PNTDRW ;Do the PAINT..
CALL B$INVIEW
JNB PAIRET ;Exit if out of FG_VIEW
CALL [b$MapXYC] ;Graphics cursor:=(CX,DX)
JMP B$PAINTBEG ;Go Paint it
DSCALE:
JNB NCFCER ;FC ERROR IF NO ARG
CMP DX,256 ;MAKE SURE LESS THAN 256
JNB NCFCER
OR DX,DX
JZ NCFCER ;DONT ALLOW SCALE OF ZERO
MOV BYTE PTR B$DRWSCL,DL ;STORE SCALE FACTOR
PAIRET: ;Early return from paint in draw
RET
NCFCER: ; moved here to fix jump out of range
JMP B$ERR_FC
DSCLDE:
MOV AL,BYTE PTR B$DRWSCL ;GET SCALE FACTOR
OR AL,AL ;ZERO MEANS NO SCALING
JNZ DSCLD0
RET
DSCLD0:
MOV BX,0
DSCLP:
ADD BX,DX ;ADD IN [DX] SCALE TIMES
DEC AL
JNZ DSCLP
XCHG DX,BX ;PUT IT BACK IN [DX]
MOV AL,DH ;SEE IF VALUE IS NEGATIVE
ADD AL,AL
PUSHF ;SAVE RESULTS OF TEST
JNB DSCPOS
DEC DX ;MAKE IT TRUNCATE DOWN
DSCPOS:
SHR DX,1 ;DIVIDE BY FOUR
SHR DX,1
POPF ;SEE IF WAS NEGATIVE
JNB DSCPOX ;ALL DONE IF WAS POSITIVE
DSCPO1:
OR DH,192 ;OR IN HIGH 2 BITS TO MAKE NEGATIVE
INC DX ;ADJUST SO TRUNCATING TO LOWER VALUE
DSCPOX:
RET
DCOLR:
JNB NCFCER ;FC ERROR IF NO ARG
MOV AL,DL ;GO SET ATTRIBUTE
CALL [b$SetAttr]
JB NCFCER ;ERROR IF ILLEGAL ATTRIBUTE
RET
DANGLE:
JNB NCFCER ;ERROR IF NO ARG
CMP DL,4 ;MAKE SURE LESS THAN 4
JNB NCFCER ;ERROR IF NOT
MOV AL,90 ;Map B$DRWANG 0,1,2 or 3
MUL DL ; to 0,90,180 or 270 degrees
MOV DX,AX
JMP SHORT TANGL1
TANGLE:
CALL B$FETCHZ ;Get char after "T"
CMP AL,'A' ;Must be Angle
JNZ NCFCER ;else error
CALL B$VALSCN ;[DX]= degrees
MOV AX,360
OR DX,DX ;See if negative
JNS TANGL0
ADD DX,AX ;neg so add 360 (let 'em go backwards)
TANGL0:
CMP AX,DX ;Must be .le. 360 degrees
JB NCFCER ; else error..
TANGL1:
;IFN SCNROT,<
; CALL SCNDIR
; JZ NoARot ;Screen is horizontal
; SUBI DX,360d ;Swap X and Y
; NEG DX
;NoARot:
;> ;IFN FG_SCRNROT
MOV BYTE PTR B$DRWANG,DL
MOV BX,DX
CALL B$fmldw ; push [BX] to ST0
FMUL FP_PI180 ; RAD(ang)= ang*(PI/180)
FLD ST(0) ; duplicate this on numeric stack
CALL B$COS4 ; ST0 = cos((Rad(ang))
FSTP DWORD PTR B$COSA ; B$COSA= COS((Rad(ang)), ST1 = Rad(ang)
CALL B$SIN4 ; Take Sin
FLD ST(0) ; duplicate SIN((Rad(ang)) on numeric stack
CALL GTASPF ; Get Aspect in [CXDX]
CALL B$fmlds ; load aspect to numeric stack
FMUL ; ST0 = SIN((Rad(ang))*Aspect,ST1 = SIN(Rad(ang))
FCHS ; ST0 = -SIN((Rad(ang))*Aspect, ST1 unchanged
FSTP DWORD PTR B$MSINA ; B$MSINA= -SIN((Rad(x))*Aspect
CALL B$fmlds ; ST0 = Aspect, ST1 = SIN(Rad(ang))
FDIV ; ST0 = SIN((Rad(ang))/Aspect
FSTP DWORD PTR B$DSINA ; B$DSINA= SIN((Rad(ang))/Aspect
FWAIT
RET
;FMULDX
;Purpose:
; Given an integer in DX and the address of a s.p. number in BX,
; multiply the two numbers, leaving the result on top of numeric stack
;Entry:
; DX contains an integer operand
; BX is a pointer to an s.p. operand
;Exit:
; ST0 contains the result of the multiplication
;Preserves:
; SI, DI
FMULDX:
PUSH BX
MOV BX,DX
CALL B$fmldw ; push number on numeric stack
POP BX
FMUL DWORD PTR [BX] ; multiply s.p. number time integer
RET
;FADARG
;Purpose:
; Given an integer in DX and the address of a s.p. number in BX,
; multiply the two numbers, with the result in ST0. Next,
; add arguments at ST0 and ST1. Scale result by 2^8 (i.e., multiply
; by 256), put 24-bit result in CX,AL (also in DX,AX)
;Entry:
; DX contains an integer operand
; BX is a pointer to an s.p. operand
;Exit:
; CX,AL contains 24-bit result.
;Preserves:
; SI, DI
FADARG:
CALL FMULDX ; multiply integer in DX by s.p. # at [BX]
FADD ; ST0 = ST0 + ST1
FMUL b$FP_256 ; scale result by 2^8 (i.e., mult. by 256)
CALL B$ftolrnd ; round, pop from ST0, get result in DX:AX
MOV CH,DL
MOV CL,AH ; in [CX,AL]
RET
GTASPF:
MOV CX,WORD PTR [B$ASPRF+2]
MOV DX,WORD PTR [B$ASPRF]
RET
sEnd GR_TEXT
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -