PAGE ,132 TITLE ADI INT DRIVER FOR IDS P80 AND P132 PRINTERS ; THIS PROGRAM IS A MEMORY RESIDENT UTILITY THAT ; PROVIDES AN ADI DRIVER INTERRUPT PROCESSOR FOR ; AUTOCAD VERSION 2.5 OR HIGHER TO ALLOW PLOTTING ; ON AN IDS P80 OR P132 PRINTER. ; ; BY PATRICK SWAYNE, HUG SOFTWARE ENGINEER 17-JUN-88 ; MOD 29-SEP-88 ; REMOVABLE VERSION 01-MAR-90 TRUE EQU 0FFFFH ;DEFINE TRUE FALSE EQU NOT TRUE ;AND FALSE TEST EQU FALSE ;ASSEMBLE TEST VERSION IF TRUE ADIINT EQU 7BH ;ADI INTERRUPT USED PORT EQU 0 ;PRINTER PORT TO USE (LPT1) TIMEOUT EQU 78H ;ADDRESS OF LPT TIMEOUT JMPF MACRO DB 0EAH ;DEFINE FAR JUMP ENDM CODE SEGMENT ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE ; DEFINE SOME MEMORY LOCATIONS ORG 1 PSPSEG LABEL WORD ;PROGRAM SEGMENT PREFIX SEGMENT ADDR. ORG 3 MCBSIZE LABEL WORD ;MEMORY CONTROL BLOCK SIZE ORG 2CH ENVSEG LABEL WORD ;ENVIRONMENT SEGMENT ORG 5DH FCBARG LABEL BYTE ;FCB ARGUMENT ORG 100H START: JMP SETUP ;SET UP PROGRAM EVEN SIG DB 'ADIIDS 1.1' ; DATA AREA ADIVEC DW 0,0 ;OLD ADI INT VECTOR UNFLG DB 0 ;UNLOAD FLAG OTIMOUT DB 0 ;OLD TIMEOUT NEFLG DB 0 ;NOT EMPTY FLAG LINPTR DW 0 ;LINE POINTER ; OUTPUT LINE BUFFER. THE LINE IS 8 TIMES THE LENGTH ; OF ONE LINE ABOVE, BECAUSE OF 8 DOTS PER BYTE. IF TEST OUTLINE DB 3,14+80H ;END OF LINE MARKER DB 1137 DUP (0) ENDIF ENDFLG DB 0 ;END OF PLOT FLAG ENDMSG DB 3,2,0CH ;RESET PRINTER MSG ENDMSZ EQU $-ENDMSG ; ADI INTERRUPT PROCESSOR ADIPROC:PUSH DX ;WE'LL USE THIS STI CMP AX,8001H ;START PLOT? JZ STPLOT ;YES CMP CS:ENDFLG,1 ;THIS PLOT ENDED? JNZ DOPLOT ;NO, CAN DO PLOT POP DX XOR AX,AX IRET DOPLOT: CMP AX,8002H ;END PLOT? JB DATALIN ;NO, MUST BE DATA LINE PUSH SI PUSH DI PUSH DS PUSH ES PUSH CS POP ES ;PUT ES HERE PUSH CS POP DS ;PUT DS HERE MOV ENDFLG,1 ;MARK END OF PLOT JMP PRTLIN ;PRINT THE LAST LINE STPLOT: CLD MOV CS:ENDFLG,0 ;CLEAR END FLAG PUSH DI PUSH CX PUSH ES MOV AX,CS MOV ES,AX ;PUT ES HERE MOV DI,OFFSET LINES ;POINT TO DATA MOV CX,(143*7) MOV AL,0 REP STOSB ;CLEAR INPUT BUFFER MOV AX,40H MOV ES,AX ;POINT TO BIOS RAM MOV DI,OFFSET TIMEOUT+PORT ;POINT TO TIMEOUT FOR CURRENT PORT MOV AL,ES:[DI] ;GET OLD TIMEOUT MOV CS:OTIMOUT,AL ;SAVE IT MOV BYTE PTR ES:[DI],0FFH ;SET TIMEOUT TO MAX POP ES POP CX POP DI MOV AH,2 MOV DX,PORT INT 17H ;TEST PRINTER PORT AND AH,90H CMP AH,90H ;IS PRINTER READY? JNZ PRNBAD ;NO PRCH1: MOV AX,3 ;AH = 0, AL = ETX INT 17H ;SEND ETX TO INIT PRINTER TEST AH,1 JNZ PRNBAD ;PRINTER CONKED OUT MOV BX,0 ;INDICATE MONOCHROME PRNOK: MOV AX,1 ;RETURN INIT OK POP DX IRET PRNBAD: XOR AX,AX ;RETURN INIT NO GOOD POP DX IRET ; A DATA LINE HAS BEEN SENT. STORE IT, AND IF 7 LINES ; HAVE BEEN SENT, PRINT THEM. DATALIN:PUSH SI ;SAVE SOME REGISTERS PUSH DI PUSH DS PUSH ES PUSH CS POP ES ;PUT ES HERE OR AX,AX ;EMPTY LINE? JZ EMLIN ;IF SO, SKIP IT MOV CS:NEFLG,1 ;MARK LINE NOT EMPTY CMP AX,142 ;TEST LINE SIZE JBE DATAL1 ;OK MOV AX,142 ;ELSE, TRUNCATE DATAL1: MOV DS,CX ;DATA SEGMENT TO DS MOV SI,BX ;DATA OFFSET TO SI MOV CX,AX ;COUNT TO CX MOV AX,ES:LINPTR ;GET LINE POINTER MOV BX,143 ;AND SIZE OF LINE MUL BX ;GET LINE OFFSET ADD AX,OFFSET LINES ;AX = DESTINATION ADDRESS MOV DI,AX ;RESULT TO DI CLD MOV AL,CL STOSB ;STORE COUNT REP MOVSB ;MOVE THE DATA EMLIN: PUSH CS POP DS ;PUT DS HERE MOV AX,LINPTR ;GET LINE POINTER INC AL ;ADD 1 MOV LINPTR,AX ;UPDATE POINTER CMP AL,7 ;7 LINES DONE? JZ PRTLIN ;TIME TO PRINT LINE LINDN: POP ES POP DS POP DI POP SI JMP PRNOK ;EXIT, INDICATING OK PRTLIN: MOV LINPTR,0 ;RESET LINE POINTER CMP NEFLG,0 ;IS LINE EMPTY? JZ DOPRT ;IF SO, SKIP CONVERSION ; FIND OUT WHICH LINE IS LONGEST, AND USE LENGTH FOR ; CONVERSION COUNT MOV SI,OFFSET LINES ;POINT TO LINE 1 MOV AL,[SI] ;GET COUNT THERE MOV CX,6 ;SET COUNTER FNDSIZ: ADD SI,143 ;MOVE TO NEXT LINE CMP AL,[SI] ;COMPARE SIZES JAE SIZOK ;CURRENT SIZE IS OK MOV AL,[SI] ;ELSE, GET BIGGER SIZE SIZOK: LOOP FNDSIZ MOV DH,AL ;SIZE TO DH ; DATA CONVERSION SECTION. WHAT WE HAVE TO DO IS CONVERT ; INFORMATION IN SCREEN (SCAN LINE) FORMAT (HORIZONTAL BYTES ; OF PIXELS) INTO PRINT HEAD FORMAT (VERTICAL BYTES OF DOTS). IF TEST MOV DI,OFFSET OUTLINE ;POINT TO OUTPUT LINE ELSE MOV DI,OFFSET BA.OUTLIN ;POINT TO OUTPUT LINE ENDIF MOV SI,OFFSET LINES+1 ;POINT TO LINES SAVED (LESS COUNT) MLOOP: MOV DL,8 ;8 DOTS PER BYTE BLOOP: MOV AL,0 ;CLEAR OUTPUT BYTE MOV CX,7 ;7 LINES TO PROCESS SLOOP: SHL BYTE PTR [SI],1 ;SHIFT BYTE IN A LINE RCR AL,1 ;PUT RESULT IN OUTPUT BYTE ADD SI,143 ;MOVE TO NEXT LINE LOOP SLOOP ;UNTIL 7 LINES DONE SHR AL,1 ;USE 7 LOWER BITS STOSB ;STORE RESULT SUB SI,143*7 ;MOVE BACK TO LINE 1 DEC DL ;COUNT THIS ROW OF DOTS JNZ BLOOP ;LOOP UNTIL INPUT BYTE PROCESSED INC SI ;MOVE TO NEXT BYTE DEC DH ;COUNT THIS BYTE JNZ MLOOP ;UNTIL ALL BYTES PROCESSED ; STORE ETX AND 14 (WITH HIGH BIT SET) AT THE END OF THE LINE, ; TO SIGNAL THE END OF GRAPHICS PRINTING. MOV AX,8EH*256+3 ;CRLF COMMAND, WITH HIGH BIT SET STOSW ; NOW, PRINT THE CONVERTED LINE, WHICH REPRESENTS 7 LINES OF ; DATA FROM AUTOCAD. DOPRT: MOV NEFLG,0 ;CLEAR NOT EMPTY FLAG IF TEST MOV SI,OFFSET OUTLINE ;POINT TO OUTPUT LINE + GRAPHIC CODE ELSE MOV SI,OFFSET BA.OUTLIN ;POINT TO OUTPUT LINE + GRAPHIC CODE ENDIF MOV DX,PORT ;SET PRINTER PORT PRLOOP: LODSB ;GET A BYTE CMP AL,3 ;ETX CHARACTER? JNZ NOTETX ;NO MOV AH,0 INT 17H ;ELSE, WE HAVE TO DUPLICATE IT TEST AH,1 JNZ PRTBAD MOV AL,[SI] ;GET NEXT CHARACTER CMP AL,14+80H ;END OF LINE? JZ NOTETX ;IF SO, SEND CHARACTER MOV AL,3 ;REPLACE ETX CHARACTER NOTETX: MOV AH,0 INT 17H ;PRINT IT TEST AH,1 ;TEST PRINTER JNZ PRTBAD ;IT'S BAD CMP AL,14+80H ;END? JNZ PRLOOP ;LOOP UNTIL DONE MOV DI,OFFSET LINES ;POINT TO DATA MOV CX,(143*7) MOV AX,0 REP STOSB ;CLEAR EVERYTHING IF TEST MOV DI,OFFSET OUTLINE ;POINT TO OUTPUT LINE ELSE MOV DI,OFFSET BA.OUTLIN ;POINT TO OUTPUT LINE ENDIF MOV CX,1138/2 REP STOSW IF TEST MOV WORD PTR OUTLINE,8EH*256+3 ;ALLOW NULL LINE ELSE MOV WORD PTR BA.OUTLIN,8EH*256+3 ;ALLOW NULL LINE ENDIF CMP ENDFLG,1 ;END OF PLOT? JNZ LINDNJ ;NO MOV SI,OFFSET ENDMSG ;POINT TO PRINTER RESET MSG MOV DX,PORT ;SET PRINTER PORT MOV CX,ENDMSZ ;NO. OF CHARACTERS TO PRINT PELOOP: LODSB ;GET A BYTE MOV AH,0 INT 17H ;PRINT IT TEST AH,1 ;TEST PRINTER JNZ PRTBAD ;IT'S BAD LOOP PELOOP ;LOOP UNTIL DONE MOV CL,OTIMOUT ;GET OLD TIMEOUT MOV AX,40H MOV DS,AX ;POINT TO BIOS RAM MOV SI,OFFSET TIMEOUT+PORT ;POINT TO CURRENT TIMEOUT MOV [SI],CL ;RESTORE OLD TIMEOUT LINDNJ: JMP LINDN ;LINE DONE, EXIT PRTBAD: POP ES POP DS POP DI POP SI JMP PRNBAD ;EXIT, INDICATING BAD IF NOT TEST ; INT 28H PROCESSOR. USED FOR UN-INSTALLING ADIIDS. INT28: CMP CS:UNFLG,1 ;UN-INSTALL ADIIDS? JZ UNINS ;YES JMPF INT28V DW 0,0 ;ELSE, EXIT UNINS: PUSH CS POP DS ;POINT TO THIS SEGMENT XOR AX,AX MOV ES,AX ;AND TO INT. SEGMENT MOV SI,OFFSET ADIVEC ;POINT TO ADI INT VECTOR MOV DI,ADIINT*4 ;WHERE IT GOES CLD CLI MOVSW ;RESTORE VECTOR MOVSW MOV SI,OFFSET INT28V ;POINT TO INT 28 VECTOR MOV DI,28H*4 ;WHERE IT GOES MOVSW ;RESTORE VECTOR MOVSW PUSH CS POP ES ;PUT ES HERE MOV AH,49H INT 21H ;RELEASE THIS PROGRAM'S MEMORY MOV ES,ENVSEG ;POINT TO ENVIRONMENT SEGMENT MOV AH,49H INT 21H ;RELEASE ENVIRONMENT SEGMENT STI ;ENABLE INTERRUPTS INT 20H ;EXIT ENDIF BA: ;BUFFER AREA ; INPUT LINE BUFFERS. 7 LINES ARE INPUT AT A TIME ; BECAUSE THE IDS PRINTER DRIVES 7 PINS DURING GRAPHIC ; OUTPUT. LINES LABEL BYTE ;STORE LINES HERE IF TEST DB 143*7 DUP (0) ;STORE LINES HERE IF TEST VERSION ENDIF BUFF STRUC IF TEST DB ? ELSE DB 143*7 DUP (?) ;STORE LINES HERE IF NORMAL VERSION OUTLIN DB 2 DUP (?) ;ETX,14 DB 1137 DUP (?) ENDIF ENDRES DB ? ;END OF RESIDENT CODE BUFF ENDS ; INSTALL THIS DRIVER IN MEMORY SETUP: MOV DX,OFFSET SIGNON MOV AH,9 INT 21H ;PRINT SIGN-ON CLD MOV AH,52H INT 21H ;GET MEMORY CONTROL BLOCK ADDR. MOV AX,ES:[BX-2] ;GET FIRST MCB SEGMENT MOV DS,AX ;POINT TO IT FNDLP: MOV AX,PSPSEG ;GET PSP SEGMENT MOV DX,CS CMP AX,DX ;IN THIS SEGMENT? JAE CHKFND ;IF SO, CHECK IF ADIIDS FOUND MOV ES,AX ;ELSE, PSP SEGMENT TO ES MOV SI,OFFSET SIG MOV DI,SI PUSH DS ;SAVE MCB SEGMENT PUSH CS POP DS ;PUT DS HERE MOV CX,5 ;5 WORDS IN SIGNATURE REPZ CMPSW ;IS ADIIDS HERE? JZ GOTCC ;WE FOUND ADIIDS MOV LSTSEG,ES ;SAVE PSP SEGMENT FNDNXT: POP DS ;RESTORE MCB SEGMENT MOV AX,MCBSIZE ;GET MCB SIZE INC AX ;CORRECT IT MOV BX,DS ADD AX,BX ;CALCULATE NEXT MCB SEGMENT MOV DS,AX ;POINT TO IT JMP FNDLP ;TRY AGAIN GOTCC: MOV FNDSEG,ES ;SAVE SEGMENT WHERE FOUND MOV BYTE PTR FNDFLG,1 ;MARK PROGRAM FOUND JMP FNDNXT CHKFND: PUSH CS POP DS ;FIX DS CMP BYTE PTR FNDFLG,1 ;WAS ADIIDS FOUND? JNZ NOTFND ;NO MOV ES,FNDSEG ;GET SEGMENT WHERE FOUND CMP FCBARG,'U' ;UNINSTALL? JZ DOUNIN MOV DX,OFFSET ALMSG MOV AH,9 INT 21H ;SAY "ADIIDS ALREADY IN" INT 20H DOUNIN: MOV BX,FNDSEG ;GET SEGMENT WHERE FOUND CMP BX,LSTSEG ;COMPARE WITH LAST PSP FOUND JNC UNLOK ;OK TO UNLOAD MOV DX,OFFSET NOUNMSG MOV AH,9 INT 21H ;ELSE, SAY "CAN'T UNLOAD" INT 20H UNLOK: MOV DX,OFFSET UNMSG MOV AH,9 INT 21H ;PRINT UNLOAD MESSAGE MOV ES:UNFLG,1 ;FLAG UNLOAD DESIRED INT 20H ;AND EXIT NOTFND: CMP FCBARG,'U' ;UNINSTALL? JNZ DOINS ;NO MOV DX,OFFSET NINMSG MOV AH,9 INT 21H ;ELSE, SAY "ALREADY UNLOADED" INT 20H ;AND EXIT DOINS: PUSH CS POP ES ;FIX ES PUSH DS ;SAVE DS XOR AX,AX MOV DS,AX ;DS AT 0 MOV SI,OFFSET ADIINT*4 ;POINT TO ADI INTERRUPT MOV DI,OFFSET ADIVEC ;PUT OLD VECTOR HERE PUSH SI CLI ;TURN OFF INTERRUPTS CLD MOVSW ;MOVE VECTOR MOVSW POP SI MOV WORD PTR [SI],OFFSET ADIPROC ;PUT IN MY VECTOR MOV 2[SI],CS ;AND THIS SEGMENT IF NOT TEST MOV SI,OFFSET 28H*4 ;POINT TO INT 28 VECTOR MOV DI,OFFSET INT28V PUSH SI MOVSW ;COPY INT 28 VECTOR MOVSW POP SI MOV WORD PTR [SI],OFFSET INT28 ;SET NEW ONE MOV 2[SI],CS ENDIF STI POP DS IF NOT TEST MOV DX,OFFSET INMSG MOV AH,9 INT 21H ;SAY "ADIIDS INSTALLED" MOV WORD PTR BA.OUTLIN,8EH*256+3 ;ALLOW NULL LINE MOV DX,OFFSET BA.ENDRES ;POINT TO END OF RES. CODE INT 27H ;EXIT, LEAVE PROGRAM HERE ELSE MOV AX,8001H INT 7BH ;INITIALIZE PRINTER OR AL,AL ;TEST PRINTER JNZ GOON ;GO ON WITH TEST MOV DX,OFFSET SAYBAD MOV AH,9 INT 21H INT 20H GOON: MOV AX,84 ;GET A BYTE COUNT MOV BX,OFFSET GDATA ;POINT TO GRAPHIC DATA TSTLOOP:MOV CX,DS ;USE THIS DS PUSH AX ;SAVE COUNT PUSH BX ;AND POINTER INT 7BH ;CALL DRIVER POP BX POP AX DEC AX ;MAKE NEXT LINE SHORTER JNZ TSTLOOP MOV AX,8002H INT 7BH ;SIGNAL END XOR AX,AX MOV ES,AX ;AND TO INT. SEGMENT MOV SI,OFFSET ADIVEC ;POINT TO ADI INT VECTOR MOV DI,ADIINT*4 ;WHERE IT GOES CLD MOVSW ;RESTORE VECTOR MOVSW INT 20H SAYBAD DB 13,10,'Printer reported bad.$' GDATA DB 84 DUP (0FFH) ENDIF LSTSEG DW 0 ;LAST PSP SEGMENT (SHOULD BE < PSPSEG) FNDSEG DW 0 ;SEGMENT WHERE FOUND FNDFLG DB 0 ;PROGRAM FOUND FLAG SIGNON DB 13,10,'ADI Driver for IDS P80/P132 printer, v 1.1',13,10 DB 'By Patrick Swayne, HUG Software Engineer',13,10 DB "Copyright (C) 1990 by Heath/Zenith Users' Group",13,10,10,'$' INMSG DB 'ADIIDS is now installed.',13,10 DB 'To uninstall, type ADIIDS U.',13,10,'$' ALMSG DB 'ADIIDS is already installed.',13,10,'$' UNMSG DB 'ADIIDS is now uninstalled.',13,10,'$' NOUNMSG DB "ADIIDS is not the last TSR. Can't uninstall.",13,10,'$' NINMSG DB "ADIIDS is already not installed.",13,10,'$' CODE ENDS END START