*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
