; 8 July 88 -- MFB cseg segment byte assume cs:cseg,ds:cseg,es:cseg org 100h ; head = (59b2h-100h) ; for use with ucc1.bld ; ( may need changing) head = (1176h-100h) ; if immediately iloaded ; on top of kernel2.img ; *********************** ; ; note -- not all labels are valid entry points ; valid entry points marked ;====== ; ; note also -- the order of (X Y color) variables is inconsistent ; therefore some words (ie EGABOX) are "corrected" by only being ; used indirectly (ie through DBOX) ; ; Corrections are not made here at the moment, as it would ; require re-writing many of the demonstration source files ; which directly use EGABOX etc, and were written in the early ; stages of EGAM.ASM. The corrections are made in UCC1.BLD -- where ; DBOX is defined -- and to be consistent, DPIX, and D4PIX are ; also defined as SYNONYMs for EGADOT and EGANIB ; ; Some "false" entry points must remain because all 'endproc ' ; must be followed by a dictionary string of some sort. ; -- ('endproc ' not only inserts a JMP THREAD -- it ; also reads the following string up to the first ; space into the dictionary) ; ;*********************** gradd = 3ceh ;graphics address register grwrt = 3cfh ;graphics write only register seqadd = 3c4h ;sequence address select register seqdat = 3c5h ;sequence data read/write register start: ;===== egam: ; ====> entry point ;===== ;set card to ega high res graphics mode MOV AH,0 ;set mode MOV AL,10h ; to 10 INT 10H nxt: MOV AH,0BH ;set palette MOV BH,1 ; palette combination (ie not background) MOV BL,1 ;palette 1 INT 10H db 'endproc ' db 'NEGAM ' ; ====> entry point ;===== negam: ; ====> entry point ;===== ;set ega high-res but don't clear buffer MOV AH,0 ;set mode MOV AL,90h ; to 10 with high bit set INT 10H jmp nxt db 'endproc ' db 'CGAM ' ; ====> entry point ;===== cgam: ;set card to CGA high res mono mode ;===== MOV AH,0 ;set mode MOV AL,6 ; to 6 INT 10H jmp nxt db 'endproc ' db 'NCGAM ' ; ====> entry point ;===== ncgam: ; ====> entry point ;===== ;set cga high-res but don't clear buffer MOV AH,0 ;set mode MOV AL,86h ; to 6 with high bit set INT 10H jmp nxt db 'endproc ' db 'NORM ' ; ====> entry point ;===== norm: ;reset normal text mode ;===== MOV AH,0 ;set mode MOV AL,3 ;normal INT 10H db 'endproc ' db 'NNORM ' ; ====> entry point ;===== mnorm: ;reset normal text mode, but don't clear buffer ;===== MOV AH,0 ;set mode MOV AL,83H ;normal INT 10H db 'endproc ' db 'EGADOT ' ; ====> entry point ( synonym DPIX in UCC1.BLD) ; light pixel at x,y (no clipping) ; x,y (column/row) in CX,DX (as for BIOS Int 10 call) ; all register contents on entry restored at exit ; ; stack ==> x y picval ==> TOS ; ;======= egadot: ;======= POP DX ;picval MOV (head+PICVAL),DX POP DX ;y value MOV (head+REGSAV),CX POP CX ;x value PUSH SI ;display type is EGA PUSH DI ;these two will need to be saved mov ax,dx ;to line up with BIOS parameter standard call dodot ; -6 POP DI POP SI MOV CX,(head+REGSAV) ; db 'endproc ' ; to create JMP THREAD db 'SETDOT ' ; ====> NOT an entry point => follows endproc SET_DOT: ;sets one point in CGA hires mode at the X co-ord in CX ;and the Y co-ord in AX. All but AX & CX registers saved ; JMP EGADOT ; set_dot not used any more ; CGADOT: PUSH SI ;display type is CGA PUSH DI ;these two will need to be saved sar ax,1 sar dx,1 MOV SI,CX ;copy of CX AND AX,0FEH ;strip odd/even bit SAL AX,1 SAL AX,1 SAL AX,1 MOV dx,AX ;bx=ax*8 SAL AX,1 SAL AX,1 ;AX=AX*32 ADD AX,dx ;ax=ax*40 SAR dx,1 ;low bit int cf JNB EVEN ADD AX,2000H ;adjust for odd row EVEN: MOV dx,SI SAR dx,1 SAR dx,1 SAR dx,1 ;cx=cx/8 ADD AX,dx ;final address in AX XCHG SI,AX AND AL,7 mov cl,7 sub cl,al ;7 - (x MOD 8) is bit # in byte mov al,1 ; sal al,cl ; al now contains bitmask MOV cx,BX ;save contents of BX ; MOV BX,0b800h ; VIDEO_BUFFER MOV ES,BX ;set ES to point to video buffer segment MOV BX,cx ;restore BX DOT1: OR AL,BYTE PTR ES:[SI] DOT2: MOV BYTE PTR ES:[SI],AL MOV AX,CS MOV ES,AX ; POP DI POP SI RET ; dodot: push dx push bx push ds mov bx,40h mov ds,bx mov bx,49h mov dl,[bx] cmp dl,6 pop ds pop bx jnz n6 pop dx call cgadot ret n6: cmp dl,10h pop dx jnz n10 jmp ok10 n10: ret ok10: PUSH SI ;display type is EGA PUSH DI ;these two will need to be saved push cx push dx ; x,y in cx,dx call setbyte ; -15 call setbit ; -15 jmp comn db 'endproc ' db 'EGANIB ' ; ====> entry point ( synonym D4PIX in UCC1.BLD ) ; stack ==> x y picval ==> TOS ;======= eganib: ;======= POP DX MOV (head+PICVAL),DX POP DX MOV (head+REGSAV),CX POP CX CALL EGABYTE ; -8 MOV CX,(head+REGSAV) db 'endproc ' db 'EGABYTE ' ; ====> NOT an entry point => follows endproc egabyte: PUSH SI ;display type is EGA PUSH DI ;these two will need to be saved push cx push dx mov ax,dx ;to line up with BIOS parameter standard ; x,y in cx,dx call setbyte pushf and al,0fh mov al,0f0h jz lozero mov al,0fh lozero: popf call setbit ;mmfb comn: MOV AX,0A000H MOV ES,AX ;set EGA hires video buffer MOV AL,BYTE PTR ES:[SI] ;Read at address A000:offset ;This latches all 4 bit planes. ;(The byte "read" is ignored.) MOV AL,0 MOV BYTE PTR ES:[SI],AL ;Write at address A000:offset ;This sets the bit-masked bits to '0' ;and stores the latched bytes to the ;bit planes ; MOV DX,seqadd ;Sequencer/Map Mode port address MOV AL,2 OUT DX,AL ;Select "Map Mask" register 2 MOV DX,seqdat ; SUB AX,AX ;make nul value ; OR BYTE PTR form,0 ; JNS MAKEDOT MOV AX,(head+picval) ;MAKEDOT: ;zero if erase mode, otherwise picval OUT DX,AL MOV AX,0A000H MOV ES,AX ;set EGA hires video buffer MOV AL,BYTE PTR ES:[SI] ; Latch the bit plane data. MOV AL,11111111b MOV BYTE PTR ES:[SI],AL ; Set bits to '1' in ; appropriate planes. call rstega ; MOV CX,(head+REGSAV) pop dx pop cx POP DI POP SI MOV AX,CS MOV ES,AX ret ; setbyte: ;; MOV DI,AX ;copy of AX MOV SI,CX ;and CX mov cl,3 sal ax,cl ;cl=3 mov dx,ax ;dx = ax * 8 dec cl ;cl becomes 2 sal ax,cl add ax,dx SAL AX,1 ;ax * 80 mov dx,si ; x value into dx inc cl ;cl becomes 3 sar dx,cl ; dx = dx/8 to find byte addr add ax,dx ;final address XCHG SI,AX ;place addr into SI ; restore x value to AX AND AX,7 ;x mod 8 mov cl,7 sub cl,al ;7 - (x MOD 8) is bit # in byte mov al,1 ; sal al,cl ; al now contains bitmask ret setbit: MOV DX,gradd ;3CEh Graphics Controller port address MOV AH,AL MOV AL,8 OUT DX,AL ; select register 8 MOV DX,grwrt ;3CFh MOV AL,AH OUT DX,AL ; load the bit mask into reg 8 ret rstega: MOV DX,seqadd MOV AL,2 ; Again, select ... OUT DX,AL ; ... Sequencer/Map Mask register 2. MOV DX,seqdat MOV AL,1111b ; Default map mask OUT DX,AL ; Enable all 4 bit planes MOV DX,gradd MOV AL,8 ; Again, select ... OUT DX,AL ; ... Graphics Controller register 8 MOV DX,grwrt MOV AL,11111111b ; Default bit mask OUT DX,AL ; Restore default bit mask ret db 'endproc ' ;no JMP THREAD needed - but following ; string has to be read into dictionary db 'EGABOX ' ; ====> entry point ; ; ****** NOTE ***** now redefined in UCC1.BLD as DBOX ; principally to allow parameters to be ; specified as X1 X2 Y1 Y2 picval ; ; stack ==> picval X1 X2 Y1 Y2 ==> TOS ;======= egabox: ;draw a filled box ;======= MOV (head+REGSAV),CX pop ax ;y2 pop cx ;y1 mov dx,cx ;dx = y1 sub ax,cx ;y2 - y1 jz nogo1 MOV bx,AX ;YCOUNT pop ax ;x2 pop cx ;cx = x1 sub ax,cx ;x2 - x1 sar ax,1 sar ax,1 ;divide by 4 jz nogo2 MOV (head+xcount),AX ;XCOUNT pop (head + picval) push cx ; cx is X start value ; push for later restoring ; dx is Y start value dotlp: push ax PUSH BX call egabyte ; +7 ;assembly graphics write CX,DX IS X,Y POP BX pop ax add cx,4 ;8 next x value DEC ax ;xcount jnz dotlp mov ax,(head+xcount) ;restore xcount pop cx ;restore xstart push cx ;save again inc dx ;next y value DEC BX ;ycount jnz dotlp pop cx ;not wanted any more jmp ext nogo1: pop ax pop ax nogo2: pop ax ext: MOV CX,(head+REGSAV) db 'endproc ' db 'DLINE ' ; ====> entry point ; ; Bresenhan's line drawing algorithm ; ;====== dline: ;draw a line from last plotted point ;====== POP DX ;picval MOV (head+PICVAL),DX POP DX ;y value MOV (head+REGSAV),CX POP CX ;x value PUSH SI ;display type is EGA PUSH DI ;these two will need to be saved call doline ; -7 POP DI POP SI MOV CX,(head+REGSAV) db 'endproc ' db 'DOLINE ' ; ====> NOT an entry point => follows endproc Doline: ; mov dx,ax ;x value ; mov cx,cx ;y value mov (head+y2),dx mov (head+x2),cx ; POP Y2 ; POP X2 MOV AX,WORD PTR (head+LASTPOINT) MOV (head+X1),AX MOV AX,WORD PTR (head+LASTPOINT+2) MOV (head+Y1),AX MOV AX,(head+Y2) MOV WORD PTR (head+LASTPOINT+2),AX MOV AX,(head+X2) MOV WORD PTR (head+LASTPOINT),AX CALL LINE ; -5 ret ; LINE: MOV AX,(head+Y2) SUB AX,(head+Y1) MOV SI,1 JGE STOREY MOV SI,-1 NEG AX STOREY: MOV (head+DELTAY),AX ; MOV AX,(head+X2) SUB AX,(head+X1) MOV DI,1 JGE STOREX MOV DI,-1 NEG AX STOREX: MOV (head+DELTAX),AX ; CMP AX,(head+DELTAY) JL CSTEEP CALL EASY ; ret ; CSTEEP: CALL STEEP FINISH: RET ; EASY: MOV AX,(head+DELTAX) SHR AX,1 MOV (head+HALFX),AX MOV CX,(head+X1) MOV AX,(head+Y1) SUB BX,BX MOV DX,(head+DELTAX) MOV (head+COUNT),DX NEWDOT: PUSH AX ;y value PUSH CX ;x value ; mov ax,dx ;to line up with BIOS parameter standard CALL dodot ; POP CX POP AX ADD CX,DI ADD BX,(head+DELTAY) CMP BX,(head+HALFX) JLE DCOUNT SUB BX,(head+DELTAX) ADD AX,SI DCOUNT: DEC (head+COUNT) JGE NEWDOT RET ; STEEP: MOV AX,(head+DELTAY) SHR AX,1 MOV (head+HALFY),AX MOV CX,(head+X1) MOV AX,(head+Y1) SUB BX,BX MOV DX,(head+DELTAY) MOV (head+COUNT),DX NEWDOT2: PUSH AX ;y1 PUSH CX ;x1 ; mov ax,dx ;to line up with BIOS parameter standard CALL dodot ; POP CX POP AX ADD AX,SI ADD BX,(head+DELTAX) CMP BX,(head+HALFY) JLE DCOUNT2 SUB BX,(head+DELTAY) ADD CX,DI DCOUNT2: DEC (head+COUNT) JGE NEWDOT2 RET db 'endproc ' db 'CIRCLE ' ; ====> entry point ; *********************** ; ; This routine is based on the article page 65 of Dr. Dobbs Journal ; July 1983 - Anatomy of a Digital Vector and Curve Generator - by ; Richard Shiffman. ; ; *********************** ;====== circle: ;====== MOV (head+REGSAV),CX pop (head+PICVAL) mov cl,5 ; get more significant digits pop dx ; by shifting left by ??? sal dx,cl ; 5 chosen arbitrarily mov (head+rad),dx pop (head+yc) pop (head+xc) PUSH SI ;display type is EGA PUSH DI ;these two will need to be saved mov ax,(head+rad) ;original y = radius mov bx,0 ;original x zero mov cx,800 ;loop count push cx cirlp: mov cl,7 ; divisor for incrementing push ax ; round circle (arbitrarily chosen ; but must match 800 loop count sar ax,cl ;divide y sub bx,ax ;updated x pop ax push bx sar bx,cl ;divide x add ax,bx ;updated y pop bx mov cx,bx mov dx,ax push ax push bx mov ax,cx mov cl,5 ; undo significant digit shift left sar ax,cl ; for BOTH x and y values sar dx,cl mov cx,ax push dx ; correction mov ax,cx ; for mov bx,7 ; aspect imul bx ; ratio mov bx,6 ; idiv bx ; mov cx,ax ; pop dx ; add cx,(head+xc) ; add x value for centre js skp ; must still use signed numbers cmp cx,640 ; clip at edges of screen jnc skp ; push dx ; aspect ratio correction ; mov ax,cx ; moved to before Xc added ; mov bx,7 ; ; mul bx ; see file SMITH for ; mov bx,6 ; method of aspect correction ; div bx ; for Xc and Yc ; mov cx,ax ; ; pop dx ; add dx,(head+yc) ; add y value for centre js skp ; must use signed numbers cmp dx,15eh ; clip at bottom of screen jnc skp mov ax,dx call dodot ; skp: pop bx pop ax pop cx dec cx ; loop count push cx jnz cirlp ; round again pop cx POP DI POP SI MOV CX,(head+REGSAV) db 'endproc ' db 'EGAPARM ' ; ====> NOT an entry point => follows endproc ;****************************************************** PICVAL DW 2 ;colour value for pixel to be lit REGSAV DW 1 FORM DB 080h ;;BITMASK DB 128,64,32,16,8,4,2,1 (not used now) lastpoint dw 4 dup (?) DELTAX DW 0 DELTAY DW 0 HALFY DW 0 HALFX DW 0 COUNT DW 0 X2 DW 0 Y2 DW 0 X1 DW 0 Y1 DW 0 xcount dw 0 xc dw 0 yc dw 0 rad dw 0 ; ;****************************************************** ; db 'endfile' aa equ $ db 'NORM ' db 'EGADOT ' db 'DODOT ' db 'EGANIB ' db 'EGABYTE ' ; db 'SETBYTE ' ; db 'SETBIT ' ; db 'RSTEGA ' db 'EGABOX ' db 'DLINE ' db 'DOLINE ' db 'LINE ' ; db 'CSTEEP ' ; db 'EASY ' ; db 'STEEP ' db 'EGAPARM ' ab equ $-aa ;****************************************************** ; end of egadot routine ;****************************************************** cseg ends end start