N! EIX;BACKGROUND PRINTERX;by(X;A. Giambra2X;<ADDR";;START ADDRESSFDDEVIC;;DEVICEPDUNIT;;DEVICEZDCOMND;;I/O COMMANDdDSTATS;;DEVICEnDBUFLO;;BUFFER ADDRESSxDTIMLO;;BUFFER ADDRESSDBYTLO;;BUFFER ADDRESSDBYTHI ;;BUFFER ADDRESSDAUX1 ;;SECTOR NUMBERDSKINVS;;OS I/O ROUTINECIOVV;;OS I/O ROUTINENOTE&;;NOTE SECTORREAD;;OPEN FOR READPUTCHAR ;;PUT CHARACTERS READCOMR;;READ SECTOR CMNDSTATUS ;;STATUS COMMANDOPEN;;OPEN DEVICECLOSE ;;CLOSE DEVICEOPENERROR;;CHANNEL OPENNOTFOUND;;WORK FLAGIOCB0;;CHANNEL 0IOCB1;;CHANNEL 1"HATABS;;HANDLER TABLE,ICCOMB;;I/O COMMAND6ICSTAC;;I/O STATUS@ICBALD;;BUFFER ADDRESSJICBLLH;;BUFFER LENGTHTICAX1J;;AUXILIARY BYTE^ICAX3L;;AUXILIARY BYTEhDOSVEC ;;DUP SYS ADDRESSrDOSINI ;;DOS INIT| PBPNT PBUFSZPRNBUF PTIMOTLOMEM;;LOW MEMORYWARMSTARTtXITVBVb;;VBI EXITSETVB\;;SET VBI ROUTINEVVBLKD$;;VBI VECTOR ADDRCR;;CARRIAGE RETURNCOMMAND;;TEMP STORAGESECTOR;;SECTOR COUNTINDEX;;WORK INDEXRETRY;;RETRY FLAGFLAG;;WROK FLAGBUSY;;BUSY FLAG%X;OFFSET TO RESIDENT PRINT HANDLER&X;RETRY LOGIC0PRINTOFF:X;DX;HANDLER TABLENX;X ADDRb OPENITl CLOSEITv RETURN WRITE RETURN RETURN !RETURNDOS  DUPSAV  VBISAV  TIMER X;$X;THE OPEN ROUTINE SUBSTITUES THE !X;PRINT.SPL FILE NAME INTO THEX;IOCB, THEN CALLS THE DISK X;OPEN ROUTINE*X;4 OPENIT>QSECTOR;;PRINT.SPL INUSE?HFOPEN1;;TEST OTHER BYTER INUSE\A;;SAVE X REGISTERf5p$>IOCB0;;CHANNEL 0-EDITORzQ>PUTCHAR;;WRITE CHARS PICCOM9Q>4MSG;;IN USE MESSAGE PICBAL9 Q>5MSGPICBAL9Q>PICBLL9;;MESSAGE LENGTHQ>PICBLL9 CIOV;;WRITE IT7>;;RESTORE X REG%>OPENERRORC;;GIVE ERROR MSGPICSTA9;;TO BASIC:$ OPEN1.QSECTOR8 HINUSEBQ>4DISKNAMELPICBAL9;;SUBSTITUTE NAMEVQ>5DISKNAME`PICBAL9jQ>;;SET COMMAND TO 1t PCOMMAND~ LOOKUP%>LOOKQHATABS8;;FIND DISK HNDLRR> D;;IS IT A 'D'?FFOUND;;YES3;;NO, SKIP 2 BYTES33ILOOK;;LOOK AGAIN FOUND3QHATABS8;;VECT TABLE ADDRPINDEX;;STORE IN INDEX 3 QHATABS8 PINDEX(%COMMAND;;OFFSET TO OPEN- X;ROUTLINE2Q@INDEX7;;TRANSFER CNTRL<5;;WITH INDIRECT JPF1P Q@INDEX7Z5;;TARGET ADDRESS_%X; IS NOW ON THE STACKdQFLAG;;RESTORE THE CHARi X; SENT BY CIOn RETURNx:;;DO INDIRECT JUMP WRITEPFLAG;;SAVE CHAR SENTX; BY CIOQ>;;USED AS OFFSET%X; TO WRITE ROUTINE PCOMMAND HLOOKUPX;!X;THE CLOSE ROUTINE CLOSES THE"X;PRINT.SPL FILE,REOPENS IT AND$X;NOTES THE FIRST SECTOR. FINALLY$X;IT CLOSES THE FILE AND FIRES UPX;THE VBI SERVICE ROUTINEX; CLOSEITQCOMMAND;;LAST CIO OP?R>;;A WRITE?HRETURN;;NO, SO EXIT"Q>;;STORE OFFSET TO'%X; TO CLOSE ROUTINE, PCOMMAND6 LOOKUP;;CALL DISK CLOSE;X; ROUTINE@$>IOCB1;;CHANNEL 1JQ>OPEN;;LOAD OPEN CMNDTPICCOM9;;STORE IN IOCB^Q>4DISKNAMEhPICBAL9;;STORE FILE NAMErQ>5DISKNAME|PICBAL9Q>READ;;OPEN INPUT PICAX19 CIOV;;CALL OS I/OQ>NOTE;;NOTE SECTOR CMND PICCOM9 CIOV;;CALL I/O ROUTINEQICAX39;;GET THE SECTOR # PSECTORQICAX39PSECTORQ>CLOSE;;CLOSE COMMAND PICCOM9 CIOV;;CLOSE THE FILEQ>;;INIT WORK AREAS PINDEX PFLAG& PRETRY0 PBUSY:Q>4WARMSTARTDPDOSVEC;;MAKE SURE CAN'TNQ>5WARMSTART;;USE DOS CMDXPDOSVECbQ>;;CALL AN IND VBIl%>4VB;;ADDR VBI ROUTINEv $>5VB SETVB;;SET VBI:OUT !XITVBVVBQBUSY;;DON'T LET VBIHOUT;;INTERRUPT ITSELFQFLAG;;TIME TO PRINT?HPRINTER;;YESPCOMMAND;;INIT WORK AREAPTIMER;;INITIALIZE TIMERQ>PDUNIT;;DRIVE 1Q>READCOM;;READ COMMAND  PDCOMNDQ>4DATA;;DATA BUFFER ADDR  PDBUFLO* Q>5DATA4PDBUFLO>QSECTOR;;LOAD SECTOR NO.H PDAUX1RQSECTOR\ PDAUX1f DSKINV;;READ A SECTORpC;;GET I/O STATUSzGOUT;;WAS IT BAD I/O?#FLAG;;SET FLAGHOUT;;EXIT PRINTER#TIMER;;INCREMENT TIMER QTIMERR>;;SLOW DOWN OUTPUTHOUTQ>;;RESET TIMER PTIMERQRETRY;;LAST I/O BAD?HTRYAGAIN;;YES,TRY AGAIN#BUSY;;SET BUSY FLAG%INDEX;;CHARACTER INDEX QDATA8;;LOAD A CHARACTER X; #X;THE FOLLOWING ROUTINE EMULATES$ X;THE OPERATING SYSTEM PRINT. X;HANDLER WRITE ROUTINE8 X;B PRINTL 5;;SAVE CHARACTERV %>W;;WRITE COMMAND` $>(;;BUFFER SIZEj Q>N;;NORMAL MODEt PDAUX1~ 'DCOMND &PBUFSZ $PBPNT 7;;GET CHARACTER PPRNBUF9;;PUT IN BUFFER 2;;INC BUFF POINTER (PBUFSZ;;= BUFFER SIZE? FBUFFUL &PBPNT;;SAVE POINTER R>;;EOL? FBLFILL;;YES, BLANK FILL %>;;GOOD STATUS !IN BLFILL Q> ;;LOAD A SPACE FILLBFPPRNBUF9 2( (PBUFSZ;;BUFFER FULL?2 HFILLBF< BUFFULF Q>;;CLEAR BUFFERP PPBPNT;;POINTERZ $>;;SET BUFF POINTERd %>n &DBUFLOx 'DBUFLO Q>@;;STORE DEVICE PDDEVIC Q> PDUNIT Q>;;DIRECTION=OUTPUT PDSTATS QPBUFSZ;;STORE BUFF SIZE PDBYTLO Q> PDBYTHI QPTIMOT;;TIMEOUT VALUE PDTIMLO  Y IN "BUSY;;BUST FLAG OFF C;;GET STATUS" IAHEAD;;GOOD I/O, #RETRY;;SET RETRY FLAG6 HJP@ AHEADJ %INDEXT 3;;INC CHAR INDEX^ )DATA;;END OF SECTOR?h ENEXTSECTOR;;YESr 'INDEX;;NO, SAVE IT| JP !OUT TRYAGAIN "RETRY;;RETRY FLAG OFF #BUSY;;SET BUSY FLAG X; RETADDR !BUFFUL;;RETRY WRITING X; THE BUFFER EXITVB  ;;PRINT HANDLER "X; CLOSE ROUTINE QVBISAV;;RESTORE VBI VECT PVVBLKD QVBISAV PVVBLKD Q>4DUPEXIT;;RESTORE X; DOSVEC PDOSVEC Q>5DUPEXIT& PDOSVEC0 HJP: NEXTSECTORD Q>;;RESET WORK AREASN PINDEXX PFLAGb QDATA};;GET NEXT SECTORl M>;;GET HIGH BYTEv PSECTOR FNEXT1 #COMMAND;;THERE IS MORE NEXT1 QDATA~;;GET LOW BYTE PSECTOR FNEXT2 #COMMAND;;THERE IS MORE NEXT2 QCOMMAND;;MORE SECTORS? FEXITVB;;NO, END VBI !OUT;;EXIT VBI DISKNAME AD:PRINT.SPLA MEMSAV  AD:MEM.SAVA MSG  AԮ̠ΠA=CR DATA;DISK DATA BUFFER*  4 DUPEXIT> $>IOCB1;;CHANNEL 1H Q>STATUS;;GET STATUS OFR PICCOM9;;MEM.SAV FILE\ Q>4MEMSAVf PICBAL9p Q>5MEMSAVz PICBAL9 CIOV )>NOTFOUND;;IS IT THERE? HJUMPDUP;;YES, GET OUT %> FINDB QHATABS8;;FIND B DEVICE R> B FFOUNDB;;FOUND IT 3 3 3 IFINDB FOUNDBQ>;;TAKE OUT OF TABL PHATABS8Q>4ADDR;;RESTORE LOMEM$PLOMEM;;TO ORIGINAL VAL. Q>5ADDR8 PLOMEMBQDOS;;RESTORE DOSINILPDOSINI;;TO ORIGINAL VALV QDOS`PDOSINIjQDUPSAV;;RESTORE DOSVECtPDOSVEC;;TO ORIGINAL VAL~QDUPSAVPDOSVEC!@DOSVEC:;;JUMP TO DUP.SYS JUMPDUP QDUPSAVPQDUPSAVP!@: RESETQ>;;RESET SECTOR NUM PSECTORPSECTORQDOS;;GET DOSINI VECT PDOSADDR;;CREATE JSR ADR QDOSPDOSADDR( DOSADDR2 ;;DOS INIT<!INITMORE;;REINIT HANDLERAX; TABLEFINITPQDOSINI;;GET DOSINI VECTZPDOS;;AND SAVE ITdQDOSINIn PDOSxQ>4RESET;;POINT DOSINI TOPDOSINI;;OUR RESET LOGIC Q>5RESETPDOSINI INITMOREQDOSVEC;;SAVE DOSVECPDUPSAV;;IN DUPSAVQDOSVECPDUPSAVQ>4DUPEXIT;;POINT DOSVECPDOSVEC;;TO DUPEXITQ>5DUPEXITPDOSVECQVVBLKD;;SAVE ORIG VBIPVBISAV;;VECTORQVVBLKDPVBISAV"Q>4FINI;;SET LOMEM TO,PLOMEM;;POINT PAST END6Q>5FINI;;OF THIS PROGRAM@ PLOMEMJ%>TSEEK^QHATABS8;;LOOK IN HANDLERcX; TABLEhFPUTIT;;FOR A FREE SPACErR> P;;IS IT THEw%X; PRINTER HANDLER?| HPUT1 GETIT;;YES, PROCESS ITPUT13;;SKIP 2 BYTES33 ISEEK PUTITQ> B;;HANDLER NAMEPHATABS8;;IN TABLE3Q>4ADDR;;STORE ADDRESS OFPHATABS8;;OUR VECT TABLE3 Q>5ADDR PHATABS8 :;;EXIT& GETIT0C;;SAVE THE Y REG:5;;ON THE STACKD3NQHATABS8;;GET VECT TABLEXPINDEX;;ADDRESSb3l QHATABS8v PINDEX%>;;OFFSET TO CLOSEX; ROUTINE,Q@INDEX7;;LOAD CLOSE ADRO>;;ADD 1 TO ITPEXITVB;;MODIFY JSR CODE3 Q@INDEX7O>PEXITVB7;;RESTORE Y INDEX?:FINI  INIT