*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