*DECK,NP$N2D
*IF,DEF,XFR
IDENT NP$N2D
ENTRY NP$N2D
NP$N2D BSS 1
*
* THIS TRANSLATION ROUTINE TAKES ONE CHARACTER AT A TIME
* FROM THE NETWORK BUFFER, AND CONVERTS IT TO DISPLAY CODE
* IN THE DISK BUFFER.
*
* ENTRY PARAMETERS :
* - ADDRESS OF NETWORK FET
* - ADDRESS OF DISK BUFFER FET
* - ADDRESS OF CONVERTION TABLE PARAMETER BLOCK.
*
* THE STRUCTURE OF THE PARAMETER BLOCK IS :
* +------------------+
* 1 1 NBUF EMPTY FLAG 1
* + -----------------+
* 2 1 DISKBUF FULL FLAG1
* +------------------+
* 3 1 NCOUNT 1 NO. OF REMAINING CHARS. IN NET BUFFER
* +------------------+
* 4 1 NBYTE 1
* +------------------+
* 5 1 DBIT 1
* +------------------+
* 6 1 STATE OF CONVER. 1
* +------------------+
* 7 1 CONVER. TBL ADDR.1
* +------------------+
* 8 1 STEPSIZE (6/12) 1
* +------------------+
*
* NBYTE - NUMBER OF BITS TO SHIFT CURRENT NETWORK WORD TO GET
* CURRENT CHARACTER AT RIGHT MOST LOCATION.
* COUNTS FROM 8 (12 IF WORD BEGINS WITH HALF CHARACTER)
* STEP 8 UNTIL 64 (60)
* DBIT - NUMBER OF BITS TO SHIFT A CHARACTER FROM RIGHTMOST
* LOCATION TO CURRENT REQUIRED IN DISKBUF.
* FOR DISPLAY CODE FILES : STARTS WITH 54 STEP -6 UNTIL 0
* DISK ASCII FILES : STARTS WITH 48 STEP -12 TILL 0
* STATE - 0 = ALL DONE IN PREVIOUS ENTRY.
* 1 = ZERO WORD REQUIRED
* 2 = LAST CHARACTER WRITTEN WAS (:) (SO THAT IF A *US*
* ARRIVES WE FIRST WRITE A BLANK, THAN A Z-BYTE)
*
*
* THE PRESETTING INCLUDES :
*
* A1 - ADDRESS OF NET FET+1 (*IN* POINTER)
* A2 - ADDRESS OF DISK FET+1 (*IN* POINTER)
* A4 - POINTER TO DISK BUFFER *IN* WORD.
* A5 - POINTER TO NET BUFFER *OUT* WORD.
*
* X4 - ACCUMULATING THE WORD TO BE WRITTEN TO DISKBUF
* X5 - CURRENT NETBUF WORD POINTED BY *OUT* (WORKING WORD)
*
* B1 - 1
* B2 - ADDRESS OF FIRST ENTRY IN CONVERSION TABLE
* B3 - STATE OF CONVERSION
* B4 - DBIT
* B5 - NBYTE
* B6 - COUNT
*
SB1 1
SA2 A1+B1
SA3 A2+B1
*
* THE PARAMETERS PASSED ARE WORDS CONTAINING THE A D D R E S S
* OF THE REQUIRED PARAMETERS (FETS,PARAMETER-BLOCK)
*
SA1 X1 GET POINTER TO ACTUAL PARAMETER
SA2 X2
SA3 X3
SA1 X1+B1 POINT TO NFET WORD CONTAINING *IN*
SA5 A1+B1 NFET WORD CONTAINING *OUT*
SA5 X5 ADDRESS OF *OUT* OURD IN NETBUF
SA2 X2+B1 POINT TO DFET WORD CONTAINING *IN*
SA4 X2 ADDRESS OF *IN* WORD OF DISK BUF
BX6 X3 SAVE PARAM TABLE ADDRESS
SA6 PARAM
MX6 0
SA6 X3 SET TO 'NETBUF AVAILABLE' INITIAL STATE
SA3 X3+B1 GET THE 'DISKFULL' INDICATOR
SA6 A3 SET TO 'DISK AVAILABLE' INITIAL STATE
SA3 A3+B1 WORD NUMBER 3 IN TABLE
SB6 X3 NCOUNT
SA3 A3+B1 WORD NUMBER 4 IN TABLE
SB5 X3 NBYTE
SA3 A3+B1
SB4 X3 DBIT (WORD 5 )
SA3 A3+B1 STATE INTO X3 FROM WORD 6
SB3 X3 B3=1 IS Z-WORD REQUIRED
* B3=2 IS LAST CHAR IN NETBUF WAS :
*
SA6 A3 RESET THE STATE IN PARAMETER BLOCK
SA3 A3+B1 WORD 7 - CONVERSION TABLE ADDRESS
SB2 X3
SA3 A3+B1 WORD 8 = STEP SIZE IN DISKBUF (6 OR 12)
BX6 X3
SA6 STEP
* COMPARE *OUT* AND *FIRST* TO SEE IF IT IS FIRST TIME ENTRY
SA3 A1-B1 POINT AT FET WORD CONTAINING *FIRST*
SB7 X3 *FIRST* ADDRESS IN B7
SB7 A5-B7 *NETBUF *OUT* - *FIRST*
NE B0,B7,READBLK0
*
* YES,IT IS FIRST TIME ENTRY. FIRST BLOCK HAS A TBH(6 OCTETS)
*
MX0 48
BX5 -X0*X5
SB6 X5 NUMBER OF CHARS FROM ABH
SB6 B6-6 DECREMENT THE NBH SIZE
SB5 56
SA5 A5+B1 MOVE *OUT* TO FIRST WORD OF DATA
READBLK0 BSS 0
*******
*
* CHECK IF WE STILL HAVE ROOM IN *DISKBUF* SO THAT WE CAN GO
* ON WITH THE PROCESS.
* 1. CHECK IF *B4* SHOWS NEW CHARACTER IN WORD.
* 2. CHECK IF *IN+1* = *OUT*.
*
* IF B O T H CONDITIONS OCCUR THAN WE USED ALL DISK SPACE WE
* COULD, WE FLAG THE *DISKFULL* AND QUIT.
********
SX0 A4+B1 *IN+1* (X0)
SA3 A2+B1 POINT TO DFET CONTAINING *OUT* POINTER
MX6 42
BX0 -X6*X0
BX7 -X6*X3 ADDRESS OF DISKBUF *OUT* WORD (X7)
SA3 A3+B1 POINT TO DFET CONTAINING *LIMIT* POINTER
BX3 -X6*X3 ADDRESS OF DISKBUF *LIMIT* POINTER (X3)
BX3 X0-X3 DISKBUF *IN+1* - *LIMIT*
NZ X3,ENDW2 SKIP THE FOLLOWING IF *IN+1*.NE.*LIMIT*
SA3 A2-B1 POINT TO DFET WORD CONTAINING *FIRST*
BX0 -X6*X3 ADDRESS OF *FIRST* REPLACES *IN+1*
ENDW2 BX6 X0-X7 CHECK IF *IN+1* = *OUT*
* NEW *IN+1* ADDRESS NOW IN X0
BX7 X0
SA7 NEXTIN SAVE FOR NEXT WORD ADVANCE
SA3 STEP
SB7 X3
SB7 B7-60 SETTING FOR FIRST CHARACTER IN DISK WRITE
SB7 B0-B7
NE B4,B7,ENTER1 IF NOT 1ST CHARACTER OF A WORD
NZ X6,ENTER1 IF *IN+1* .NE. *OUT*
* DISK FULL, SO WE CAN NOT GO TO NEXT WORD FOR WRITE
DISKFUL SX6 1
SA3 PARAM
SA6 X3+B1 SET FLAG OF *DISK BUFFER FULL* (WORD 2)
MX6 0
SA6 A4 CLEAN WORD WE HAD NO CHANCE TO WRITE
EQ NEXIT
*
**********
*
* IF COUNT=0 READ NEXT BLOCK (OR RETURN IF LAST BLOCK)
*
ENTER1 BSS 0
*
* CHECK FOR SPECIAL ENTRIES :
* B3 = 1 - A ZERO WORD IS REQUIRED IN *DISKBUF*
* B3 = 2 - LAST CHARACTER IN *DISKBUF* WAS A COLON (:)
*
EQ B3,B1,ZRBYT1 TO WRITE A ZERO WORD
READBLK NE B6,B0,NEXT
SB7 X1 NETBUF *IN* ADDRESS
SX6 A5-B7 NETBUF *OUT* - *IN*
NZ X6,NEXT2
* *IN* = *OUT* - NETWORK BUFFER EMPTIED.
SA3 PARAM
SX6 1 SET FLAG 'NETWORK BUFFER EMPTY'
SA6 X3 ADDRESS ON FLAG LOCATION
BX7 X4
SA7 A4 FLUSH OUT LAST CHARACTERS ACCUMULATED
EQ NEXIT
* ANOTHER BLOCK EXISTS IN NETBUF (BLK OR MSG)
NEXT2 SA5 A5+B1 ADVANCE THE POINTER TO NETBUF *OUT* WORD
MX0 48
BX5 -X0*X5 EXTRAXT TLC FROM BIT 48 THR 59
SB6 X5 GET COUNT FROM TLC OF ABH
SA5 A5+B1 POINT TO FIRST WORD OF DATA AREA
SB5 8 SET TO 1ST CHARACTER IN WORD
*
***********
* GET THE NEXT CHARACTER TO BE TRANSLATED
NEXT SB7 64
NE B5,B7,REGBYTE IF NBYTE.NE.64 GO TO REGBYTE
*
* WE HAVE A BYTE SPLIT BETWEEN TWO WORDS (NBYTE = 64)
*
MX0 56
BX3 -X0*X5 SAVE RIGHTMOST 4 BITS (BIT 7 FORCED TO 0)
LX3 4 AND PUT THEM IN BITS 4-7
SA5 A5+B1 ADVANCE TO NEXT WORD FOR 2ND HALF
*
* NOW COMBINE WITH PREVIOUS 4 BITS
*
MX0 4
BX6 X5*X0
LX6 4 TO MOVE THEM FROM LEFT TO RIGHT
BX7 X3+X6 COMBINE AND REMEMBER IN *X7*
SB5 12 START COUNTING FROM 12 (NOT 8)
EQ TBLENT
*
* REGULAR ASCII BYTE (ALL IN THE SAME WORD)
*
REGBYTE LX3 B5,X5 GET ASCII CHAR TO RIGHTMOST BYTE
MX0 52 KEEP LEFTMOST PARITY BIT
BX7 -X0*X3 CHAR MASKED AT RIGHTMOST BITS OF *X7*
SB5 B5+8 GET READY FOR NEXT BYTE
*
* IF NBYTE BECAME 68 RESET AND MOVE TO NEXT WORD OF NETBUF
*
SB7 B5-68
LT B7,B0,TBLENT
*****
* WE ARE AT THE LAST CHARACTER IN THE WORD
*
SB7 X1 NETBUF *IN* WORD ADDRESS
SB7 A5-B7 NETBUF *OUT* - *IN*
EQ B7,B0,TBLENT GO TO TBLENT IF NETBUF EMPTY(IN=OUT)
*
* NOT END OF BUFFER YET. GET NEXT WORD AND POSITION READY
*
SA5 A5+B1
SB5 8
*****
* GET CHAR USING OFFSET OF CHARACTER STORED IN X7 PREVIOUSLY
*
TBLENT SB6 B6-B1 DECREMENT CHARACTER COUNTER
SA3 STEP
SX3 X3-6
ZR X3,TBLENT1 8/8 TO DISPLAY CODE (6) CONV.
*
* ASCII (12 BITS) CONVERSION.
*
SB7 X7-37B 37B IS ASCII *UNIT SEPARATOR*
EQ B0,B7,ZRBYT
*
* ONLY SPECIAL CASING IS NULL THAT GOES FROM 0000 TO 4000
*
NZ X7,NORM
MX7 1
LX7 12 X7 = 4000B
EQ NORM
TBLENT1 SA3 X7+B2 CONV. TBL. ADDR. + THE OFFSET FOUND
MX0 12
BX6 X3*X0 FUNCTION INTO X6
MX0 48
BX7 -X0*X3 VALUE OF DISPLAY CODE/ASCII12 INTO X7
NG X6,SPECIAL
SB3 B0 CLEAR POSSIBLE 'COLON READ' INDICATOR
NORM LX7 B4 SHIFT VALUE TO CURRENT LOCATION
BX4 X7+X4 ADD NEW CHARACTER
EQ B0,B4,ENDW
* NOT E-O-L YET. JUST GET NEXT LOCATION
SA3 STEP
SB7 X3 STEP 6 OR 12 DEPENDING ON TRANSLATION MOD
SB4 B4-B7
EQ READBLK FOR NEXT CHARACTER FROM NETWORK
ENDW BX7 X4
SA7 A4 STORE WORD JUST COMPOSED INTO DISKBUF
SA4 NEXTIN
SA4 X4 ADVANCE FOR NEXT WORD TO USE
MX4 0 PRESET FOR NEXT ACCUMULATION
*
* SET *B4* TO THE FIRST CHARACTER SHIFT AMOUNT FOR NEXT WORD
*
SA3 STEP
SB7 X3
SB4 60
SB4 B4-B7 STEP 6 OR 12 DEPENDING ON TRANSLATION MOD
EQ READBLK0
*
* SPECIAL CASES SECTION
*
SPECIAL MX0 1
BX3 -X0*X6 CLEAR LEFTMOST BIT OF FUNCTION (X'800')
NZ X3,SP1
* CODE = '800' JUST DELETE CHARACTER
SB3 B0 CLEAR THE 'COLON READ' INDICATOR
EQ READBLK GET NEXT CHARACTER
SP1 LX3 11 X'001'
BX3 -X0*X3
NZ X3,COLON ONLY POSSIBILITY LEFT (X'803')
*---------- CODE IS X'801' = Z-BYTE -----------------
ZRBYT SB7 B1+B1
NE B3,B7,ZRBYT1 IF LAST CHAR WAS NOT COLON
SX7 55B LAST CHAR COLON. SUFFIX A BLANK CHAR
LX7 B4 MOVE TO CURRENT REQUESTED LOCATION
BX4 X7+X4 INSERT INTO WORKING OUTPUT REGISTER.
SA3 STEP
SB7 X3 STEP 6 OR 12 DEPENDING ON TRANSLATION MOD
SB4 B4-B7 GET READY FOR NEXT LOCATION
ZRBYT1 SB3 B0 CLEAR POSSIBLE 'LAST CHAR WAS COLON'
SA3 STEP
SX3 X3-12 TO CHECK IF ASCII MOD
ZR X3,ENDW ONLY ONE ASCII CHAR WILL DO AS A Z-BYTE
GE B4,B1,ENDW OR AT LEAST 2 DISPLAY CODE
SB3 1 SIGNAL ANOTHER ZERO WORD IS REQUIRED
EQ ENDW
COLON SB3 B1+B1 RECORD INTERNALLY THE EVENT
EQ NORM GO INSERT CHARACTER
*
* STORE VARIABLES IN TABLES AND RETURN
*
NEXIT SA3 PARAM RESERVE VARIABLES IN TABLE
SX6 B6
SA6 X3+2 SAVE NCOUNT ( WORD 3 OF PARAM TABLE)
SX6 B5
SA6 A6+B1 SAVE NBYTE (IN WORD 4)
SX6 B4
SA6 A6+B1 SAVE DBIT (IN WORD 5)
SX6 B3 RECORD THE STATE OF DISKBUF
SA6 A6+B1 STORE IN WORD 6 OF PARAMETER BLOCK
*
* SAVE A4 (*IN* POINTER OF DISKBUF) BACK IN FET
*
NEXIT2 MX0 42
SA2 A2 ADDRESS OF DFET WORD WITH *IN* POINTER
BX2 X2*X0 MASK OUT OLD POINTER
MX3 0
SX3 A4 NEW *IN* ADDRESS
BX7 X2+X3 INSERT ADDRESS TO WORD
SA7 A2 WRITE BACK
*
* SAVE A5 (*OUT* POINTER OF NETBUF) BACK INTO FET
*
SA3 A1+B1 NFET WORD CONTAINING *OUT*
BX3 X3*X0 MASK OUT OLD ADDRESS
MX2 0
SX2 A5 NEW ADDRESS
BX6 X2+X3 INSERT NEW ADDRESS TO WORD
SA6 A3 WRITE BACK
EQ NP$N2D
PARAM BSSZ 1
STEP BSSZ 1
NEXTIN BSSZ 1
END
*ENDIF