PAGE 56,132 ; .386 ; ; SEGMENT definitions and order ; ; July 2008 ; Add basic IP decoding ; Feb 2012 ; Created from MONDECODE to provide a transparent decode for MIC-E frames ;* 32 Bit code _TEXT SEGMENT DWORD USE32 PUBLIC 'CODE' _TEXT ENDS ;* Contains 32 Bit data _BPQDATA SEGMENT DWORD PUBLIC 'DATA' _BPQDATA ENDS ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:FLAT _BPQDATA SEGMENT CR EQU 0DH LF EQU 0AH D10 DW 10 D60 DD 60 D3600 DD 3600 D86400 DD 86400 TIMESTAMP DD 0 NEWVALUE DW 0 WORD10 DW 10 WORD16 DW 16 ; ; BASIC LINK LEVEL MESSAGE BUFFER LAYOUT ; MESSAGE STRUC MSGCHAIN DD ? ; CHAIN WORD MSGPORT DB ? ; PORT MSGLENGTH DW ? ; LENGTH MSGDEST DB 7 DUP (?) ; DESTINATION MSGORIGIN DB 7 DUP (?) ; ORIGIN ; ; MAY BE UP TO 56 BYTES OF DIGIS ; MSGCONTROL DB ? ; CONTROL BYTE MSGPID DB ? ; PROTOCOL IDENTIFIER MSGDATA DB ? ; START OF LEVEL 2 MESSAGE ; MESSAGE ENDS ; ; ; ; L4FLAGS DEFINITION ; L4BUSY EQU 80H ; BNA - DONT SEND ANY MORE L4NAK EQU 40H ; NEGATIVE RESPONSE FLAG L4MORE EQU 20H ; MORE DATA FOLLOWS - FRAGMENTATION FLAG L4CREQ EQU 1 ; CONNECT REQUEST L4CACK EQU 2 ; CONNECT ACK L4DREQ EQU 3 ; DISCONNECT REQUEST L4DACK EQU 4 ; DISCONNECT ACK L4INFO EQU 5 ; INFORMATION L4IACK EQU 6 ; INFORMATION ACK ; NULL EQU 00H CR EQU 0DH LF EQU 0AH ; PORT_MSG DB ' Port=',NULL UI_MSG DB 'UI',NULL ;-----------------------------------------------------------------------------; ; Parameter area for received frame ; ;-----------------------------------------------------------------------------; PORT_NO DB 0 ; Received port number 0 - 256 VERSION_NO DB 0 ; Version 1 or 2 1,2 POLL_FINAL DB 0 ; Poll or Final ? P,F COMM_RESP DB 0 ; Command or Response C,R FRAME_TYPE DB 0 ; Frame Type UI etc in Hex PID DB 0 ; Protocol ID FRAME_LENGTH DD 0 ; Length of frame 0 - 65... NR DB 0 ; N(R) Flag NS DB 0 ; N(S) Flag INFO_FLAG DB 0 ; Information Packet ? 0 No, 1 Yes ; ; HDLC COMMANDS (WITHOUT P/F) ; UI EQU 3 SABM EQU 2FH DISC EQU 43H DM EQU 0FH UA EQU 63H FRMR EQU 87H RR EQU 1 RNR EQU 5 REJ EQU 9 ; PFBIT EQU 10H ; POLL/FINAL BIT IN CONTROL BYTE CRLF DB 0DH,0AH AX25CALL DB 7 DUP (0) ; WORK AREA FOR AX25 <> NORMAL CALL CONVERSION NORMCALL DB 10 DUP (0) ; CALLSIGN IN NORMAL FORMAT NORMLEN DD 0 ; LENGTH OF CALL IN NORMCALL ; TENK DD 10000 DD 1000 WORD100 DD 100 DWORD10 DD 10 ; ACCUM DB 4 DUP (0) CONVFLAG DB 0 SUPPRESS DB 0 ; ZERO SUPPRESS FLAG SAVEDI DD 0 SAVESI DD 0 _BPQDATA ENDS _TEXT SEGMENT PUBLIC 'CODE' PUBLIC _APRSMONDECODE EXTRN DISPLAY_BYTE_1:NEAR, DISPLAY_BYTE_2:NEAR, DISPADDR:NEAR, NORMSTR:NEAR _APRSMONDECODE: ; ; esi=message, edi=buffer ; MOV SAVESI,ESI MOV SAVEDI,EDI MOV TIMESTAMP,EAX ; ; GET THE CONTROL BYTE, TO SEE IF THIS FRAME IS TO BE DISPLAYED. We Should only get UI frames ; PUSH ESI MOV ECX,9 ; MAX DIGIS CTRLLOOP: TEST BYTE PTR MSGCONTROL-1[ESI],1 JNZ CTRLFOUND ADD ESI,7 LOOP CTRLLOOP ; ; INVALID FRAME ; POP ESI MOV ECX,0 RET CTRLFOUND: MOV AL,MSGCONTROL[ESI] POP ESI ; TEST AL,1 ; I FRAME JZ IFRAME AND AL,NOT PFBIT ; CLEAR P/F CMP AL,3 ; UI JE OKTOTRACE ; ALWAYS DO UI IFRAME: MOV ECX,0 RET OKTOTRACE: ; ;-----------------------------------------------------------------------------; ; Get the port number of the received frame ; ;-----------------------------------------------------------------------------; mov CL,MSGPORT[ESI] mov PORT_NO,CL mov AH,MSGDEST+6[ESI] mov AL,MSGORIGIN+6[ESI] mov COMM_RESP,0 ; Clear Command/Response Flag ;-----------------------------------------------------------------------------; ; Is it a Poll/Final or Command/Response ; ;-----------------------------------------------------------------------------; test AH,80H mov COMM_RESP,'C' jnz NOT_RESPONSE mov COMM_RESP,'R' NOT_RESPONSE: ;-----------------------------------------------------------------------------; ; Is this version 1 or 2 of AX25 ? ; ;-----------------------------------------------------------------------------; xor AH,AL test AH,80H mov VERSION_NO,1 je VERSION_1 mov VERSION_NO,2 VERSION_1: ; ; DISPLAY TIMESTAMP AND T/R FLAG ; MOV EAX,TIMESTAMP mov EDX,0 DIV D86400 MOV EAX,EDX MOV edx,0 DIV D3600 CALL DISPLAY_BYTE_2 MOV AL,':' CALL PUTCHAR MOV EAX,EDX MOV EDX,0 DIV D60 ; MINS IN AX, SECS IN DX PUSH DX CALL DISPLAY_BYTE_2 MOV AL,':' CALL PUTCHAR POP AX ; SECS CALL DISPLAY_BYTE_2 MOV AL,'R' TEST PORT_NO,80H JZ TR MOV AL,'T' TR: CALL PUTCHAR MOV AL,' ' CALL PUTCHAR ;-----------------------------------------------------------------------------; ; Display Origin Callsign ; ;-----------------------------------------------------------------------------; PUSH ESI lea ESI,MSGORIGIN[ESI] call CONVFROMAX25 mov ESI,OFFSET NORMCALL call DISPADDR POP ESI PUSH ESI mov AL,'>' call PUTCHAR ;-----------------------------------------------------------------------------; ; Display Destination Callsign ; ;-----------------------------------------------------------------------------; lea ESI,MSGDEST[ESI] call CONVFROMAX25 mov ESI,OFFSET NORMCALL call DISPADDR pop ESI movzx EAX,MSGLENGTH[ESI] mov FRAME_LENGTH,EAX mov CX,8 ; Max number of digi-peaters ;-----------------------------------------------------------------------------; ; Display any Digi-Peaters ; ;-----------------------------------------------------------------------------; NEXT_DIGI: test MSGORIGIN+6[ESI],1 jnz NO_MORE_DIGIS add ESI,7 sub FRAME_LENGTH,7 ; Reduce length push ECX push ESI lea ESI,MSGORIGIN[ESI] call CONVFROMAX25 ; Convert to call push EAX ; Last byte is in AH mov AL,',' call PUTCHAR mov ESI,OFFSET NORMCALL call DISPADDR pop EAX test AH,80H jz NOT_REPEATED ; We should only put a * on the last repeated test AH,1 ; if last address must be last repeated jnz NEEDSTAR pop ESI test MSGORIGIN+13[ESI],80H push ESI jnz NOSTAR ; Repeated by next NEEDSTAR: mov AL,'*' call PUTCHAR NOSTAR: NOT_REPEATED: pop ESI pop ECX loop NEXT_DIGI NO_MORE_DIGIS: ;----------------------------------------------------------------------------; ; Display the Port No of the frame ; ;----------------------------------------------------------------------------; mov EBX,OFFSET PORT_MSG call NORMSTR mov AL,PORT_NO AND AL,7FH call DISPLAY_BYTE_1 ; mov AL,' ' call PUTCHAR ;-----------------------------------------------------------------------------; ; If this is Version 2 get the Poll/Final Bit ; ;-----------------------------------------------------------------------------; mov POLL_FINAL,0 ; Clear Poll/Final Flag mov AL,MSGCONTROL[ESI] ; Get control byte cmp COMM_RESP,'C' jne NOT_COMM test AL,PFBIT je NOT_POLL mov POLL_FINAL,'P' NOT_POLL: NOT_COMM: cmp COMM_RESP,'R' jne NOT_RESP test AL,PFBIT je NOT_FINAL mov POLL_FINAL,'F' NOT_FINAL: NOT_RESP: ;-----------------------------------------------------------------------------; ; Start displaying the frame information ; ;-----------------------------------------------------------------------------; and AL,NOT PFBIT ; Remove P/F bit mov FRAME_TYPE,AL mov AL,'<' ; Print "<" call PUTCHAR mov NR,0 ; Reset all the flags mov NS,0 mov INFO_FLAG,0 mov AL,FRAME_TYPE cmp AL,UI je UI_FRAME MOV ECX,0 RET UI_FRAME: mov EBX,OFFSET UI_MSG call NORMSTR ;----------------------------------------------------------------------------; ; If Version 2 Then display P/F C/R Information ; ;----------------------------------------------------------------------------; cmp VERSION_NO,2 jne NOT_VERSION_2 mov AL,' ' call PUTCHAR mov AL,COMM_RESP ; Print Command/Response Flag call PUTCHAR cmp POLL_FINAL,0 je NO_POLL_FINAL mov AL,' ' call PUTCHAR mov AL,POLL_FINAL ; Print Poll/Final Flag if Set call PUTCHAR NO_POLL_FINAL: NOT_VERSION_2: mov AL,'>' call PUTCHAR ;----------------------------------------------------------------------------; ; Find the PID if an information frame ; ;----------------------------------------------------------------------------; mov AL,0 lea ESI,MSGPID[ESI] lodsb mov PID,AL MOV ECX,FRAME_LENGTH ;----------------------------------------------------------------------------; ; Display the rest of the frame (If Any) ; ;----------------------------------------------------------------------------; mov AL,':' call PUTCHAR XOR AL,AL ; IN CASE EMPTY sub ECX,23 JZ NO_INFO ; EMPTY I FRAME JNS @F ; Length Negative PUSH EAX push edi mov [edi],0 ; Null Terminate JMP NO_INFO @@: ; ; PUT TEXT ON A NEW LINE ; PUSH ECX MOV AL,0DH PUSH ESI CALL PUTCHAR POP ESI POP ECX cmp ECX,257 jl LENGTH_OK mov ECX,256 LENGTH_OK: push ECX lodsb call PUTCHAR ; APRS requires all chars to be passed pop ECX loop LENGTH_OK NO_INFO: ; ; ADD CR UNLESS DATA ALREADY HAS ONE ; CMP AL,CR JE NOTANOTHER mov AL,CR call PUTCHAR NOTANOTHER: MOV ECX,EDI SUB ECX,SAVEDI RET PUTCHAR: STOSB 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 EDI ; SAVE BUFFER PUSH ESI ; SAVE MOV EDI,OFFSET NORMCALL MOV ECX,10 ; MAX ALPHANUMERICS MOV AL,20H REP STOSB ; CLEAR IN CASE SHORT CALL MOV EDI,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 ESI ADD ESI,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 [EDI],'-' INC EDI CMP AL,10 JB CONVAX70 SUB AL,10 MOV BYTE PTR [EDI],'1' INC EDI CONVAX70: ADD AL,30H ; CONVERT TO DIGIT STOSB CONVAX90: MOV ECX,EDI SUB ECX,OFFSET NORMCALL MOV NORMLEN,ECX ; SIGNIFICANT LENGTH TEST AH,1 ; LAST BIT SET? POP EDI RET _TEXT ENDS END