; 8 July 88 -- MFB cseg segment byte assume cs:cseg,ds:cseg,es:cseg org 100h head = (8E40h-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. ; ; 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 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 ; 10h ; to 10 INT 10H jmp nxt ; MOV AH,0BH ;set palette ; MOV BH,1 ; palette combination (ie not background) ; MOV BL,1 ;palette 1 ; INT 10H 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 10 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 ; 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) ; pop dx ; pop cx ; 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: ;; POP DX ;picval ;; MOV (head+PICVAL),DX ;; POP DX ;y value ;; MOV (head+REGSAV),CX ;; POP CX ;x value PUSH SI ;display type is CGA PUSH DI ;these two will need to be saved ;; mov ax,dx ;to line up with BIOS parameter standard sar ax,1 sar dx,1 ;; MOV DI,AX ;copy of AX ===> not needed <=== MOV SI,CX ;and 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 ;; MOV dx,DI ;get back y 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 ;; MOV CX,(head+REGSAV) 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 ; 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 ;======= 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 ; ; Bresnihan'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 ; +40 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 ; +40 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 ;====== circle: ;====== MOV (head+REGSAV),CX pop (head+PICVAL) mov cl,5 pop dx sal dx,cl 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 push ax 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 sar ax,cl sar dx,cl mov cx,ax push dx mov ax,cx mov bx,7 imul bx mov bx,6 idiv bx mov cx,ax pop dx add cx,(head+xc) js skp cmp cx,640 ;540 jnc skp ; push dx ; mov ax,cx ; mov bx,7 ; mul bx ; mov bx,6 ; div bx ; mov cx,ax ; pop dx add dx,(head+yc) js skp cmp dx,15eh jnc skp mov ax,dx call dodot ; -6 skp: pop bx pop ax pop cx dec cx push cx jnz cirlp 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