*DECK,NP$D2N *IF,DEF,XFR IDENT NP$D2N ENTRY NP$D2N NP$D2N BSS 1 * * THIS TRANSLATION ROUTINE TAKES ONE CHARACTER AT A TIME FROM * THE DISK BUFFER AND WRITES IT'S EQUIVALENT ASCII (NETWORK 8) * INTO THE NETWORK BUFFER. * * THE PROCESS GOES ON UNTIL ONE OF THE TWO OCCURS : * - THE DISK BECOMES EMPTY * - THE NETWORK BUFFER BECOMES FULL * THEN THE ROUTINE EXITS WITH THE PROPER FLAG SET. * * ENTRY PARAMETERS : * - ADDRESS OF NETWORK FET * - ADDRESS OF DISK FET * - ADDRESS OF CONVERSION TABLE PARAMETER BLOCK * * THE STRUCTURE OF THE PARAMETER BLOCK IS THE FOLLOWING: * * +--------------------+ * WORD 0 1 *NETBUF* FULL FLAG 1 * +--------------------+ * 1 1 *DISKBUF* EMPTY FLG1 * +--------------------+ * 2 1 NCOUNT 1 * +--------------------+ * 3 1 NBYTE 1 * +--------------------+ * 4 1 DBIT 1 * +--------------------+ * 5 1 CONVERSION STATE 1 * +--------------------+ * 6 1 CONVR. TABLE ADR. 1 * +--------------------+ * 7 1 STEPSIZE ON DISK 1 * +--------------------+ * 8 1 RESERVED 1 * +--------------------+ * * WHERE - * *NETBUF FULL* IS SET TO 1 WHEN NO MORE ROOM IN NETWORK * BUFFER (NETPUT IS REQUIRED) * * *DISKBUF EMPTY* IS SET TO 1 WHEN ALL DATA USED, BUFFER * EMPTIED AND STILL SPACE AVAILABLE IN *NETBUF*. * (NO NETPUT IS DONE UNLESS E-O-R E-O-I, AND ANOTHER READ * REQUEST IS TO BE ISSUED) * * NCOUNT IS THE NUMBER OF CHARACTERS WRITTEN TO NETBUF (TO * BE USED AS TLC WHEN NETPUTTING THE MESSAGE) * * NBYTE IS NUMBER OF BITS TO LEFT-SHIFT IN ORDER TO BRING A * CHARACTER FROM A RIGHTMOST POSITION TO THE CURRENT ONE. * IT STARTS COUNTING FROM 52 (WHEN 1ST BYTE IS A COMPLETE * CHARACTER) AND COUNTS DOWN STEP 8. * * DBIT IS THE NUMBER OF BITS TO SHIFT A CHARACTER FROM IT'S * CURRENT POSITION IN *DISKBUF* TO A RIGHTMOST POSITION. * FOR DISPLAY CODE FILES - BEGIN AT 6 STEP 6 UP. * ASCII FILES - BEGIN AT 12 STEP 12 UP. * * STATE REMEMBERS A LAST SPECIAL EVENT TILL THE NEXT ENTRY. * SPECIAL EVENTS START WHEN A COLON(:) IS READ FROM DISK. * IT MAY BE A COLON BUT IT ALSO MAY BE A Z-BYTE. * WE KEEP A COUNTER OF CONSEQUTIVE (:) (IN *B3*) UNTIL : * -Z-BYTE CONDITION MET (2 OR MORE COLONS AND END-OF-WORD) * -A NON-ZERO CHARACTER IS ENCOUNTERED. * IN THE LATER CASE WE GO INTO A LOOP TO SEND THE * APPROPRIATE NUMBER OF COLONS TO THE NETWORK BUFFER,UNTIL * COUNTER GOES BACK TO ZERO. * IF AT THIS TIME THE NETWORK BUFFER BECOMES FULL, WE * REMEMBER THE REMAINING NUMBER OF REQUIRED COLONS + LAST * NON-ZERO CHARACTER READ TO SEND THEM IN NEXT ENTRY. * * ADDRESS OF CONVERSION TABLE - IS CASE OF 6-->8 OR 8-->6. * * STEP SIZE IS 6 FOR DISK DISPLAY-CODE FILES, * 12 FOR DISK ASCII FILES. * * NOTE FOR FILE TRANSFER * ---------------------- * BECAUSE THE SENDER SENDS ONLY *MSG* BLOCKS,EVERY BLOCK SHOULD * START WITH A *TBH* OF 6 OCTETS. * IT IS THE RESPONSIBILITY OF THE SENDER,PRIOR TO CALLING THIS * ROUTINE FOR THE FIRST TIME WHEN CONSTRUCTING A BLOCK, TO SET * THE FOLLOWING : * - *IN* POINTER = *OUT* POINTER = *FIRST* POINTER * - THE *TBH* IN THE FIRST 6 OCTETS (ANYTHING APPLICABLE) * - SET *NCOUNT* TO 6 * - SET *NBYTE* TO 4 * * THE PRESETTING OF REGISTERS INCLUDE : * * A1 - ADDRESS OF NET FET+1 (*IN* POINTER) * A2 - ADDRESS OF DISK FET+1 (*IN* POINTER) * A4 - POINTER TO DISK BUFFER *OUT* WORD. * A5 - POINTER TO NET BUFFER *IN* WORD. * * X4 - CURRENT (WORKING) WORD IN DISKBUF * X5 - ACCUMULATED NETBUF WORD (POINTED BY *IN*) * * B1 - 1 * B2 - ADDRESS OF FIRST ENTRY IN CONVERSION TABLE * B3 - CONVERSION STATE * B4 - DBIT * B5 - NBYTE * B6 - COUNT * * SB1 1 SA2 A1+B1 SECOND PARAMETER ADDRESS SA3 A2+B1 THIRD PARAMETER ADDRESS * * THE PARAMETERS GIVEN ARE WORDS CONTAINING THE A D D R E S S * OF THE REQUIRED PARAMETERS (FETS,PARAMETER BLOCK) * SA1 X1 GET POINTER TO THE ACTUAL ADDRESS SA2 X2 SA3 X3 SA1 X1+B1 POINT TO NFET WORD CONTAINING *IN* SA5 X1 *NETBUF* *IN* WORD SA2 X2+B1 POINT TO DFET WORD CONTAINING *IN* SA4 A2+B1 DFET WORD CONTAINING *OUT* SA4 X4 *DISKBUF* *OUT* WORD BX6 X3 SA6 PARAM SAVE ADDRESS OF PARAMETER TABLE MX6 0 SA6 X3 CLEAR FLAG OF *NETBUF* FULL SA6 X3+B1 AND FLAG OF *DISKBUF* EMPTIED SA3 A6+B1 SB6 X3 *** NCOUNT *** GOES INTO *B6* SA3 A3+B1 SB5 X3 *** NBYTE *** GOES INTO *B5* SA3 A3+B1 SB4 X3 *** DBIT *** GOES INTO *B4* SA3 A3+B1 STATE WORD SB3 X3 STATE WORD IS 48/0,6/'LAST CHAR',6/#ZEROS SA6 A3 CLEAR STATE WORD SA3 A3+B1 WORD 7 - CONVERSION TABLE ADDRESS SB2 X3 SA3 A3+B1 STEP SIZE TO GO IN DISKBUF (6 OR 12) BX6 X3 SA6 STEP SA3 A3+B1 BLOCKSIZE BX6 X3 SA6 BLKZ * * CHECK FIRST FOR ANY LEFT-OVERS FROM PREVIOUS ENTRY * MX0 -6 TO EXTRACT SIX RIGHT MOST BITS SX6 B3 BX7 X0*X6 ISOLATE THE 'LAST CHAR' INDICATOR ZR X7,BEGIN0 NO LEFT-OVER TO WRITE FROM PREVIOUS ENTRY BX7 -X0*X6 NUMBER OF ZEROS IN STATUS WORD ZR X7,LCHARNZ WRITE ONLY 'LAST CHAR' EQ LCHARPZ WRITE SOME COLONS THEN THE 'LAST CHAR' * * CHECK IF FILE ENTERED HAD NO DATA,CASE WE EXIT IMMEDIATLY. * BEGIN0 SB7 X2 *IN* ADDRESS SB7 A4-B7 *OUT* - *IN* EQ B7,B0,BEGIN3 IF FILE ENTERED AS EMPTY BEGIN BSS 0 * * AT THIS SECTION GET A CHARACTER FROM DISKBUF. * * *A4* POINTS TO *OUT* WORD AND CAN BE USED TO EXTRACT * CURRENT CHARACTER UNTIL END-OF-WORD REACHED. * * WHEN ADVANCING TO NEXT WORD IS REQUIRED, MAKE SURE OUT * DOES NOT GO BEOND *IN* POINTER. * SB7 66 LAST POSIBLE CHARACTER IN THE WORD LT B4,B7,BEGIN1 IF NOT END-OF-WORD * * PREVIOUS CYCLE USED LAST CHARACTER FROM A WORD IN *DISKBUF*. * SO, MOVE *OUT* TO NEXT WORD. * IF BECAME = *IN* THEN WE EMPTIED THE BUFFER AND WE RETURN. * BEGIN2 SA4 A4+B1 ADVANCE THE *OUT* POINTER * CHECK IF WE PASSED *LIMIT* SA3 A2+2 DFET WORD CONTAINING *LIMIT* SB7 X3 SB7 A4-B7 *OUT* - *LIMIT* NE B7,B0,NOROL IF LIMIT NOT YET REACHED SA3 A2-B1 DFET WORD CONTAINING *FIRST* SA4 X3 SET *OUT* TO BE *FIRST* NOROL SA3 STEP SB4 X3 INITILIZE DBIT TO BEGINNING OF NEXT WORD * * CHECK IF BUFFER BECAME EMPTY * SB7 X2 *IN* ADDRESS SB7 A4-B7 *OUT* - *IN* NE B7,B0,BEGIN1 IF FILE NOT YET EMPTIED. BX6 X5 GET WHATEVER AVAILABLE ON WORKING OUT REG SA6 A5 WRITE INTO *NETBUF* PARTIAL WORD BEGIN3 SA3 PARAM SX6 1 FLAG TO INDICATE DISKBUF EMPTIED. SA6 X3+B1 SET FLAG IN WORD 1 OF PARAMETER TABLE EQ EXITN BEGIN1 BSS 0 * * *X4* HAS THE CURRENT WORKING WORD * *B4* HAS NUMBER OF BITS TO SHIFT TO GET CHAR TO RIGHT SIDE * LX7 X4,B4 CHARACTER IN RIGHTMOST BITS SA3 STEP SX3 X3-6 ZR X3,SIX IF DISPLAY CODE CONVERSION (STEP = 6) TWELVE BSS 0 * * WE HAVE AN ASCII DISK DATA (8 BITS IN TWELVE) * WE USE THE RIGHTMOST 8 BITS FOR TRANSMITION. * ONLY EXCEPTION IS *NULL* CHARACTER, WHERE BIT 11 IS SET. * (4000B ---> 0000B) * SB4 B4+12 GET READY FOR NEXT CHARACTER MX0 -12 BX7 -X0*X7 EXTRUCT 12 RIGHTMOST BITS ZR X7,ZBYTE12 * ZERO OUT * MX0 -11 BX7 -X0*X7 *THE 12TH BIT OF 4000* EQ WRITEN ZBYTE12 BSS 0 * * ZERO BYTE. WE RIGHT ONE *US* AND GO TO NEXT WORD, BECAUSE * ALL OTHER BYTES MUST BE Z-BYTES ALSO (NULL HAS BIT 11 SET) * SB4 72 SIGNAL END-OF-LINE SX7 037B ASCII *US* (UNIT SEPERATOR) EQ WRITEN SIX SB4 B4+6 GET READY FOR NEXT CHARACTER MX0 -6 BX7 -X0*X7 RIGHTMOST DISPLAY CHARACTER SA3 X7+B2 CONVERTION TABLE ENTRY WITH INDEX=ORDINAL MX0 12 BX6 X0*X3 FUNCTION GOES INTO X6 MX0 52 BX7 -X0*X3 ASCII VALUE OF CONVERTED CHARACTER NZ X6,ZRBYT6 IF ZERO-BYTE TERMINATOR REGCHAR BSS 0 * * WHEN A CHARACTER IS NON ZERO , WE CHECK IF WE ALREADY HAVE * SOME ZEROS (NOT AT WORD BOUNDARY), WHICH MEANS THAT WE HAVE * TO TREAT THEM AS COLONS. (64 CHAR SET) * * WE SAVE THE FIRST NON-ZERO CHARACTER AFTER A ZERO SEQUENCE, * IN CASE WE DO NOT HAVE ENOUGH SPACE IN THE NETWORK BUFFER FOR * ALL CHARACTERS (COLONS AND PRESENT) * IN THIS CASE, WE CONTINUE WRITING IN THE NEXT ENTRY. * EQ B3,B0,WRITEN IF NO OUTSTANDING ZEROS ZLOOP SX3 B3 MX0 -6 BX6 -X0*X3 GET NO OF ZEROS FROM RIGHTMOST BITS NZ X6,PZEROS IF NUMBER OF ZEROS NOT EQUAL 0 * WE ONLY HAVE THE 'LAST CHAR' LEFT TO WRITE LCHARNZ SX3 B3 SB3 B0 CLEAR INDICATOR BX7 X3 AX7 6 'LAST CHAR' TO RIGHTMOST POSITION EQ WRITEN GO WRITE IT PZEROS BSS 0 * * WE STILL HAVE SOME ZEROS WE SHOULD GENERATE COLONS AGAINST. * IF THE 'LAST CHAR' STILL ZERO, IT MEANS THE CURRENT SHOULD * BECOME THE 'LAST CHAR' AND BE INSERTED TO *B3* * BX6 X3 AX6 6 'LAST CHAR' TO RIGHTMOST 6 BITS NZ X6,LCHARPZ IF 'LAST CHAR' ALREADY IN LX7 6 MOVE CURRENT CHAR TO 'LAST CHAR' POSITION BX3 X3+X7 SB3 X3 INSERT NEW 'LAST CHAR' INTO THE STATUS. LCHARPZ BSS 0 * * WE HAVE BOTH THE 'LAST CHAR' AND SOME COLONS TO WRITE OUT. * SO WE SEND A COLON , DECREMENT COUNTER AND LOOP UNTIL DONE. * SB3 B3-B1 SX7 072B ASCII COLON EQ WRITEN ZRBYT6 BSS 0 * * INCREMENT NUMBER OF ZEROS. * IF TWO OR MORE AND END-OF-WORD IT IS AN END-OF-LINE (*US*) * SB3 B3+B1 INCREMENT NUMBER OF ZEROS SB7 66 LT B4,B7,BEGIN1 IF NOT LAST CHAR IN WORD EQ B3,B1,BEGIN2 ONLY 1 ZERO BYTE AT END-OF-WORD * TWO OR MORE ZERO BYTES AT THE END OF A WORD SB3 B0 CLEAR STATUS WORD SX7 037B ASCII *US* EQ WRITEN GO WRITE IT WRITEN BSS 0 * * WE COME TO THIS SECTION TO WRITE A CHARACTER IN *NETBUF*. * THE CHARACTER IS RIGHT JUSTIFIED IN *X7* * AFTER WRITING THE CHARACTER WE TRY TO GO TO THE NEXT CHAR * POSITION IN *NETBUF*. * IF BUFFER FULL SET FLAG AND EXIT. * ELSE, GO GET NEXT CHAR (USUALLY FROM BEGIN UNLESS B3 IS NOT * ZERO WHERE WE LOOP TO ZLLOP FOR NEXT COLON) * * *B5* INDICATES THE SHIFT REQUIRED TO GET CHARACTER TO PLACE. * NEGATIVE *B5* MEANS CHARACTER SHOULD BE SPLIT BETWEEN TWO * WORDS (THIS HAPPENS ONLY WHEN NEXT WORD IS GUARANTEED) * SB6 B6+B1 INCREMENT THE *NCOUNT* LT B5,B0,WRITE1 IF IT IS A SPLIT CHARACTER EQ WRITE2 FOR NON-SPLIT CHARS. WRITE1 BX6 X7 AX6 4 FOUR LEFT BITS OF CHARACTER BX6 X5+X6 INSERT IT INTO WORKING REGISTER *X5* SA6 A5 AND WRITE THE WHOLE WORD TO *NETBUF* SA5 A5+B1 ADVANCE TO NEXT WORD FOR 2ND HALF MX0 -4 BX5 -X0*X7 REMAINING 4 BITS AT RIGHTMOST SIDE LX5 56 MOVE TO LEFT SIDE SB5 48 POSITION NEXT CHARACTER (HALF CHAR SHIFT) EQ ENDW WRITE2 LX7 B5 MOVE CHAR TO CURRENT POSITION IN *NETBUF* BX5 X5+X7 AND INSERT INTO WORKING REGISTER *X5* NE B5,B0,WRITE3 IF NOT LAST BYTE IN WORD BX6 X5 SA6 A5 WRITE OUT THE FULLY COMPOSED WORD WRITE3 SB5 B5-8 LT B5,B0,WRITE4 IF NEED TO MOVE TO NEXT WORD EQ ENDW WRITE4 BSS 0 * * WE ENTER HERE IF CHAR WRITTEN IS LAST(COMPLETE) IN THE WORD. * *B5* CAN HAVE THE FOLLOWING VALUES : * -4 : HALF CHARACTER STILL LEFT AT WORD TO BE FILLED. * -8 : LAST WORD IS EXACTLLY FILLED UP * * IF WE CAN MOVE TO NEXT WORD - * IF *B5* = -8 WE MOVE TO NEXT WORD AND CHANGE *B5* = 52 * IF NOT - * SET THE *NETWORK FULL* FLAG * IF *B5* = -4 FLUSH THE LAST UNCOMPLETED WORD FROM *X5* * SA3 A1+2 NFET WORD CONTAINING *LIMIT* SB7 X3-1 *LIMIT-1* ADDRESS SB7 A5-B7 *(IN+1) - LIMIT* NE B7,B0,WRITE5 IF *LIMIT* NOT REACHED * LIMIT REACHED,BUFFER FILLED. SB5 B5+4 NE B5,B0,WRITE6 IF LAST WORD WAS COMPLETELY COMPOSED BX6 X5 SA6 A5 WRITE LAST WORD (4 BITS MISSING AT END) WRITE6 SA3 PARAM SX6 1 FLAG TO SIGNAL *NETBUF FULL* SA6 X3 STORE IN PARAMETER BLOCK (WORD 0) EQ EXITN WRITE5 SB7 -4 EQ B5,B7,ENDW IF STILL HALF CHAR AVAILABLE SA5 A5+B1 ADVANCE TO NEXT WORD MX5 0 PRESET FOR NEXT DATA COLLECTION SB5 52 POSITION OF NEXT CHAR AT THE BEGINNING ENDW BSS 0 * * THE WRITE IS COMPLETED. GET NEXT CHARACTER TO WRITE OUT. * IF *B3* = 0 THEN GET IT FROM *DISKBUF* (BEGIN) * ELSE WE STILL HAVE SOME OUTSTANDING COLONS, LOOP BACK * TO ZLLOP UNTILL ALL EXHASTED. * SA3 BLKZ SB7 X3 NE B6,B7,AGAIN BX6 X5 SA6 A5 WRITE LAST WORD (4 BITS MISSING AT END) WRITE8 SA3 PARAM SX6 1 FLAG TO SIGNAL *NETBUF FULL* SA6 X3 STORE IN PARAMETER BLOCK (WORD 0) EQ EXITN AGAIN EQ B3,B0,BEGIN EQ ZLOOP EXITN BSS 0 * * WHEN WE ARRIVE HERE ONE OF THE FLAGS IS SET * (*NETBUF FULL* OR *DISKBUF EMPTY* ) * ALL WE NEED MORE TO DO IS STORE ALL VARIABLES IN TABLES FOR * NEXT ENTRY. * SA3 PARAM SX6 B6 SA6 X3+2 SAVE *NCOUNT* (WORD 3 OF PARAM TABLE) SX6 B5 SA6 A6+B1 SAVE *NBYTE* (WORD 4 OF PARAM TABLE) SX6 B4 SA6 A6+B1 SAVE *DBIT* (WORD 5 OF PARAM TABLE) SX6 B3 SA6 A6+B1 SAVE STATE OF TRANSFER * SAVE *A4* (*OUT* POINTER OF DISKBUF) BACK INTO DFET MX0 42 SA2 A2+B1 POINT TO WORD CONTAINING *OUT* POINTER BX2 X0*X2 CLEAR THE ADDRESS FIELD MX3 0 SX3 A4 THE CORRECT VALUE OF *OUT* ADDRESS BX7 X2+X3 INSERT IT SA7 A2 AND WRITE BACK THE DFET WORD * SAVE *A5* (*IN* POINTER OF NETBUF) BACK IN THE NFET SA3 A1 NFET WORD CONTAINING *IN* BX3 X0*X3 MASK OUT OLD ADDRESS MX2 0 SX2 A5 GET NEW ADDRESS TO BE USED BX6 X2+X3 INSERT NEW ADDRESS SA6 A3 WRITE BACK TO NFET EQ NP$D2N PARAM BSSZ 1 STEP BSSZ 1 BLKZ BSSZ 1 END *ENDIF