PAGE 62,132 ; INCLUDE ENVIRON.ASM INCLUDE STRUCS.ASM ; ; MAY 90 - ADD RESIDENT OPTION ; ; Oct 90 - Converted to use BPQ Host Mode ; ; THIS USES A SPECIAL HOST MODE INTERFACE ROUTINE IN THE SWITCH ; ; THE INTERFACE IS CALLED USING INT 7FH ; ; ; COMMANDS SUPPORTED ARE ; ; AH = 0 Get node/switch version number and description. On return ; AH = major version number and AL = minor version number, ; and user's buffer pointed to by ES:SI is set to the text ; string normally output by the USERS command. CX is set to the ; length of the text string. ; ; ; AH = 1 Set application mask to value in DL (or even DX if 16 ; applications are ever to be supported). ; ; Set application flags to value in CL (or CX). ; ; ; AH = 2 Send frame in ES:SI (length CX) ; ; ; AH = 3 Receive frame into buffer at ES:SI, length of frame returned ; in CX. BX returns the number of outstanding frames still to ; be received (ie. after this one) or zero if no more frames ; (ie. this is last one). ; ; ; ; AH = 4 Get stream status. Returns: ; ; CX = 0 if stream disconnected or CX = 1 if stream connected ; DX = 0 if no change of state since last read, or DX = 1 if ; the connected/disconnected state has changed since ; last read (ie. delta-stream status). ; ; AH = 5 ACK stream status change. ; ; ; AH = 6 Session control. ; ; CX = 1 connect ; CX = 2 disconnect ; CX = 3 return user to node ; ; ; AH = 7 Get buffer counts for stream. Returns: ; ; BX = number of frames queued for receive ; CX = number of un-acked frames to be sent ; DX = number of buffers left in node ; ; ; AH = 8 Port control/information. Called with a stream number ; in AL returns: ; ; AX = Radio port on which channel is connected (or zero) ; BX = L2 paclen for the radio port ; CX = L2 maxframe for the radio port ; DX = L4 window size (if L4 circuit, or zero) ; ES:DI = CALLSIGN ;AH = 9 Fetch node/application callsign & alias. AL = application ; number: ; ; 0 = node ; 1 = BBS ; 2 = HOST ; 3 = SYSOP etc. etc. ; ; Returns string with alias & callsign or application name in ; user's buffer pointed to by ES:SI length CX. For example: ; ; "WORCS:G8TIC" or "TICPMS:G8TIC-10". ; ; ;AH = 10 Unproto transmit frame. Data pointed to by ES:SI, of ; length CX, is transmitted as a HDLC frame on the radio ; port (not stream) in AL. This is needed for things like ; mailbox broadcasts, node broadcasts etc. ; ; XX SEGMENT AT 0 db 16 dup (0) NEIGHBOURS DW 0 ROUTES_LEN DW 0 ; LENGTH MAXNEIGHBOURS DW 0 ; MAX ADJACENT NODES DESTS DW 0 ; NODE LIST DESTS_LEN DW 0 MAXNODES DW 0 ; MAX NODES IN SYSTEM LINKS DW 0 ; L2 LINK TABLE MAXLINKS DW 0 ; MAX LEVEL 2 LINKS (UP,DOWN AND INTERNODE) L4TABLE DW 0 MAXCIRCUITS DW 0 ; NUMBER OF L4 CIRCUITS PORTTABLE DW 0 NUMBEROFPORTS DW 0 TNCTABLE DW 0 NUMBEROFSTREAMS DW 0 ENDDESTLIST DW 0 ; NODE LIST+1 ; XX ENDS CR EQU 0DH LF EQU 0AH CODE SEGMENT PUBLIC 'CODE' ASSUME CS:CODE,DS:CODE,ES:CODE ; ORG 100H GO: JMP START CR EQU 0DH LF EQU 0AH PORT DB 0 NODEDS DW 0 VERSERROR DB 'Version not compatible with Node Software$' PORTERROR DB 'Port number specified is invalid$' NOTBPQERROR DB 'Switch not found$' PASSERR DB 'Password file is invalid', 0dh,0ah,'$' KBLINE DB 80 DUP (20H) KBCURSOR DW OFFSET KBLINE REMLINE DB 300 DUP (20H) REMCURSOR DW OFFSET REMLINE SENDBUFFER DB 256 DUP (0) SENDCURSOR DW OFFSET SENDBUFFER CALLSIGN DB 10 DUP (0) COMMANDLINE DB 80 DUP (0) WHATMSG DB 'Invalid Command',0dh WAS DB ' was ',0 BADMSG DB 'Bad Parameter',0dh BADPORT DB 'Invalid Port Number',0dh NOVALCALLS DB 'No Valid Calls defined on this port',0dh SIGNINSTRING DB 'Attached to Remote Sysop system - enter password (' PWSTRING DB 16 DUP (0),cr PWTEXT DB 81 DUP (0) PWLEN DB 0 VALNODESFLAG DB 0 PORTPARAMFLAG DB 0 RESFLAG DB 0 ; SET IF RESIDENT MODE PWCHARS DB 5 DUP (0) ; PROMPT SENT PWFLAG DB 0 ; SET WHEN RESPONSE NEEDED PWFILE DB 'PASSWORD.BPQ' PWHANDLE DW 0 CMDX STRUC DB ' ' ; COMMAND STRING CMDLEN DB ? ; SIGNIFICANT LENGTH CMDPROC DW ? ; COMMAND PROCESSOR CMDFLAG DW ? ; FLAG/VALUE ADDRESS CMDX ENDS COMMANDLIST LABEL BYTE CMDX <'BYE',4,DOEXIT> CMDX <'TXDELAY',3,PORTVALX,PORTTXDELAY> CMDX <'MAXFRAME',3,PORTVAL,PORTWINDOW> CMDX <'RETRIES',3,PORTVAL,PORTN2> CMDX <'ROUTES',3,ROUTECMD> CMDX <'FRACK',3,PORTVAL,PORTT1> CMDX <'RESPTIME',3,PORTVAL,PORTT2> CMDX <'PACLEN',3,PORTVAL,PORTPACLEN> CMDX <'NODESPAC',3,PORTVAL,NODESPACLEN> CMDX <'QUALITY',3,PORTVAL,PORTQUALITY> CMDX <'PERSIST',2,PORTVALX,PORTPERSISTANCE> CMDX <'SLOTTIME',2,PORTVALX,PORTSLOTTIME> CMDX <'TXTAIL',3,PORTVALX,PORTTAILTIME> CMDX <'XMITOFF',7,PORTVAL,PORTDISABLED> CMDX <'DIGIFLAG',5,PORTVAL,DIGIFLAG> CMDX <'DIGIPORT',5,PORTVAL,DIGIPORT> CMDX <'USERS',1,PORTVAL,USERS> CMDX <'FULLDUP',5,PORTVALX,FULLDUPLEX> CMDX <'SOFTDCD',4,PORTVAL,SOFTDCDFLAG> CMDX <'L3ONLY',1,PORTVAL,PORTL3FLAG> CMDX <'BBSALIAS',4,PORTVAL,PORTBBSFLAG> CMDX <'VALIDCALL',5,VALNODES> IF BLACKBITS CMDX <'EXCLUDE',5,DISPBLACKLIST> ENDIF CMDX <'REBOOT',6,REBOOT> SAVECMD CMDX <'SAVENODES',8,SAVENODES> NUMBEROFCOMMANDS EQU ($-COMMANDLIST)/TYPE CMDX ; NEWVALUE DB 0 D10 DB 10 D100 DB 100 D16 DB 16 NUMBER DB 5 DUP (0) HEXFLAG DB 0 PORTNO DB 0 ; PORT NO FROM COMMAND ORIGIN DB 'R' ; SOURCE OF CURRENT COMMAND AX25CALL DB 7 DUP (0) ; WORK AREA FOR AX25 <> NORMAL CALL CONVERSION NORMCALL DB 10 DUP (0) ; CALLSIGN IN NORMAL FORMAT RESIDENT DB 'RESIDENT' REMOTEACTIVE DB 0 ROUTEPORT DB 0 ; PORT FOR ROUTE UPDATE NEWROUTEVAL DB 0 ROUTEDISP DB 0 ; DISPLAY/UPDATE FLAG ZAPFLAG DB 0 ; CLEAR ROUTE STATS FLAG RAN1 DB 0 RAN2 DB 0 RAN3 DB 0 RAN4 DB 0 RAN5 DB 0 OUTERLOOP: MOV AX,1000H INT 15H ; FOR DESQVIEW STI ; FOR IBM XT BIOS BUG CALL BG JMP OUTERLOOP ; Main background routine - searching for input from keyboard or Comms ; command lines are processed, and replies sent to screen or comms ; BG: INC WORD PTR RAN1 CALL MAINLOOP RET MAINLOOP: CMP RESFLAG,1 JE BG1 ; LEAVE KBD ALONE MOV AH,1 INT 16H JZ BG1 ; NO KEYBOARD CHAR ; INC RAN3 MOV AH,0 INT 16H ; GET THE CHAR CMP AL,19H ; CTRL/Y JNE KB000 JMP CLOSEDOWN ; KB000: ; INC ACTIVE ; SOMETHING HAPPENED CALL PROCESSKEY RET BG1: ; ; LOOK FOR STATUS CHANGE OR DATA AVAILABLE ; MOV AL,PORT MOV AH,4 CALL NODE CMP DX,0 JNE STATUSCHANGE ; ; NO STATUS - LOOK FOR DATA ; MOV DI,OFFSET REMLINE MOV AL,PORT MOV AH,3 CALL NODE CMP CX,0 JNE GOTCOMMS RET GOTCOMMS: ; ADD RAN3,CL MOV SI,OFFSET REMLINE PUSH CX CALL DISPLAYMSG POP CX CALL DOREMLINE ; PROCESS COMMAND LINE RET IGNOREIT: DISCONNECTED: MOV REMOTEACTIVE,0 RET ; STATUSCHANGE: ; ; SEE IF NOW CONNECTED - THEN SEE IF NEW CONNECT ; PUSH CX ; MOV AL,PORT MOV AH,5 ; ACK THE STATUS CHANGE CALL NODE POP CX OR CX,CX JZ DISCONNECTED ; ; CONNECTED - GET CALLSIGN ; MOV AL,PORT MOV AH,8 MOV DI,OFFSET CALLSIGN CALL NODE ; SEE IF A NEW CONNECT ; CMP REMOTEACTIVE,0 JNE ALREADYACTIVE ; ; A NEW CONNECT ; ; SEND PASSWORD REQUEST ; CALL SETUPPASSWORD MOV SI,OFFSET SIGNINSTRING CALL SENDSTRING ; PROMPT MOV REMOTEACTIVE,1 MOV PWFLAG,1 ; WAITING FOR PASSWORD ALREADYACTIVE: RET PROCESSKEY: OR AL,AL ; TWO KEY PAIR? JNZ NORMKEYBD ; NO MOV AL,AH ; JMP SPECIALKEY NORMKEYBD: CMP AL,20H JL KBCTRL KBNORM: CMP KBCURSOR,OFFSET KBLINE+79 JE NORMRET MOV DI,KBCURSOR MOV [DI],AL INC KBCURSOR CALL DISPLAY NORMRET: RET KBCTRL: CMP AL,7 JE KBNORM ; SO WE CAN SEND BELL CMP AL,8 JE KBBSPACE CMP AL,0DH JE KBCR RET KBBSPACE: CALL CUL RET KBCR: MOV DI,KBCURSOR MOV [DI],AL ; PUT IN BUFFER CALL DISPLAY ; ECHO IT MOV ORIGIN,'K' ; FROM KEYBOARD MOV SI,OFFSET KBLINE CALL TNCCOMMAND PUSH DS POP ES MOV ORIGIN,'R' MOV KBCURSOR,OFFSET KBLINE MOV DI,OFFSET KBLINE MOV CX,40 MOV AX,2020H REP STOSW RET SPECIALKEY: ; PROCESS EXTENDED CODE KEYS CMP AL,75 JE SPLBS ; CUR LEFT RET SPLBS: MOV AL,8 CALL KBBSPACE RET CUL: ; CURSOR LEFT CMP KBCURSOR,OFFSET KBLINE JE CURRET DEC KBCURSOR CALL DISPLAY ; ECHO IT CURRET: RET ; DOREMLINE: CMP REMLINE,0DH ; NULL? JE SKIPREM MOV ORIGIN,'R' ; REMOTE MOV SI,OFFSET REMLINE CMP PWFLAG,1 JE CHECKPASSWORD CALL TNCCOMMAND PUSH DS POP ES SKIPREM: RET CHECKPASSWORD: MOV CX,5 MOV BX,OFFSET PWCHARS ; STRING SEND PW000: MOV AL,[BX] INC BX CBW MOV DI,OFFSET PWTEXT-1 ADD DI,AX LODSB CMP AL,[DI] JNE DUFFPW LOOP PW000 JMP SHORT PWOK DUFFPW: CALL DOEXIT PWOK: MOV PWFLAG,0 JMP SKIPREM ; FINISHED DOEXIT: ; ; RETURN TO COMMAND MODE, AND RELEASE ; MOV AH,6 ; CONNECT/DISCONNECT MOV AL,PORT MOV CX,3 ; RETURN TO NODE CALL NODE RET SENDSTRING: ; ; SEND CR TERMINATED STRING TO NODE ; PUSH SI MOV CX,1 GETLENGTH: CMP BYTE PTR [SI],0DH JE GOTLENGTH INC SI INC CX JMP GETLENGTH GOTLENGTH: POP SI PUSH SI PUSH CX CALL DISPLAYMSG ; DISPLAY IT POP CX POP SI CMP ORIGIN,'R' ; REMOTE>? JNE SENDYY ; NO PUSH ES PUSH CS POP ES MOV AH,2 MOV AL,PORT CALL NODE ; SEND TO NODE POP ES SENDYY: RET PUTSTRING: ; ; SEND STRING LENGTH CX TO NODE ; LODSB CALL SENDCHAR LOOP PUTSTRING RET SENDCHAR: ; ; SEND TO CONSOLE, AND TNC IF REMOTE ; CMP ORIGIN,'R' JNE SENDXX PUSH DI MOV DI,SENDCURSOR MOV [DI],AL INC DI ; ANT BE SURE ABOUT SEG REGS CMP AL,0DH JNZ SEND10 ; ; SEND BUFFER TO NODE ; PUSH AX PUSH CX PUSH SI MOV CX,DI MOV SI,OFFSET SENDBUFFER SUB CX,SI PUSH ES PUSH CS POP ES MOV AL,PORT MOV AH,2 CALL NODE POP ES POP SI POP CX POP AX MOV DI,OFFSET SENDBUFFER SEND10: MOV SENDCURSOR,DI POP DI SENDXX: CALL DISPLAY RET DISPLAYMSG: LODSB CALL DISPLAY LOOP DISPLAYMSG RET DISPLAY: CMP RESFLAG,1 JE NODISPLAY PUSH AX MOV AH,14 INT 10H ; DISPLAY CMP AL,0DH JNE DISRET ; ; ADD LF TO CR ; MOV AH,14 MOV AL,0AH INT 10H DISRET: POP AX NODISPLAY: RET ; ; CLOSEDOWN: CALL DOEXIT ; KICK OFF ANY USER MOV AH,1 MOV AL,PORT MOV DL,0 MOV CL,0 CALL NODE ; DISABLE STREAM CALL WAITLOOP MOV AX,4C00H INT 21H ; WAITLOOP: MOV CX,1000 STOPLOOP: PUSH CX CALL MAINLOOP ; CLEAR ECHO OF COMMAND POP CX LOOP STOPLOOP RET TNCCOMMAND: ; ; PROCESS COMMAND TO TNC CODE ; MOV DI,OFFSET COMMANDLINE ; ; CONVERT TO UPPER CASE ; MOV CX,50 ; IN CASE GARBAGE!! TNCUCLOOP: LODSB CMP AL,0DH JE TNCUCEND CMP AL,61H JB TNCUCOK CMP AL,7AH JA TNCUCOK SUB AL,20H TNCUCOK: STOSB LOOP TNCUCLOOP ; TNCUCEND: MOV AL,20H MOV CX,30 REP STOSB ; PUT A FEW SPACES ON END FOR DECODE ROUTINES MOV VALNODESFLAG,0 MOV PORTPARAMFLAG,0 MOV SI,OFFSET COMMANDLINE CALL SCAN MOV DI,OFFSET COMMANDLIST MOV CX,NUMBEROFCOMMANDS COMMANDLOOP: PUSH SI PUSH DI PUSH CX MOV CL,CMDLEN[DI] ; MIN LENGTH REP CMPSB JE COMMANDFOUND POP CX POP DI POP SI ADD DI,TYPE CMDX LOOP COMMANDLOOP TNCDUFF: MOV SI,OFFSET WHATMSG CALL SENDSTRING RET COMMANDFOUND: CMP BYTE PTR [SI],0DH JE ENDOFCOMMAND CMP BYTE PTR [SI],' ' JE ENDOFCOMMAND CMPSB JE COMMANDFOUND ; LOOP TILL ALL COMPARED OR END ; ; END OF STRING WRONG ; POP CX POP DI POP SI JMP TNCDUFF ENDOFCOMMAND: POP CX POP DI POP AX ; TO CLEAR STACK CALL SCAN JMP CMDPROC[DI] ; ENTER COMMAND PROCESSOR - ; SI POINTS TO CHAR FOLLOWING COMMAND SCAN: MOV CX,10 ; DONT LOOK TOO FAR! SCAN1: CMP BYTE PTR [SI],20H JNE SCANRET INC SI LOOP SCAN1 XOR AL,AL ; RETURN Z SCANRET: RET ; ROUTECMD: ; ; PROCESS ROUTES TABLE UPDATE COMMANDS ; CMP BYTE PTR [SI],20H JNE NOTDISPALL JMP DISPROUTES NOTDISPALL: CALL CONVTOAX25 CALL SCAN CALL GETVALUE ; GET NUMBER, UP TO SPACE , CR OR OFFH JC BADROUTECMD ; INVALID DIGITS MOV AL,NEWVALUE MOV ROUTEPORT,AL CALL SCAN MOV ROUTEDISP,1 CMP BYTE PTR [SI],20H JE JUSTDISPLAY MOV ZAPFLAG,0 CMP BYTE PTR [SI],'Z' JNE NOTZAP MOV ZAPFLAG,1 JMP SHORT JUSTDISPLAY NOTZAP: MOV ROUTEDISP,2 ; LOCK UPDATE CMP BYTE PTR [SI],'!' JE JUSTDISPLAY CALL GETVALUE ; GET NUMBER, UP TO SPACE , CR OR OFFH JC BADROUTECMD ; INVALID DIGITS MOV AL,NEWVALUE MOV NEWROUTEVAL,AL MOV ROUTEDISP,0 CALL SCAN ; SEE IF ! MOV AH,[SI] JUSTDISPLAY: MOV ES,NODEDS MOV DI,ES:NEIGHBOURS MOV CX,ES:MAXNEIGHBOURS ROUTLOOP: MOV SI,OFFSET AX25CALL PUSH CX PUSH DI PUSH AX CALL COMPARECALLS POP AX MOV ES,NODEDS POP DI POP CX JE FOUNDROUT NEXTROUTE: ADD DI,ES:ROUTES_LEN LOOP ROUTLOOP BADROUTECMD: JMP BADVALUE FOUNDROUT: MOV AL,ROUTEPORT CMP ES:NEIGHBOUR_PORT[DI],AL JNE NEXTROUTE ; WRONG PORT CMP ZAPFLAG,1 JNE NOTCLEARCOUNTS XOR AX,AX MOV ES:WORD PTR NBOUR_IFRAMES[DI],AX MOV ES:WORD PTR NBOUR_IFRAMES+2[DI],AX MOV ES:WORD PTR NBOUR_RETRIES[DI],AX MOV ES:WORD PTR NBOUR_RETRIES+2[DI],AX JMP SHORT NOUPDATE NOTCLEARCOUNTS: CMP ROUTEDISP,1 JE NOUPDATE CMP ROUTEDISP,2 JE LOCKUPDATE MOV AL,NEWROUTEVAL MOV ES:NEIGHBOUR_QUAL[DI],AL CMP AH,'!' JNE NOUPDATE LOCKUPDATE: XOR ES:NEIGHBOUR_FLAG[DI],1 ; FLIP LOCKED BIT NOUPDATE: MOV SI,DI CALL DISPLAYROUTE RET PORTVALX: ; ; THESE SET TNC PARAMS, SO SET PARAM TIMER AFTERWARDS ; MOV PORTPARAMFLAG,1 JMP SHORT PORTVAL VALNODES: MOV VALNODESFLAG,1 PORTVAL: ; ; PROCESS PORT VALUE COMMANDS ; CALL GETVALUE ; GET NUMBER, UP TO SPACE , CR OR OFFH JC BADVALUE ; INVALID DIGITS VALOK: MOV AL,NEWVALUE MOV PORTNO,AL ; SAVE PORT NUMBER MOV ES,NODEDS MOV BX,ES:PORTTABLE MOV CX,ES:NUMBEROFPORTS FINDPORT: CMP AL,ES:PORTNUMBER[BX] JE PORTOK MOV BX,ES:PORTPOINTER[BX] LOOP FINDPORT PUSH DS POP ES MOV SI,OFFSET BADPORT JMP ERRCOM PORTOK: CMP VALNODESFLAG,1 JE DISPVALNODES CALL SCAN CMP BYTE PTR [SI],20H JBE DISPVAL ; DISPLAY ONLY CALL GETVALUE ; GET NUMBER, UP TO SPACE , CR OR OFFH JC BADVALUE ; INVALID DIGITS MOV CL,0 CALL KEYDISP ; DISPLAY KEYWORD WAS MOV SI,CMDFLAG[DI] ; ADDR OF FLAG MOV AH,ES:[SI][BX] ; GET OLD VALUE MOV AL,NEWVALUE MOV ES:[SI][BX],AL ; SET FLAG CMP PORTPARAMFLAG,1 JNE NOTPP MOV PARAMTIMER[BX],18 ; 1 SEC NOTPP: PUSH DS POP ES MOV AL,AH ; DISPLAY OLD JMP VALDISP BADVALUE: MOV SI,OFFSET BADMSG ERRCOM: CALL SENDSTRING PUSH DS POP ES RET DISPVALNODES: CMP ES:PERMITTEDCALLS[BX],0 JNE VALN00 MOV SI,OFFSET NOVALCALLS JMP ERRCOM ; NONE TO DISPLAY VALN00: MOV SI,ES:PERMITTEDCALLS[BX] VALN10: CMP BYTE PTR ES:[SI],0 JE VALNRET ; FINISHED MOV AX,0 CALL CMDR95 ADD SI,7 JMP VALN10 VALNRET: MOV AL,CR CALL SENDCHAR PUSH DS POP ES RET DISPVAL: MOV CX,1 CALL KEYDISP DISPV00: MOV SI,CMDFLAG[DI] ; ADDR OF FLAG MOV AL,ES:[SI][BX] ; GET VALUE VALDISP: PUSH DS POP ES MOV WORD PTR NUMBER+1,2020H ; CLEAR OUT IN CASE LESS THAN 3 DIGITS MOV NUMBER+3,20H MOV DI,OFFSET NUMBER CMP HEXFLAG,1 JE DISPHEX CALL CONV_DIGITS JMP SHORT DISPCOM DISPHEX: CALL CONVHEX DISPCOM: MOV SI,OFFSET NUMBER MOV CX,5 CALL PUTSTRING MOV AL,0DH CALL SENDCHAR RET KEYDISP: PUSH CX MOV SI,DI MOV CX,8 ; MAX LENGTH CALL PUTSTRING MOV AL,20H CALL SENDCHAR MOV AL,PORTNO CALL CONV_DIGITS MOV AL,20H CALL SENDCHAR MOV SI,OFFSET WAS ; DISPLAY 'was' POP CX OR CL,CL MOV CX,5 JZ KEYDISP12 ; NO MOV CX,1 ; LEAVE OUT 'WAS' KEYDISP12: CALL PUTSTRING RET IF BLACKBITS DISPBLACKLIST: BLIST00: CALL SCAN CMP BYTE PTR [SI],20H JBE DISPLIST ; DISPLAY ONLY PUSH DI CMP WORD PTR [SI],' Z' JNE UPLIST ; ; CLEAR LIST ; MOV AH,15 CALL NODE MOV DI,BX ; ADDR OF BLACKLIST MOV ES,NODEDS MOV CX,71 MOV AL,0 REP STOSB MOV ES:[DI],BX ; END ADDR BDISPIT: POP DI JMP SHORT DISPLIST UPLIST: CALL CONVTOAX25 MOV AH,15 CALL NODE MOV ES,NODEDS MOV AX,ES:[BX+71] ; END OF BLACKLIST MOV DI,BX ; ADDR OF LIST ADD DI,71 ; END OF LIST CMP DI,AX JE BDISPIT MOV DI,AX MOV SI,OFFSET AX25CALL MOV CX,6 REP MOVSB ADD WORD PTR ES:[BX+71],7 JMP BDISPIT DISPLIST: MOV AH,15 CALL NODE MOV SI,BX ; ADDR OF BLACKLIST MOV ES,NODEDS BLIST10: CMP BYTE PTR ES:[SI],0 JE BLISTRET ; FINISHED MOV AX,0 CALL CMDR95 ADD SI,7 JMP BLIST10 BLISTRET: MOV AL,CR CALL SENDCHAR PUSH DS POP ES RET ENDIF REBOOT: DB 0EAH,0,0,0FFH,0FFH GETVALUE: ; ; EXTRACT NUMBER (HEX OR DECIMAL) FROM INPUT STRING ; MOV NEWVALUE,0 LODSB CMP AL,'$' ; HEX? JE DECODEHEX DEC SI VALLOOP: LODSB CMP AL,' ' JE ENDVALUE CMP AL,0FFH JE ENDVALUE CMP AL,',' JE ENDVALUE ; ; ANOTHER DIGIT - MULTIPLY BY 10 ; MOV AL,NEWVALUE CMP AL,26 JNC DUFFVALUE ; WILL OVERFLOW IF MULTIPLIED MUL D10 MOV NEWVALUE,AL MOV AL,-1[SI] SUB al,'0' JC DUFFVALUE CMP AL,10 JNC DUFFVALUE ADD NEWVALUE,AL JC DUFFVALUE JMP VALLOOP DECODEHEX: HEXLOOP: LODSB CMP AL,' ' JE ENDVALUE CMP AL,0FFH JE ENDVALUE CMP AL,',' JE ENDVALUE ; ; ANOTHER DIGIT - MULTIPLY BY 16 ; MOV AL,NEWVALUE MUL D16 MOV NEWVALUE,AL MOV AL,-1[SI] SUB al,'0' JC DUFFVALUE CMP AL,10 JC HEXOK SUB AL,7 CMP AL,10 JC DUFFVALUE CMP AL,16 JNC DUFFVALUE HEXOK: ADD NEWVALUE,AL JMP HEXLOOP ENDVALUE: CLC RET DUFFVALUE: STC RET CONVHEX: MOV BYTE PTR NUMBER,'$' INC DI B2HEX: PUSH AX SHR AL,1 SHR AL,1 SHR AL,1 SHR AL,1 CALL B1HEX POP AX B1HEX: AND AL,0FH CMP AL,10 JB B1HEX2 ADD AL,7 B1HEX2: ADD AL,30H STOSB RET CONV_DIGITS: CMP AL,10 JB UNITS cmp AL,100 jb TENS MOV AH,0 DIV D100 OR AL,30H CALL SENDCHAR mov AL,AH TENS: CBW DIV D10 OR AL,30H CALL SENDCHAR MOV AL,AH ; REMAINDER = UNITS UNITS: add AL,30H CALL SENDCHAR ret CONVTOAX25: ; ; CONVERT CALLSIGN IN [SI] TO AX25 FORMAT IN AX25CALL ; RETURN NZ IF CALLSIGN INVALID ; MOV DI,OFFSET AX25CALL MOV CX,6 ; MAX ALPHANUMERICS MOV AL,40H REP STOSB ; CLEAR IN CASE SHORT CALL MOV AL,01100000B ; DEFAULT SSID STOSB MOV DI,OFFSET AX25CALL MOV CL,7 CONVAX00: LODSB CMP AL,'-' JE CONVAX20 ; SSID FOLLOWS CMP AL,' ' JE CONVAX40 ; END OF NAME ; CMP AL,'#' JNE NOTHASH CMP CL,7 JE CONVAX10 ; OK AS FIRST CHAR NOTHASH: CMP AL,'/' ; ALLOW / AND DIGITS (FOR W0RLI!) JB CONVAX49 ; INVALID CMP AL,'9' JBE CONVAX10 ; OK CMP AL,'A' JB CONVAX49 ; INVALID CMP AL,'Z' JBE CONVAX10 ; OK CMP AL,'a' JB CONVAX10 ; OK CMP AL,'z' JA CONVAX49 ; INVALID AND AL,NOT 20H ; CONVERT TO UPPER CASE CONVAX10: SAL AL,1 ; SHIFT UP STOSB LOOP CONVAX00 ; ; HAVE PROCESSED 7 CHARS - NAME IS INVALID ; JMP SHORT CONVAX49 CONVAX20: LODSB ; FIRST CHAR IF SSID CMP AL,'0' JB CONVAX49 ; INVALID CMP AL,'9' JA CONVAX49 ; OK ; MOV AH,AL ; SAVE LODSB CMP AL,' ' JE CONVAX30 ; END OF SSID INC SI ; OTHER CODE EXPECTS SI TO POINT TO NEXT FIELD CMP AL,'0' JB CONVAX49 ; INVALID CMP AL,'5' ; LIMIT 10 - 15 JA CONVAX49 ; OK ; SUB AL,30H CMP AH,'1' JNE CONVAX49 ; IF 2 DIGITS, FIRST MUST BE 1 ADD AL,10 MOV AH,AL CONVAX30: SAL AH,1 ; UP 1 BIT OR AH,01100000B ; DEFAULT RR BITS MOV AX25CALL+6,AH CONVAX40: ; ; NO SSID SUPPLIED ; XOR AL,AL ; SET ZERO RET CONVAX49: OR AL,1 ; SET NZ RET CONVFROMAX25: ; ; CONVERT AX25 FORMAT CALL IN [SI] TO NORMAL FORMAT IN NORMCALL ; RETURNS LENGTH IN CX AND NZ IF LAST ADDRESS BIT IS SET ; PUSH SI ; SAVE MOV DI,OFFSET NORMCALL MOV CX,10 ; MAX ALPHANUMERICS MOV AL,20H REP STOSB ; CLEAR IN CASE SHORT CALL MOV DI,OFFSET NORMCALL MOV CL,6 CONVAX50: LODSB CMP AL,40H JE CONVAX60 ; END IF CALL - DO SSID SHR AL,1 STOSB LOOP CONVAX50 CONVAX60: POP SI ADD SI,6 ; TO SSID LODSB MOV AH,AL ; SAVE FOR LAST BIT TEST SHR AL,1 AND AL,0FH JZ CONVAX90 ; NO SSID - FINISHED ; MOV BYTE PTR ES:[DI],'-' INC DI CMP AL,10 JB CONVAX70 SUB AL,10 MOV BYTE PTR ES:[DI],'1' INC DI CONVAX70: ADD AL,30H ; CONVERT TO DIGIT STOSB CONVAX90: MOV CX,DI SUB CX,OFFSET NORMCALL TEST AH,1 ; LAST BIT SET? RET W10 DW 10 ; ; POWERS OF 10 - 8 4-BYTE NUMBERS FROM 100,000,000 TO 10 ; POWERS DD 100000000 DD 10000000 DD 1000000 DD 100000 DD 10000 DD 1000 DD 100 DD 10 ; ACCUM DB 4 DUP (0) CONVFLAG DB 0 SUPPRESS DB 0 ; ZERO SUPPRESS FLAG DISPROUTES: ; MOV ES,NODEDS MOV SI,ES:NEIGHBOURS MOV CX,ES:MAXNEIGHBOURS CMDR10: PUSH CX CMP ES:NEIGHBOUR_CALL[SI],0 JE CMDR90 ; SPARE ; CALL DISPLAYROUTE CMDR90: POP CX ADD SI,TYPE NEIGHBOUR_LIST LOOP CMDR10 RET DISPLAYROUTE: MOV AL,20H CMP ES:NEIGHBOUR_LINK[SI],0 JE IDLEROUTE ; ; ACTIVE LINK ; MOV AL,'>' IDLEROUTE: CALL SENDCHAR MOV AL,20H CALL SENDCHAR MOV AL,ES:NEIGHBOUR_PORT[SI] CALL CONV_DIGITS MOV AL,20H CALL SENDCHAR MOV AX,0 CALL CMDR95 ; DISPLAY CALL ; ; CHECK FOR DIGIS ; CMP ES:NEIGHBOUR_DIGI[SI],0 JE CMDR50 MOV AL,'V' CALL SENDCHAR MOV AL,'I' CALL SENDCHAR MOV AL,'A' CALL SENDCHAR MOV AL,' ' CALL SENDCHAR MOV AX,7 CALL CMDR95 ; DISPLAY DIGI CALL CMP ES:NEIGHBOUR_DIGI+7[SI],0 JE CMDR50 MOV AX,14 CALL CMDR95 ; DISPLAY 2ND DIGI CALL CMDR50: MOV AL,ES:NEIGHBOUR_QUAL[SI] CALL CONV_DIGITS MOV AL,20H CALL SENDCHAR TEST ES:NEIGHBOUR_FLAG[SI],1 JZ NOTLOCKED MOV AL,'!' CALL SENDCHAR NOTLOCKED: ; ; DISPLAY FRAME COUNTS, ETC ; MOV AL,20H CALL SENDCHAR MOV AL,20H CALL SENDCHAR MOV AX,ES:WORD PTR NBOUR_IFRAMES[SI] MOV DX,ES:WORD PTR NBOUR_IFRAMES+2[SI] CALL CONVBIGNUMBER MOV AL,20H CALL SENDCHAR MOV AL,20H CALL SENDCHAR MOV AX,ES:WORD PTR NBOUR_RETRIES[SI] MOV DX,ES:WORD PTR NBOUR_RETRIES+2[SI] CALL CONVBIGNUMBER MOV AL,20H CALL SENDCHAR MOV AL,20H CALL SENDCHAR MOV AL,ES:NBOUR_MAXFRAME[SI] CALL CONV_DIGITS MOV AL,20H CALL SENDCHAR MOV AL,20H CALL SENDCHAR MOV AL,ES:NBOUR_FRACK[SI] CALL CONV_DIGITS MOV AL,20H CALL SENDCHAR MOV AL,20H CALL SENDCHAR ; ; DO TIME ; MOV AL,BYTE PTR ES:NEIGHBOUR_TIME+1[SI] CALL PRINTNUM MOV AL,':' CALL SENDCHAR MOV AL,BYTE PTR ES:NEIGHBOUR_TIME[SI] CALL PRINTNUM ; MOV AL,20H ; STOSB ; MOV AL,NBOUR_PACLEN[SI] ; CALL CONV_DIGITS MOV AL,0DH CALL SENDCHAR RET CMDR95: ; ; DO A CALLSIGN ; PUSH SI PUSH DI MOV DI,OFFSET AX25CALL MOV DS,NODEDS PUSH CS POP ES MOV CX,7 REP MOVSB PUSH CS POP DS MOV SI,OFFSET AX25CALL CALL CONVFROMAX25 ; CONVERT TO CALL INC CX POP DI MOV SI,OFFSET NORMCALL CALL PUTSTRING POP SI MOV ES,NODEDS RET CONVBIGNUMBER: MOV SUPPRESS,1 ; ZERO SUPRESS; JMP SHORT DEC000 ; ; THIS ROUTINE CONVERTS A 32 BIT BINARY NUMBER IN DX,AX ; TO PRINTABLE DECIMAL CHARS ; CONVTO10DIGITS: MOV SUPPRESS,0 DEC000: PUSH BX PUSH SI PUSH CX MOV CONVFLAG,0 MOV CX,8 MOV WORD PTR ACCUM,AX MOV WORD PTR ACCUM+2,DX MOV SI,OFFSET POWERS ; LOW ORDER OF FIRST DEC010: MOV BL,0 ; LOOP COUNT FOR SUBTRACT DEC020: CALL SUB4 JC DEC030 ; TOO SMALL INC BL ; NUMBER OF SUBTRACTS JMP DEC020 ; DEC030: CALL ADD4 ; PUT BACK MOV AL,BL ADD AL,'0' ; TO CHARACTER FORM TEST CONVFLAG,1 JNZ DEC040 ; ALREADY HAVE A SIGNIFICANT CHAR CMP AL,'0' ; IS IT A ZERO JE DEC036 ; YES, SO CHANGE TO SPACE OR CONVFLAG,1 ; SET NON-ZERO CHAR FOUND JMP SHORT DEC040 ; AND PRINT IT ; DEC036: CMP SUPPRESS,1 JE DEC044 ; SUPPRESS LEADING SPACES MOV AL,' ' DEC040: CALL SENDCHAR DEC044: ADD SI,4 LOOP DEC010 MOV AL,ACCUM ; REMAINDER ADD AL,'0' CALL SENDCHAR ; PRINT IT ; POP CX POP SI POP BX RET ; ; ROUTINE TO ADD TWO 4 BYTE NUMBERS ; ; ADD4: MOV AL,[SI] ADD ACCUM,AL MOV AL,[SI+1] ADC ACCUM+1,AL MOV AL,[SI+2] ADC ACCUM+2,AL MOV AL,[SI+3] ADC ACCUM+3,AL RET ; ; ROUTINE TO SUBTRACT TWO 4 BYTE NUMBERS ; ; SUB4: MOV AL,[SI] SUB ACCUM,AL MOV AL,[SI+1] SBB ACCUM+1,AL MOV AL,[SI+2] SBB ACCUM+2,AL MOV AL,[SI+3] SBB ACCUM+3,AL RET PRINTNUM: MOV AH,0 DIV D10 OR AX,3030H PUSH AX CALL SENDCHAR POP AX MOV AL,AH CALL SENDCHAR RET SETUPPASSWORD: PUSH ES MOV AX,40H MOV ES,AX MOV AX,ES:6CH MOV WORD PTR RAN4,AX POP ES MOV DI,OFFSET PWSTRING MOV BX,OFFSET PWCHARS ; VALUE SENT MOV SI,OFFSET RAN1 MOV CX,5 RANLOOP: LODSB PUSH CX CALL PWCHR POP CX MOV [BX],AL INC BX MOV AL,20H STOSB LOOP RANLOOP DEC DI MOV AL,')' STOSB MOV AL,0DH STOSB RET PWCHR: ; ; LIMIT NUMBER IN A TO RANGE 1 - PW LENGTH ; INC AL ; DONT ALLOW ZERO CMP PWLEN,0 JE NOPW ; PASSWORD NOT SET PWL000: SUB AL,PWLEN JZ TOOLOW JNC PWL000 ; LOOP TILL -VE OR ZERO TOOLOW: ADD AL,PWLEN NOPW1: PUSH AX MOV AH,0 DIV D10 ADD AX,3030H STOSW POP AX ; RETURN NUMBER ; RET NOPW: MOV AL,1 JMP SHORT NOPW1 COMPARECALLS: ; ; COMPARE AX25 CALLSIGNS IN SI, DI IGNORING EXTRA BITS IN SSID ; MOV CX,6 REP CMPSB ; COMPARE WITH LINKCALL JNE COMPCALLRET ; DONT MATCH LODSB MOV AH,ES:[DI] AND AX,0001111000011110B ; MASK NON-SSID BITS CMP AL,AH COMPCALLRET: RET NODE: INTVAL LABEL BYTE INT 7FH RET ; ; RESIDENT MODE STUFF ; STACKINUSE DB 0 HWTIMERLINK DD 0 ; LINK TO OLD H/W TIMER ROUTINE SAVESTACKSEG DW 0 SAVESTACKPTR DW 0 DW 128 DUP (0) INTSTACKTOP LABEL WORD HWTIMERINT: ; ; ENTERED FROM 8253 TIMER 0 INTERRUPT (LEVEL 0 - INT 8) ; ; CALL SYSTEM TIMER CODE, AND IF NOT ALREADY ACTIVE, CALL MAIN ROUTINE ; ; save stack ; PUSHF ; RETURN IS VIA IRET CALL CS:HWTIMERLINK ; ; BY NOW INT CONTROLLER HAS BEEN RESET, SO OTHER INTERRUPTS MAY OCCUR - ; INTS ARE DISABLED ; ; CLD ; CALL MAIN PROCESSING ROUTINE IF NOT ACTIVE CMP CS:STACKINUSE,0 JNE ALREADY_ACTIVE ; MOV CS:STACKINUSE,1 ; FORCE SERIALISATION ; ; SAVE COMPLETE STATUS ; ; save stack ; PUSH AX MOV CS:SAVESTACKSEG,SS MOV CS:SAVESTACKPTR,SP ; MOV AX,CS MOV SS,AX MOV SP,OFFSET INTSTACKTOP ; STI ; PUSH ES PUSH DS PUSH SI PUSH DI PUSH BP PUSH BX PUSH CX PUSH DX ; MOV DS,AX MOV ES,AX CALL BG POP DX POP CX POP BX POP BP POP DI POP SI POP DS POP ES ; ; RESTORE OLD STACK ; CLI MOV SS,CS:SAVESTACKSEG MOV SP,CS:SAVESTACKPTR ; POP AX MOV CS:STACKINUSE,0 ALREADY_ACTIVE: IRET ; ENDOFPROG LABEL BYTE BADCONFIGMSG DB 'Configuration file read error',0DH,0AH,'$' CONFIGFILENAME DB CONFIGNAME,0 NOCONFIGMSG DB 'Configuration file ',CONFIGNAME,' not found',0DH,0AH,'$' ; ; BPQCFG FIRST 128 BYTES ; CONFIGTABLE LABEL BYTE ; ; CONFIGURATION DATA STRUCTURE ; ; DEFINES LAYOUT OF CONFIG RECORD PRODUCED BY CONFIGURATION PROG ; ; LAYOUT MUST MATCH THAT IN CONFIG.C SOURCE ; C_NODECALL DB 10 DUP (0) ; OFFSET = 0 C_NODEALIAS DB 10 DUP (0) ; OFFSET = 10 C_BBSCALL DB 10 DUP (0) ; OFFSET = 20 C_BBSALIAS DB 10 DUP (0) ; OFFSET = 30 ; C_OBSINIT DW 0 ; OFFSET = 40 C_OBSMIN DW 0 ; OFFSET = 42 C_NODESINTERVAL DW 0 ; OFFSET = 44 C_L3TIMETOLIVE DW 0 ; OFFSET = 46 C_L4RETRIES DW 0 ; OFFSET = 48 C_L4TIMEOUT DW 0 ; OFFSET = 50 C_BUFFERS DW 0 ; OFFSET = 52 C_PACLEN DW 0 ; OFFSET = 54 C_TRANSDELAY DW 0 ; OFFSET = 56 C_T3 DW 0 ; OFFSET = 58 DW 0 ; OFFSET = 60 DW 0 ; OFFSET = 62 C_IDLETIME DW 0 ; OFFSET = 64 C_EMSFLAG DB 0 ; OFFSET = 66 DB 0 C_BBS DB 0 ; OFFSET = 68 C_NODE DB 0 ; OFFSET = 69 C_HOSTINTERRUPT DB 0 ; OFFSET = 70 C_DESQVIEW DB 0 ; OFFSET = 71 C_MAXLINKS DW 0 ; OFFSET = 72 C_MAXDESTS DW 0 C_MAXNEIGHBOURS DW 0 C_MAXCIRCUITS DW 0 ; 78 C_TNCPORTLISTO DB 16 DUP (0) ; OFFSET = 80 C_IDINTERVAL DW 0 ; 96 C_XXXXXXXX DW 0 ; 98 ; SPARE (WAS DIGIFLAG) C_MINQUAL DW 0 ; 100 C_HIDENODES DB 0 ; 102 C_L4DELAY DW 0 ; 103 C_L4WINDOW DW 0 ; 105 C_BTINTERVAL DW 0 ; 106 X_UNPROTO DB 9 DUP (0) ; 108 ; NOW SPARE C_BBSQUAL DW 0 ; 117 DB (CONFIGTABLE+128-$) DUP (0) CONFIGHANDLE DW 0 START: ; MOV DX,OFFSET MSG1 MOV AH,9 INT 21H ; ; SEE IF JUST 'SAVENODES' ; MOV SI,5DH MOV DI,OFFSET SAVECMD MOV CX,8 REP CMPSB JNE NOTSAVENODES CALL SAVENODES RET NOTSAVENODES: MOV SI,5DH CALL GETVALUE JC BADPORTVAL MOV AL,NEWVALUE OR AL,AL JZ BADPORTVAL CMP AL,64 JA BADPORTVAL MOV BYTE PTR PORT,AL ; PARAM IS PORT NUMBER ; ; GET NODE INTERRUPT NUMBER FROM CONFIG FILE ; MOV DX,OFFSET CONFIGFILENAME MOV AH,3DH MOV AL,0 ; READ ONLY INT 21H ; OPEN IT JC NOCONFIGFILE MOV CONFIGHANDLE,AX MOV BX,AX MOV DX,OFFSET CONFIGTABLE MOV CX,128 MOV AH,3FH INT 21H ; READ CMP AX,CX JNE SHORTCONFIG JMP SHORT PROCESSCONFIG NOCONFIGFILE: MOV DX,OFFSET NOCONFIGMSG JMP SHORT CONFIGERR SHORTCONFIG: MOV DX,OFFSET BADCONFIGMSG CONFIGERR: MOV AH,9 INT 21H MOV AX,4C01H INT 21H ; EXIT BADPORTVAL: MOV DX,OFFSET PORTERROR MOV AH,9 INT 21H JMP EXIT PROCESSCONFIG: MOV BX,CONFIGHANDLE MOV AH,3EH INT 21H ; CLOSE IT MOV AL,C_HOSTINTERRUPT ; INTERRUPT MOV BYTE PTR INTVAL+1,AL ; PATCH NODE CALL INSTRUCTION ; ; GET NODE VERSION AND DATA SEGMENT ; MOV AH,0 ADD AX,AX ADD AX,AX ; * 4 MOV SI,AX ; TO CODE PUSH DS XOR AX,AX MOV DS,AX LDS SI,DS:[SI] ; GET POINTER TO SWITCH CODE SUB SI,7 MOV DI,OFFSET G8BPQ MOV CX,5 REP CMPSB ; MAKE SURE SWITCH IS LOADED JE SWITCHOK POP DS MOV DX,OFFSET NOTBPQERROR MOV AH,9 INT 21H JMP SHORT EXIT SWITCHOK: CMP BYTE PTR DS:[SI],MAJORVERSION JNE BADVERSION CMP BYTE PTR DS:1[SI],MINORVERSION JE VERSIONOK BADVERSION: POP DS MOV DX,OFFSET VERSERROR MOV AH,9 INT 21H EXIT: MOV AX,4C00H INT 21H VERSIONOK: MOV AX,DS:4 ; NODE DS POP DS MOV NODEDS,AX MOV AH,1 MOV AL,PORT MOV DL,4 ; SYSOP APPL MOV CL,0 ; APPL FLAGS CALL NODE ; MOV DX,OFFSET PWFILE MOV AH,3DH MOV AL,0 ; READ ONLY INT 21H ; OPEN IT JC NOPWFILE MOV BX,AX MOV DX,OFFSET PWTEXT MOV CX,80 MOV AH,3FH INT 21H MOV AH,3EH INT 21H ; CLOSE MOV SI,OFFSET PWTEXT PWSETUP: CMP BYTE PTR [SI],20H JB FILEOK INC SI INC PWLEN JMP SHORT PWSETUP NOPWFILE: MOV DX,OFFSET PASSERR MOV AH,9 INT 21H FILEOK: ; ; SEE IF RESIDENT OPTION SPECIFIED ; ; MOV SI,6DH MOV DI,OFFSET RESIDENT MOV CX,8 REP CMPSB JNE NOTRESIDENT CALL MAKERESIDENT INT 27H NOTRESIDENT: JMP OUTERLOOP MAKERESIDENT: ; ; hook the system timer - we need to be able to poll the rx buffer ; MOV RESFLAG,1 MOV WORD PTR SAVECMD,0 ; DISABLE SAVENODES push ds PUSH ES MOV AX,0 MOV DS,AX ; MOV SI,8*4 ; ADDR OF H/W TIMER INTERRUPT (INT 8) ; MOV AX,[SI] ; SYSTEM TIMER ROUTINE OFFSET MOV WORD PTR cs:HWTIMERLINK,AX MOV AX,2[SI] MOV WORD PTR cs:HWTIMERLINK+2,AX ; MOV [SI+2],CS MOV AX,OFFSET HWTIMERINT MOV [SI],AX ; POP ES POP DS MOV DX,OFFSET ENDOFPROG RET MARKER: ; ; FOLLOWING SEQUENCE OCCURS AT START OF THENODE CODE SEGMENT ; RET DB 'BPQ' ; FOR DUMP SYSTEM FILENAME DB 'BPQNODES',0 HANDLE DW 0 DECODEDNAME DB 20 DUP (0) LINE DB 80 DUP (0) ROUTEADD DB 'ROUTE ADD ' NODEADD DB 'NODE ADD ' G8BPQ LABEL BYTE MSG1 DB NAMESTRING,' Switch SYSOP Support Program for Version ' db VERSIONSTRING,' - ',DATESTRING,CR,LF,'$' MSG2 DB 'CANT FIND BPQCODE',CR,LF,'$' MSG3 DB 'TABLE DUMP COMPLETE',CR,LF,'$' SAVENODES: ; ; CHECK ALL INTS ; ASSUME DS:NOTHING MOV BX,0 CHECKLOOP: CALL CHECKIT JE CODEFOUND ADD BX,4 CMP BX,400H JB CHECKLOOP PUSH CS POP DS MOV DX,OFFSET MSG2 MOV AH,9 INT 21H RET CODEFOUND: PUSH DS MOV AX,[SI] ; DATA SEG MOV DS,AX PUSH DS ; SAVE PUSH CS ; GET OUR SEG BACK FOR OPEN POP DS ; ; OPEN FILE ; MOV DX,OFFSET FILENAME MOV CX,0 MOV AH,3CH INT 21H MOV HANDLE,AX POP DS ASSUME DS:NOTHING CALL DOROUTES CALL DONODES POP DS CLOSE: PUSH CS POP DS MOV BX,HANDLE MOV AH,3EH INT 21H ; CLOSE FILE ; MOV DX,OFFSET MSG3 MOV AH,9 INT 21H RET CHECKIT: MOV AX,0 MOV DS,AX MOV AX,2[BX] ; CODE SEGMENT MOV DS,AX MOV SI,0 MOV DI,OFFSET MARKER MOV CX,4 REP CMPSB RET DONODES: MOV SI,OFFSET NODEADD MOV DI,OFFSET LINE MOV CX,9 CLI REP MOVS LINE, NORMCALL STI MOV BX,DS:DESTS MOV CX,DS:MAXNODES CMDN10: PUSH CX MOV DI,OFFSET LINE+9 CMP DEST_CALL[BX],0 JE CMDN20 ; SPARE ; TEST DEST_STATE[BX],80H JNZ CMDN20 ; SPECIAL (BBS) NODE LEA SI,DEST_CALL[BX] CALL DECODENODENAME ; CONVERT TO ALIAS:CALL MOV CX,18 CMDN15: LODS NORMCALL STOSB CMP AL,' ' JE CMDN16 LOOP CMDN15 CMDN16: PUSH BX MOV CX,3 CMDN110: MOV SI,ROUT1_NEIGHBOUR[BX] CMP SI,0 JE CMDN199 PUSH CX PUSH SI ; SAVE NEIGHBOUR PUSH DI CALL CONVFROMAX25 ; CONVERT TO CALL POP DI MOV SI,OFFSET NORMCALL NCOPY: LODS NORMCALL STOSB CMP AL,' ' JNE NCOPY ; ; GET PORT FROM ROUTES ENTRY ; POP SI MOV AL,NEIGHBOUR_PORT[SI] CALL XCONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS mov AL,' ' stosb MOV AL,ROUT1_QUALITY[BX] CALL XCONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS mov AL,' ' stosb TEST ROUT1_OBSCOUNT[BX],80H JZ NOTLOCKEDDEST MOV AX,' !' STOSW NOTLOCKEDDEST: ADD BX,4 POP CX LOOP CMDN110 CMDN199: MOV AX,0A0DH STOSW PUSH DS PUSH CS POP DS MOV DX,OFFSET LINE MOV CX,DI SUB CX,DX ; GET LENGTH MOV BX,HANDLE MOV AH,40H INT 21H POP DS POP BX CMDN20: POP CX ADD BX,DS:DESTS_LEN LOOP CMDN10_JMP ; TOO FAR! CMDN99A: RET CMDN10_JMP: JMP CMDN10 DECODENODENAME: ; ; SI = TABLE ENTRY WITH AX25 CALL AND ALIAS ; ; RETURNS SI = 20 BYTE DECODED NAME IN FORM ALIAS:CALL ; PUSH CX PUSH DI MOV DI,OFFSET DECODEDNAME MOV CX,10 MOV AX,' ' REP STOSW ; CLEAR IT CALL CONVFROMAX25 PUSH CX ; SAVE CALL LENGTH MOV DI,OFFSET DECODEDNAME MOV CX,6 ; MAX LENGTH DECODEN10: LODSB CMP AL,' ' JBE DECODEN20 STOSB LOOP DECODEN10 DECODEN20: MOV AL,':' STOSB POP CX MOV SI,OFFSET NORMCALL CLI REP MOVS LINE, NORMCALL STI POP DI POP CX MOV SI,OFFSET DECODEDNAME RET DOROUTES: ; MOV SI,OFFSET ROUTEADD MOV DI,OFFSET LINE MOV CX,10 CLI REP MOVS LINE, NORMCALL STI MOV SI,DS:NEIGHBOURS MOV CX,DS:MAXNEIGHBOURS XCMDR10: PUSH CX MOV DI,OFFSET LINE+10 CMP NEIGHBOUR_CALL[SI],0 JE XCMDR92 ; SPARE ; MOV AX,0 CALL XCMDR95 ; DISPLAY CALL MOV AL,NEIGHBOUR_PORT[SI] CALL XCONV_DIGITS MOV AL,20H STOSB MOV AL,NEIGHBOUR_QUAL[SI] CALL XCONV_DIGITS MOV AL,20H STOSB TEST NEIGHBOUR_FLAG[SI],1 JZ XNOTLOCKED MOV AL,'!' STOSB XNOTLOCKED: ; ; CHECK FOR DIGIS ; CMP NEIGHBOUR_DIGI[SI],0 JE XCMDR50 MOV AL,20H STOSB MOV AX,'IV' STOSW MOV AX,' A' STOSW ; PUT IN VIA MOV AX,7 CALL XCMDR95 ; DISPLAY DIGI CALL CMP NEIGHBOUR_DIGI+7[SI],0 JE XCMDR50 MOV AX,14 CALL XCMDR95 ; DISPLAY 2ND DIGI CALL XCMDR50: MOV AL,20H STOSB MOV AL,NBOUR_MAXFRAME[SI] CALL XCONV_DIGITS MOV AL,20H STOSB MOV AL,NBOUR_FRACK[SI] CALL XCONV_DIGITS MOV AL,20H STOSB MOV AL,NBOUR_PACLEN[SI] CALL XCONV_DIGITS XCMDR90: PUSH DS PUSH CS POP DS MOV AX,0A0DH STOSW MOV DX,OFFSET LINE MOV CX,DI SUB CX,DX ; GET LENGTH MOV BX,HANDLE MOV AH,40H INT 21H POP DS XCMDR92: POP CX ADD SI,DS:ROUTES_LEN LOOP XCMDR10_JMP RET XCMDR10_JMP: JMP XCMDR10 XCMDR95: PUSH SI PUSH DI ADD SI,AX CALL CONVFROMAX25 INC CX MOV SI,OFFSET NORMCALL POP DI CLI REP MOVS LINE, NORMCALL STI POP SI RET XCONV_DIGITS: CMP AL,10 JB XUNITS cmp AL,100 jb XTENS MOV AH,0 DIV D100 OR AL,30H STOSB mov AL,AH XTENS: CBW DIV D10 OR AL,30H STOSB MOV AL,AH ; REMAINDER = UNITS XUNITS: add AL,30H STOSB ret CODE ENDS ; END GO