# WildPackets Decoder Reference

## Doc version 5.2.0.0, updated 7/21/03

### for EtherPeek v5.1, EtherPeek NX v2.1, GigaPeek v1.0 or higher

## Table of Contents

Introduction
Overview
| Instructions
| Global Variables
| Local Variables
| The Previous Test
| String Arrays
File Formats
Threaded Decoding
| Super Globals
Examples
| Creating Your Own Decoders
| New 802.2 LSAP Types
| New SNAP Types
| New IP Types
| New TCP Types
| New UDP Types
Decoder Instructions
Data Formats
| Data Format Representation
| Data Location Field
| Data Style Field
Label Format Representation
| Label Newline Field
| Label Location Field
| Label Style Field
Instruction Index

## Introduction

This document is a guide to WildPackets' language for decoding packets in the Peek products. The language described here enables our customers to extend the decoders we have provided or to create new ones. We have devised a simple, interpreted language designed specifically for displaying network frames for several media types. The language includes instructions for displaying data, controlling the sequence of instructions, manipulating data values, and conditional execution. The format of decoder files, a detailed description of each instruction and its effects, and the tools needed for creating decoder files are discussed.

## Overview

The decode of a protocol is accomplished through a collection of decoders. Each decoder is uniquely named and contains a sequence of decode instructions. An important part of the decoding process is the ability of decoders to link to other decoders. This allows a modular design, and eliminates the need for duplication of decoders for the decoding of different packets with the same first layers. Decoders of one file may use decoders of others.

The decoding process follows the layers of the protocols from the bottom layer to the top, and as layers are encountered, decoders will call other decoders and relinquish the decoding task to them. There is some strong presumption that the bottom layers appear first in the packet although there is some ability to handle the decoding when this is not exactly the case.

Each decoder is a combination of one or more decoding instructions. Most instructions are composed of a decode instruction, a value, some option fields, and a string. When the user decides to decode a packet, the decode manager is called with a pointer to the first byte of the packet. As decode instructions are encountered and executed, this pointer is incremented as dictated by the instruction type, in preparation for the next instruction. Packet data that is processed by the instruction may be saved for later use in global or local variables.

Stated another way, the pointer to the data in the packet and a decoder instruction operate on one or more bytes in the packet and the pointer moves along correspondingly. In some cases, an instruction may operate only on bits within a byte.

When the decode manager runs out of instructions, it will display the rest of the packet in a generic data format. Depending on the media type, the last of the remaining bytes are reserved for the FCS (4 bytes, Ethernet or Wireless), or not (0 bytes, Token Ring). If the decode manager runs out of packet data before exhausting the instructions an error message is displayed, notifying the user that not enough bytes were available. Nevertheless, using the different patterns of instructions, it is still possible in some cases to scan beyond the end of the packet or to create infinite loops so some caution should be exercised.

## Instructions

A decoder is a sequence of one or more instructions. A typical instruction has a type, a value, an option, a data style, a label style, and a string (that may be empty).

Type | A four character code identifying the decoder instruction.
Value | A signed 32-bit value. The two high bits are used to provide options for certain instructions.
Global | A signed 32-bit value. The 26 high bits are used to provide options for certain instructions. The low 5 bits represent the index of a global variable.
Data Style | A 1-byte value containing fields for text location and style.
Label Style | A 1-byte value containing fields for text location, style, and a new line option.
String | An ASCII string to be used as a label or the name of another decoder or a string array.

Fundamentally, a single decoder instruction is intended to provide enough information to yield a label and a value after that label. The decode instruction also includes formatting information about both the label and data parts. Of course, there is no requirement to do both a label and data portion in each instruction and there are some decoder instructions that just operate on the data without displaying either a label or data, or instructions which just control the flow of instructions: test and branch, subroutine call, etc.

## Global Variables

The decoders have access to 32 long word (32-bit) global areas, where they may save information for later use. There is also one implicit Boolean global, for use in test instructions. These globals provide the ability to interpret data in later parts of a packet, in accordance to values in earlier bytes of that packet.

### Global Variable Format Representation

Bit(s) | Meaning
--- | ---
0x00000040 | Local bit on global
0x00000080 | Register bit on value;
0x00000100 | Previous Test bit (TEQU family only)
0x00080000 | Constant value bit
0x0FF00000 | Number of bits to skip
0x20000000 | Skip bit
0x40000000 | Branch bit
0x80000000 | Debugger break

## Local Variables

The decoders have access to 32 long word (32-bit) local variables, where they may save information for later use inside a particular decode. These local variables provide the ability to use data from earlier parts of a decode. To use a local, instead of setting the Most Significant Bit(MSB), you will instead set the 2nd MSB. See example below, which adds 3 to the local variable 2. **Note: You can only move global variables to local variables.

    ADDG 3 42;		* add 3 to local 2
    ADDG 3 82;		* add global 3 to local 2
    ADDG 40000003 c2;		* add local 3 to local 2

As indicated by any given instruction, the global field will determine which local to use in the operation. For example, after reading two bytes of the packet, you may wish to store it in local number 3, for use later, like the example above.

## The Previous Test

Several decoder instructions perform tests to be used in other conditional instructions. For example, one instruction may compare packet data to a value or a value to a global and then a subsequent instruction will conditionally display a string or branch to another decoder. The decoder mechanism keeps track of the status of tests. See the table of instruction descriptions for instructions that take advantage of this feature. Here is an example:

    void Test;
      MOVE 2 1;		* move 2 into g2
      SEQU 2 1;		* is 2 == g1 ?
      SKIP 1;
        LABL -They are not equal;
      TRTS;

Below is a variation of the example using ENDS instead of specifying the actual number to skip:

    void Test;
      MOVE 2 1; 		* move 2 into g2
      SEQU 2 1; 		* is 2 == g1 ?
       SKIP;
        LABL -They are not equal;
       ENDS;
       TRTS;

And the "coup de grat" is the following example that sets the "skip bit" on the SEQU that instructs it to skip the instructions up to the ENDS instruction. In other words, if the test is true the enclosed block is executed.

    void Test;
      MOVE 2 1;		* move 2 into g2
      SEQU 2 20000001;		* if 2 == g2 ?
        LABL -They are equal;
      ENDS;
      TRTS;

In the above example the skip bit is the 3rd highest significant bit on the global. The skip bit is supported by all of the S* functions including SEQU, SNEQ, SLTE, SGTE, and SBIT.

## String Arrays

The other major component of decoders are string arrays referred to here as "str#" resources (because they're identified by the string "str#"). String arrays are identified by a unique name and are composed of a list of strings located with a 1-based index. Indexed string arrays provide their own index. Decoders can make use of string arrays by extracting data from a packet, possibly doing some arithmetic, and either displaying a string from an array or calling a function specified in an array.

String arrays are identified by the lowercase string "str#" followed by a unique name. Each string in the array appears on a line by itself terminated by a semicolon. Here is an example:

    str# MyStrings;
      String1;
      String2;
      String3;
      ;
      String5;
      String6;

The above string array is accessed in a linear manner. The line with only a semi-colon specifies an empty string entry. A variation of the string array is the indexed string array. This type of str# allows the index of entries to be specified with a hex value of the entry followed by a '|' followed by a string. Here is an example:

    str# MyStrings2;
      1 | String1;
      5 | String5;
      8 | String8;
      9 | String9;

Another variation of the string is the mixed string array which includes indexed and non-indexed entries. Here is an example:

    str# MyBitStr;
      3 | 1... Bit 3 is set;
          0... Bit 3 is not set;
      2 | .1.. Bit 2 is set;
          .0.. Bit 2 is not set;
      1 | ..1. Bit 1 is set;
          ..0. Bit 1 is not set;

The string array in the example above is used with the BST# instruction.

## File Formats

Decoders are stored in text files located in a directory adjacent to the program. Under MacOS, this directory is called "Packet Decoders"; under Windows, simply "Decodes". Individual decoders are identified by the lowercase string "void" followed by a unique name. Individual instructions follow the format: [instruction][value] [global] [data format] [label format] [string], where each element is separated by a tab character or one or more spaces. Each line is terminated by a semicolon. Here is an example:

    void FTP;
      TEQU 0 10 0 30 FTP No Cmd Data;
      TLTE 5dc 10 0 30 FTP No Cmd Data;
      LABL 0 0 0 b1 FTP Control - File Transfer Protocol;
      TNXT 0 0 0 0 FTP Cmd or Reply; **

The same function could also be written as:

    void FTP()
      {
         TEQU( 0, g[0x10], 0, 0x30, "FTP No Cmd Data");
         TLTE( 0x5dc, g[0x10], 0, 0x30, "FTP No Cmd Data");
         LABL( 0, 0, 0, 0xb1, "FTP Control - File Transfer Protocol");
         TNXT( 0, 0, 0, 0, "FTP Cmd or Reply");
      }

In the above example the parameters are enclosed in parenthesis. When parenthesis are used numbers are assumed to be decimals. In order to specify hex prefix numbers with 0x. In order to specify globals and locals use the g[] and l[] arrays.
Lines beginning with an asterisk "*" are ignored and can be used for comments.

**Notes: A dash can be used in place of the four number parameters when they are all equal to zero, i.e.,

    TNXT -FTP Cmd or Reply;

can replace:

    TNXT 0 0 0 0 FTP Cmd or Reply;

The TSUB instruction has become implicit for subroutine calls. It is not necessary to prefix a subroutine call with TSUB anymore. For example, what used to be:

    TSUB 0 0 0 0 Foo;

or:

    TSUB -Foo;

can also be simply:

    Foo;

Specifying TSUB will still work but is not necessary.

Assignments and math on locals and globals can be done using the following syntax:

    g[1] = 1;
    l[1] = 2;
    g[4] = l[4];
    l[3] = g[6];

    g[1] += 1;
    l[1] += 2;
    g[4] += l[4];
    g[7] += g[6];
    l[3] += g[6];
    l[3] += l[6];

    g[1] *= 0;
    l[2] /= 2;
    g[3] %= 1;
    g[4] &= l[4];
    g[5] |= 5;

Tests on locals and globals can be done using the following syntax:

    if g[2] == 1 {
      LABL 0 0 90 c2 "g[2] == 0";
    }

    if g[2] == l[2] {
      LABL 0 0 90 c2 "g[2] == l[2]";
    }

    if l[1] == g[1] {
      LABL 0 0 90 c2 "l[1] == g[1]";
    }

Tests can also be nested:

    if g[1] <= l[2] {
      LABL 0 0 90 c2 "g[1] <= l[2]";

      if g[2] <= l[1] {
        LABL 0 0 90 c2 "g[2] <= l[1]";
      }
    }

Packet data can be accessed in the following ways:

    g[1] = pb[1];		* means GBYT 1 1;
    g[1] = pb[0];		* means GBYT 0 1;
    g[1] = pw[0];		* means GWRD 0 1;
    g[1] = pl[0];		* means GLNG 0 1;
    l[1] = pl[0];		* means GLNG 0 41;

In the above examples 'p' stands for packet, 'b' for byte, 'w' for word, and 'l' for long

## While Loops

The following is example of while loops:

    void main()
    {
      g[1] = 0;
      while (g[1] < 5)
      {
        g[1] += 1;
        DGLB( 0, g[1], 0x90, 0xc2, "g[1]:");
      }

      g[1] = 5;
      while (g[1] > 0)
      {
        g[1] -= 1;
        DGLB( 0, g[1], 0x90, 0xc2, "g[1]:");
      }
    }

## Threaded Decoding

Packets usually contain the information needed to decode them into their protocol components. However, some protocol stacks use transactions in the form of a request packet followed by a response packet and the response packet does not contain any information about the type of request to which is responding. For example, in AFP (the AppleTalk File Protocol), a request will be made to get information about a file, and the response will contain the requested information, but the response packet does not identify itself as being the answer to a file information request. Because of the lack of information in the response packet, it could just as easily be interpreted as a response to a get volume parameters request. As a solution to this problem, the decoder language contains the WHOA instruction. This instruction takes the name of an indexed string as its string parameter. Each name in the string array is a choice of how to decode the next portion of the packet and this name is also the name of the decoder to be used. These choices are presented to the user in a dialog and the value field contains a number that is the index of the default choice that is highlighted in the list.

With this as the basis, it should be clear that the user must manually select a decode choice for those protocols that do not identify their responses. As an implementation detail, the program tends to remember the last choice selected and uses that one again for subsequent packets. However, such inference is often incorrect.

To extend the capabilities of the decoders, an additional mechanism was added that is referred to here as threaded decoding. First, the MARK instruction is added so that when a request packet is encountered, the packet is "marked" with the relevant information; in particular, the type of response that will be subsequently expected. Then, when the WHOA instruction is encountered at some later packet, the WHOA instruction checks to see if there is a marked packet that tells it how to decode the current packet. If so, the user is NOT prompted for input, but instead it is assumed that the decoding should be done as the previous MARK instruction indicated.

To clarify and illustrate the mechanism, consider the following example. A certain protocol sets up a socket-to-socket connection. Requests are made and non-request identifying responses are given. In the implementation of the protocol, the response is directed to the requester to a socket number that is unique on the requester's node. To write a decoder program for this situation, during the decode of the request the MARK instruction is processed. The string field of the MARK instruction contains the name of a string array that contains the names of all the possible response types. The value field tells which option is the correct one for this request. The source socket number is contained in a global variable and this global is passed to the MARK instruction. In processing the MARK instruction, the name of the string array (the str#), the choice of which item to use in the array, the number of the packet and the socket number passed in the global variable are stored together in LIFO memory, a.k.a., a cache.

In writing a decode program for the response, at the appropriate point where different types for the response are possible, the WHOA instruction is called. The string field of the WHOA instruction contains the name of a string array that contains the names of the all the possible response types. The value field tells which of these options is the default. The destination socket of the response has been saved in a global variable. In processing the WHOA instruction, the cache is searched for a match of both the socket number value contained in the global and the string array name. If a match is found, the choice from the possibilities, as stored in the cache by the MARK instruction, is used to decode the next portion of the packet. Moreover, if the WHOA instruction contains the number of a global variable in the high 8 bits of the value field, that global will get the number of the packet that contained the request placed into its value. If there is a match in the cache, execution continues with the designated decoder. If there is no match and the user makes a choice from those presented, execution continues with the corresponding chosen decoder. In all other cases, including when cancel is chosen, execution continues with the instruction following the WHOA instruction. Please see example below:

Mark and Whoa code example
1) Open decodes.dcd
2) Search for void SNMP

    void SNMP;
         ASN1_Init;
         MOVE 0 11;  *enum testing is off
         LABL  0  0  0 b1 SNMP - Simple Network Management Protocol;
         WHOA  0  1  0  0 SNMP Exp Opt;
         WHOA  0  2  0  0 SNMP Exp Opt;
         SEQU a1  1;
         SKIP  5  0;
         SEQU a2  1;
         SKIP  3  0;
         MARK  2  2  0  0 SNMP Exp Opt;
         WHOA  0  2  0  0 SNMP Exp Opt;
         TNXT -Summary SNMP Fields;
         MARK  2  1  0  0 SNMP Exp Opt;
         WHOA  0  1  0  0 SNMP Exp Opt;
         TNXT -Summary SNMP Fields;

3) Notice MARK on line 11. It translates to MARK this packet as a possible help for a following packet, use the string array SNMP Exp Out to figure out the next possible decode. The value field tells which string to use based on the value global field, which is 2; later if this value in the global is matched, then it will use the decode specified in the string array at position 2. It then stores this in a LIFO(Last In First Out) cache.
4) Notice WHOA on line 12. It translates to decode this packet based on information from a previous packet. Check global location 2 and see what value is there. If the value indexes to a string in the given string array, SNMP Exp Out, then jump to that named decoder.

Another MARK and WHOA code example
1) Open decodes.dcd
2) Search for void TCP::Ports

    void TCP::Ports()
    {
    	MOVE  0   9;
    	WHOA  0   2 0 0 Alternate Decoders;
    	WHOA  0   2 0 0 H323_Decoders;
    	WHOA  0   2 0 0 MegacoText::Str;
    	WHOA  0   2 0 0 SIP::MW_List;
    	MOVE  1   9;

    	TSB#  0   2 -TCP::Ports_Str;

    	SKIP 1;
    	MOVE    2 9;     // g[9]==2 means we did not find a match
    }

3) Notice the third WHOA. It refers to MegacoText::Str. If you search for str# MegacoText::Str, you'll find that there is only one entry for this list. This is because in the beginning of the Megaco request, it marks the port as the valid Megaco port. This is done because Megaco can switch ports depending on which thread you are viewing. So, when there is a MARK, global 2 contains the port number that Megaco currently runs on. In that case, when there is a WHOA, it can check against that MARK to see if Megaco is a valid entry. If it is a valid entry, it will use the MARK's value field to determine which decoder function to branch off to [in this case, MegacoText is specified].

One last example of MARK and WHOA seen in the Novell decodes.
1) Open decodes.dcd
2) Search for void NCP Reply.

    void NCP Request;
    	GWRD 0 b;
    	DBYT 0 14 90 c2 Sequence number:;
    	...

    void NCP Reply;
    	GWRD 0 b;
    	DBYT 0 14 90 c2 Sequence number:;
    	...
    	WHOA 0 14 0 0 NCP::Type_17::MW_List;
    	WHOA 0 14 0 0 NCP::Type_21::MW_List;
    	WHOA 0 14 0 0 NCP::Type_22::MW_List;
    	WHOA 0 14 0 0 NCP::Type_23::MW_List;
    	WHOA 0 14 0 0 NCP::Type_32::MW_List;
    	WHOA 0 14 0 0 NCP::Type_34::MW_List;
    	WHOA 0 14 0 0 NCP::Type_35::MW_List;
    	WHOA 0 14 0 0 NCP::Type_36::MW_List;
    	WHOA 0 14 0 0 NCP::Type_86::MW_List;
    	WHOA 0 14 0 0 NCP::Type_87::MW_List;
    	WHOA 0 14 0 0 NCP::Type_90::MW_List;
    	WHOA 0 14 0 0 NCP::Type_104::MW_List;
    	WHOA 0 14 0 0 NCP::Type_111::MW_List;
    	WHOA 0 14 0 0 NCP::Type_114::MW_List;
    	WHOA 0 14 0 0 NCP::Type_123::MW_List;
    	WHOA 0 14 0 0 NCP::Type_131::MW_List;
    	WHOA 0 14 0 0 NCP::Type_Loners::MW_List;
    	WHOA 0 b 0 c2 Adv NW Rep Opt;
    	TNXT -NW Reply Any Left;

3) The beginning few lines were taken out, but notice a long list of WHOA's. Novell Core Protocol works by having the request specify what the response will be and it also can contain information that the response will need in order to decode the packet properly.
a) Notice also in the second line of both void NCP Request and void NCP Reply, the line "DBYT 0 14 90 c2 Sequence Number." That is the value that is used in the MARK and the WHOA. So dependent on the sequence number, the MARK and WHOA will check the value in global 14 to confirm if it is valid or not.
b) The next step is to MARK all of the request packets that can have a response. Search for void NCP::Type_22::52. At the beginning of the function, you'll find:

    void NCP::Type_22::52;
    	MARK 34 14 0 0 NCP::Type_22::MW_List;
    	...

    str# NCP::Type_22::MW_List;
    	 1 | NCP::Type_22::01R;
    	 2 | NCP::Type_22::02R;
    	 5 | NCP::Type_22::05R;
    	 6 | NCP::Type_22::06R;
    	12 | NCP::Type_22::12R;
    	...
    	51 | NCP::Type_22::51R;
    	52 | NCP::Type_22::52R;

It MARKS to use the 52th number [0x34 == 52 decimal] specified in the list.
c) To summarize, MARK will save global 14 [sequence number] to be checked on the WHOA as well as the value field [0x34] to be used as an index to the list of responses. When the WHOA is called, if global 14 matches, then it will use the MARKed value field to branch to the correct decoder.

### Super Globals

Another way to use threaded decoding is to use super globals. These are used to carry information from one packet to the next. For example, let's say that a request packet uses flags to determine what type of response is needed. The response packet would then need the value of those flags to be able to decode it properly. Previously, that was a limiting factor in the decodes. With super globals, such information from one packet may be carried to the next.

An example using Super Globals

    Request:
    	...
    	DLNG 40000000 1 90 c2 Volume Request Flags:;
    	 CEQU 0 1 0 14 Return the volume name with the volume number;
    	 CEQU 1 1 0 14 Do not return the volume name with the volume number;
    	s[1] = g[1];			// save the global 1's value in the super global
    	...

    Response:
    	...
    	DLNG 0 1 90 c2 Next Volume Number:;
    	g[1] = s[1];			// get the super global's value in global 1
    	if (g[1] == 0)
    	{
    		NCP::VolMntStructWithName;
    	}
    	if (g[1] != 0)
    	{
    		NCP::VolMntStruct;
    	}
    	...

Depending on what the value for the Volume Request Flags are in the request, the response will give a Volume Struct with a name or without a name. The super global saves what's in global 1 in the request and is able to use it in the response.

### Examples

Decoder programming is much like assembly language programming with very long assembly instructions. The following examples serve to illustrate how we have programmed the decoding of some of the protocols.

This is a typical, simple decode instruction:

    HWRD 0 2 90 c2 Checksum:;

This instruction translates to: decode the next 16 bits as hexadecimal, the high order bit of value is zero so prepend a "0x" (ignore remaining bits in value), store the 16 bits in global variable number 2, and format the display as: new line, label at column 2, in data label style, with the given string, data in plain style beginning at column 24.

Here is another example:

    HBYT 0 1 90 c2 AppleTalk Type:;
    CEQU 1 1 0 14 Short DDP;
    TTST 0 0 0 0 Short DDP;
    CEQU 2 1 0 14 Long DDP;
    TTST 0 0 0 0 Long DDP;

These instructions do the decoding of the byte that contains the LAP type in an AppleTalk DDP packet. After displaying the value in hexadecimal, a translation string of "Short DDP" or "Long DDP" is displayed in the message style if the LAP type is equal to 1 or 2 respectively. Further, if either the type is 1 or 2, decode execution switches to a decoder named "Short DDP" or "Long DDP" respectively.

The best source of examples is the decoders we've provided with the product. If you're using Microsoft Windows you can view the decoders with a text editor such as NotePad or WordPad. If you're using MacOS you can view the decoders with a text editor such as BBEdit.

## Creating Your Own Decoders

Remember, your decoder and string arrays should be uniquely named over the set of all decoder files. If you fail to do this, it is not a fatal problem, but it can be confusing because, most likely, only the first occurrence of an item will be found. Many protocol stacks have names or acronyms that are exactly the same. Choose your decoder names judiciously. Also, old decoder files must be moved out of the directory tree of the application.

Inevitably, you will need to link your decoders into the parsing stream of the decoder mechanism by changing at least one of the existing decoder files. Here are some hints for commonly used control points.

### New 802.2 LSAP Types

1. Make a copy of the "decodes.dcd" file as a backup and move it to a safe place.
2. Open the original file.
3. Locate the last instruction in the "LSAP::Names" decoder which is a "TRTS".
4. Add a new "CEQU" instruction immediately before the last "TRTS" instruction.
5. Edit the instruction value to be the hexadecimal value of the new LSAP.
6. Edit the instruction string to be the name of the new 802.2 type.
7. Base the rest of the instruction on preceding "CEQU" instructions.
The next steps add the jump point to the new LSAP type. Usually there are two possibilities: two jump points, (one for the DSAP and one for the SSAP) or one jump point which requires that both the DSAP and SSAP have the same new value.
8. Locate the decoder called "802_2::Common".
9. Go to the bottom of the decode "802_2::Common", you will see a "802_2::Data", this is a branch instruction similar to:

    TSUB 0 0 0 0 802.2 Data;

or

    TSUB -802.2 Data;

Follow the the branch to the new decode "802_2::Data".
10. Locate the last instruction in the "802_2::Data" decoder which is a "DUMP".
11. If you want two jump points on either LSAP, add two "TEQU" instructions before the last "DUMP" instruction. One "TEQU" will test global 1 and the other will test global 2. Look above in the decode at the handling of 802.2 SNA for an example (instructions number 15 and 16).
12. If you want one jump point, only if the DSAP and SSAP are both the new LSAP value, then add an "SEQU" and a "TEQU" instruction before the last "DUMP" instruction. The "SEQU" instruction will test global 1 and set the previous test flag and the "TEQU" instruction will test global 2 and, using a special option (setting the high bit in the global column) for the "TEQU" instruction, branch to the named decoder if the values match to globals. Look above at the handling of IP for an example.
13. Edit the values for the instructions you added.
14. Edit the strings for the instructions you added to be the name of the new decode to handle the new LSAP.
15. Save and close the file.

### New SNAP Types

1. Make a copy of the "decodes.dcd" file as a backup and move it to a safe place.
2. Open the original file.
3. Locate the decoder called "SNAP::Names".
4. Locate the last instruction in the "SNAP::Names" decoder which is a "TRTS".
5. Add a new "CEQU" instruction before the "TRTS".
6. Edit the instruction value to be the hexadecimal value of the new SNAP.
7. Edit the instruction string to be the name of the new SNAP type.
8. Base the rest of the instruction on preceding "CEQU" instructions.
9. Locate the decoder called "SNAP".
10. Locate the last "TEQU" instruction.
11. Add a new "TEQU" instruction after the

    TEQU 80c5 2 0 0 VINES Echo;

instruction.
12. Edit the instruction value to be the hexadecimal value of the new SNAP.
13. Edit the instruction string to be the name of the new jump point, the decoder that decodes the new SNAP type.
14. Base the rest of the instruction of preceding "TEQU" instructions.
15. Save and close the file.

### New IP Types

1. Make a copy of the "decodes.dcd" file as a backup and move it to a safe place.
2. Open the original file.
3. Locate the decoder called "IP Common".
4. Add a new "TEQU" instruction at the top.
5. Edit the instruction value to be the hexadecimal value of the new IP type.
6. Edit the instruction string to be the name of the new decoder that handles the IP type.
7. Save and close the file.

### New TCP or UDP Types

1. Make a copy of the "decodes.dcd" file as a backup and move it to a safe place.
2. Open the original file.
3. Locate the decoder called "TCP::Ports_Str".
4. Add a new entry above the first entry which should be

    0x7 | Echo;

that will test the source port number stored in global 2.
5. Edit the instruction value to be the hexadecimal value of the new TCP or UDP type.
6. Edit the instruction string to be the name of the new decoder that handles the TCP or UDP type.
7. Examine subsequent instructions until you find them repeated. These instructions are testing the destination port number stored in global 2.
8. Add a new entry below your previous entry that will test the destination port number stored in global 2.
9. Edit the instruction value and string just as before.
10. Save and close the file.

If your decoder work has value to other users of our products, we would be happy to distribute your decoders along with our own, giving you credit for your work.

## Decoder Instructions

Instruction | Value | Global | Increment | Description
--- | --- | --- | --- | ---
ADDG | Value to add. | Global to store result. If the high bit of the global is on then add value numbered global to global, i.e., global[glob_num] += global[value] instead of global[glob_num] += value. | Add value to a specified global. | 0
ANDG | Value to AND. | Global to AND. If the high bit of the global is on then and value numbered global with global, i.e., global[glob_num] &= global[value] instead of global[glob_num] &= value. | 0 | Logical AND value and a specified global.
AT01 | If value is zero, the name table search will be made using zero as a net work number or as a LLAP address type depending on the media type. If value is set to 1, the search will be made assuming that the pointer is at the destination node address in a long DDP packet and it will look for the net number backwards accordingly. If value is set to 2, the search will be made assuming that the pointer is at the source node address in a long DDP packet and it will look for the net number backwards accordingly. | Result displayed is stored in this global. | 1 | AppleTalk 1 byte node number. Display as an AppleTalk address. Also an attempt is made to find that node in the name table.. If a match is made, then the name will be displayed.
AT03 | not used | Result displayed is stored in this global. | 3 | AppleTalk 3 bytes. Display as an AppleTalk address. An attempt is made to find that address in the name table. If a match is made, then the name will be displayed.
ATLG | not used | Result displayed is stored in this global. | 4 | AppleTalk long. Display as an AppleTalk address. An attempt is made to find that address in the name table. If a match is made, then the name will be displayed.
BBIT | Number of bits. Second highest bit signifies to use LSB order. | Result displayed is stored in this global. | Value number of bits. | Display bits as binary.
BBYT | not used | Result displayed is stored in this global. | 1 | Display byte as binary.
BGLB | not used | Global to display. | 0 | Display a global in binary format.
BITO | not used | bit offset from byte is stored in this global location. | 0 | Get bit offset.
BLNG | not used | Result displayed is stored in this global. | 4 | Display a 32-bit integer in binary format as 32 binary digits with a leading '%' sign.
BREM | not used | Number of bytes remaining is stored in this global location. | 0 | Get number of remaining bytes of packet.
BST# | Value to subtract from global | Global to test bits specified in indexed string array with. | 0 | A str# resource with the following string name is loaded and the indexes in the entries are used as bit positions to test against the global. For each entry if the bit is the string is displayed, otherwise the string in the next is displayed if the next entry is an un-indexed entry.
BWRD | The second highest bit commands a byte swap (INTEL format). | Result displayed is stored in this global. | 2 | Display a 16-bit integer in binary format as 16 binary digits with a leading '%' sign.
BYTO | not used | Byte offset from start of packet is stored in this global location. | 0 | Get byte offset.
CBIT | Value to check against global. | Global to check against value. If the global has the high bit set then the previous test must also be true before displaying the string. | 0 | Test bit indicated by value in the specified global and if set then the string is displayed. Bit numbers start with zero as the least significant bit.
CEQU | Value to check against global. | Global to check against value. If the global has the high bit set then the previous test must also be true before displaying the string. | 0 | Test value against a global. The string is displayed if equal.
CGTE | Value to check against global. | Global to check against value. If the global has the high bit set then the previous test must also be true before displaying the string. | 0 | If value is greater than or equal to the specified global then the string is displayed. If the instruction global has the high bit on then the previous test must also be true before displaying the string. (ie. global <= value)
CHR# | If no global is specified, value is used for number of bytes to display. High bit signifies display as 7-bit ASCII, i.e., ignore the high bit of each byte. | If specified, global is used determine how many bytes to display. | Value or global | Display bytes as printing characters using ASCII.
CKSM | Value 1 indicates an AppleTalk DDP checksum. Value 2 indicates an IPv4 header checksum. Value 3 indicates a TCP, UDP, ICMP, or IGMP checksum. | not used | 0 | Verify checksums for various packet types and displays the correct checksum if the value contained in the packet is incorrect.
CLTE | Value to check against global. | Global to check against value. If the global has the high bit set then the previous test must also be true before displaying the string. | 0 | If value is less than or equal to the specified global then the string is displayed. (ie. global >= value)
CLSE | not used | not used | 0 | If the most recent test is false display the string.
CNEQ | Value to check against global. | Global to check against value. If the global has the high bit set then the previous test must also be true before displaying the string. | 0 | Test value against a global. The string is displayed if not equal.
CRLF | not used | not used | 0 | Insert a return or new line.
CST# | Value to subtract from global | Index into string resource | 0 | A str# resource with the following string name is loaded and an index (in a global) is used to get the string to be displayed. If there is a value it is subtracted from the global. If there is no such string then nothing happens, and the test result is set to false.
CSTR | High bit signifies display as 7-bit ASCII, i.e., ignore the high bit of each byte. Second highest bit signifies that the string is in UNICODE. | Length of the string (not including NULL terminator) is stored here. | Length of the string plus 1 for NULL terminator. | Display a C-style string. The string in terminated by a null character (byte value zero).
D64B | High bit signifies whether to display as signed. The second highest bit commands a byte swap (INTEL format). | Result displayed is stored in this global. | 8 | Display a 64-bit integer in decimal format. If the high bit of value is on then the data is displayed as a signed decimal, rather than unsigned. The second highest bit commands a byte and word swap (INTEL format).
DBIT | Number of bits. High bit signifies to display as signed number. Second highest bit signifies to use LSB order. | Result displayed is stored in this global. | Value number of bits. | Display bits as decimal.
DBYT | High bit signifies to display as signed. | Result displayed is stored in this global. | 1 | Display byte as decimal.
DECR | If no global specified, the number of bytes to decrement by. | If specified, holds the number of bytes to decrement by. | Negative Global or Value number of bytes. | Decrement the packet pointer by the global, or value, skipping backwards by the number of bytes specified.
DGLB | High bit signifies whether to display as signed. | Global to display. | 0 | Display a global in decimal format.
DIVG | Value to divide by | Global to store result. If the high bit of the global is on then divide value numbered global by global, i.e., global[glob_num] /= global[value] instead of global[glob_num] /= value. | 0 | Divide specified global by value.
DLNG | High bit signifies whether to display as signed. The second highest bit commands a byte swap (INTEL format). | Result displayed is stored in this global. | 4 | Display a 32-bit integer in decimal format.
DMPE | If value is 0, dump all the remaining bytes if the packet. If value is 1, leave enough bytes for CRC. Any other value means to output that number of bytes. | If specified, output the number of bytes contained within this global. | Number of bytes output | Display data in both hex and EBCDIC, side by side. Number of bytes is either in a global if specified, or in value, or is to the end of the packet.
DUMP | If value is 0, dump all the remaining bytes if the packet. If value is 1, leave enough bytes for CRC. Any other value means to output that number of bytes. | If specified, output the number of bytes contained within this global. | Number of bytes output | Display data in both hex and ASCII, side by side. Number of bytes is either in a global if specified, or in value, or is to the end of the packet.
DWRD | High bit signifies whether to display as signed. The second highest bit commands a byte swap (INTEL format). | Result displayed is stored in this global. | 2 | Display a 16-bit integer in decimal format.
EBC# | If no global is specified, value is used for number of bytes to display. High bit signifies display as 7-bit EBCDIC, i.e., ignore the high bit of each byte. | If specified, global is used determine how many bytes to display. | Value or global | Display bytes as printing characters using EBCDIC.
ENDS | not used | not used | 0 | End a SKIP block
ETHR | not used | not used | 6 | Six bytes as an Ethernet address. An attempt is made to translate the address into a DECnet address. Also an attempt is made to find that address and/or DECnet address in the name table. If a match is made, then the name will be displayed.
FCSC | not used | Result (checksum) is stored in this global location. | 0 | Calculates checksum based on packet media type.
FTPL | Value 1 is for use with FTP, SMTP, and POP style replies. Value 3 is for TELNET style command and data. | not used | Number of bytes output | Display data in both hex and ASCII, side by side. Number of bytes is determined by scanning for a command delimiter. Value 0 is for use with FTP, SMTP and POP style requests.
GBIT | Number of bits to retrieve. | Global location to store retrieved bits. | 0 | Take the number of bits specified in value and place them in the specified global without incrementing the packet pointer or displaying any information.
GBYT | Byte offset from current location in packet. | Global location to store retrieved byte. | 0 | Put a byte in the specified global without incrementing the packet pointer or displaying any information.
GLNG | Byte offset from current location in packet. | Global location to store retrieved long. | 0 | Put a 32-bit integer in the specified global without incrementing the packet pointer or displaying any information.
GSTR | If the 3rd highest bit is set, it specifies to use the value as the value to be searched for. If nothing is specified, the default value searched for will the NULL. | Byte offset from packet location up to where it found the value specified. | 0 | Get string length.
GWRD | Byte offset from current location in packet. | Global location to store retrieved word. | 0 | Put a 16-bit integer in the specified global without incrementing the packet pointer or displaying any information.
HBIT | Number of bits. High bit signifies not to prepend "0x". | Result displayed is stored in this global. | Value number of bits. | Display bits as hex.
HBYT | High bit signifies not to prepend "0x". | Result displayed is stored in this global. | 1 | Display byte as hex. Also useful for display or tests of greater than 4 bytes, where results have to be loaded in different globals.
HEX# | If no global is specified, value is used for number of bytes to display. High bit signifies whether to prepend "0x". | If specified, global is used determine how many bytes to display. | Value or global | Display bytes as hex.
HGLB | High bit signifies whether to prepend "0x". | Global to display. | 0 | Display a global in hexadecimal format.
HLNG | High bit signifies whether to prepend "0x". The second highest bit commands a byte swap (INTEL format). | Result displayed is stored in this global. | 4 | Display a 32-bit integer in hexadecimal format.
HWRD | High bit signifies whether to prepend "0x". The second highest bit commands a byte swap (INTEL format). | Result displayed is stored in this global. | 2 | Display a 16-bit integer in hexadecimal format.
INCR | If no global specified, the number of bytes to increment by. | If specified, holds the number of bytes to increment by. | Global or Value number of bytes. | Increment the packet pointer by the global, or value, skipping ahead by the number of bytes specified.
IPLG | not used | Result displayed is stored in this global. | 4 | Display an IPv4 address. An attempt is made to find that address in the name table. If a match is made, then the name will be displayed.
IPV6 | not used | not used | 16 | Display an IPv6 address. An attempt is made to find that address in the name table. If a match is made, then the name will be displayed.
LABL | not used | not used | 0 | A label only. The instruction string is used as a label and is displayed. The packet pointer is not incremented.
LSTS | not used | not used | 0 | List start. If a string is provided, a count will be appended to it and displayed. The count will be incremented. Count starts at 1.
LSTE | not used | Indicates end of list if greater than or equal to list count. | 0 | List end. Execution returns to the last LSTS, unless global is less than or equal to the count.
LSTZ | not used | Indicates end of list unless it's less than or equal to zero. | 0 | List end. Execution continues at the last LSTS unless global is less than or equal to zero.
MARK | Index of string within the str# designated by the string field to use in future WHOA. | Contains the reference point for linking request and response packets, usually transaction ID or port # etc. Entered into the cache with packet number and value and string fields. | 0 | MARK a value and this packet number for later usage in the WHOA instruction by logging the relevant parameters in a cache. See the more detailed overall explanation of MARK and WHOA threading, above.
MODG | Value to mod by. | Global to store result. If the high bit of the global is on then modulus value numbered global by global, i.e., global[glob_num] %= global[value] instead of global[glob_num] %= value. | 0 | Modulus specified global by value.
MOVE | not used | If the high bit of the instruction global is set then put value-numbered global into global. | 0 | Put value (or value contained within a global) in a specified global without incrementing packet pointer.
MULG | Value to multiply by. | Global to store result. If the high bit of the global is on then multiply value numbered global by global, i.e., global[glob_num] *= global[value] instead of global[glob_num] *= value. | 0 | Multiply value and a specified global.
NBNM | not used | 16th byte of the decoded name (the resource or service code) is stored in this global. | Length of the name | Display NetBIOS (reversible half-ASCII) name.
NOTG | Value to NOT. | Global to store result. If the high bit of the global is on then store value numbered global into global, i.e., global[glob_num] ~= global[value] instead of global[glob_num] ~= value. | 0 | Logical NOT a specified global.
ORRG | Value to OR. | Global to OR. If the high bit of the global is on then store value numbered global into global, i.e., global[glob_num] |= global[value] instead of global[glob_num] |= value. | 0 | Logical OR value and a specified global.
OSTP | not used | Result displayed is stored in this global. | 4 | 4 bytes displayed as characters.
POPX | not used | Value popped from stack is stored in this global. | 0 | Pops one value from the stack and stores the value in the global specified.
PORT | If value is set to 0, a 2-byte field is displayed as a TCP/UDP port. If value is set to 1, a 2-byte field is displayed as a NetWare port. | Result displayed is stored in this global. | 2 | Used to display a port field. If value is set to 0, a 2-bit field is displayed as a TCP /UDP port. If value is set to 1, a 2-bit field is displayed as a Netware port. In any of the above cases, also try to find a match in the name table, and display the name if found.
PRTO | If value is set to 1, a 2-byte field is displayed as an unsigned 16-bit integer depicting Ethernet Type II protocol type. If value is set to 2, a 1- byte field is displayed as an unsigned hexadecimal byte depicting the LSAP type (802.2). If value is set to 3, a 5-byte field is displayed as an 802.2 SNAP value in hexadecimal. | Result displayed is stored in this global. If it's an 802.2 SNAP ID, then only the bottom 4 bytes are stored. | If value is 0 or 1, increment is 2. If value is 2, increment is 1. If value is 3, increment is 5. | Used to display a protocol field. An attempt is made to find that protocol in the name table. If a match is made, then the name will be displayed.
PSTR | High bit signifies display as 7-bit ASCII, i.e., ignore the high bit of each byte. | Length of the string (not including length byte) is stored here. | Length of the string plus 1 for length byte. | Display a Pascal-style string. The first data byte indicates the length of the string.
PUSH | not used | Global value to push onto the stack. | 0 | Pushes a value onto the stack.
SBIT | Bit number to test. | Global to test. | 0 | Test the bit specified by value in the specified global and remember for the next test. Bit numbers start with zero as the least significant bit.
SCMP | Number of chars to compare. | not used. | 0 | Compares the number of bytes specified by value field to the string specified in the string field. If equal, the test boolean flag will be set to true.
SEQU | Value to check against global. | Global to check against value. If the high bit of the global is on then compare value numbered global with global, i.e., global[glob_num] == global[value] instead of global[glob_num] == value. | 0 | Check value against global, and set previous test if equal.
SGTE | Value to check against global. | Global to check against value. If the high bit of the global is on then compare value numbered global with global, i.e., global[glob_num] <= global[value] instead of global[glob_num] <= value. | 0 | Check value against global, and set previous test if greater than or equal.
SGTX | Value to check against global. | Global to check against value. If the high bit of the global is on then compare value numbered global with global, i.e., global[glob_num] < global[value] instead of global[glob_num] < value. | 0 | Check value against global, and set previous test if greater.
SHFL | Amount to shift left. | Global contains the value to shift. | 0 | Shifts the global value to the left the number specified in the value field.
SHFR | Amount to shift right. | Global contains the value to shift. | 0 | Shifts the global value to the right the number specified in the value field.
SKIP | Number of instructions to skip. If the value is 0 then the value will be determined by ENDS. If the high bit is set then skip if most recent test was false. If 2nd highest bit is set then do not skip. If 3rd highest bit is set then skip. | not used | 0 | Skip over value number of instructions if most recent test was true. If the high bit of the value is on then skip if most recent test was false. This is an easy way to branch over a few instructions without having to transfer to other decode resources. Note: You can not skip backwards (no negative values permitted).
SLTE | Value to check against global. | Global to check against value. If the high bit of the global is on then compare value numbered global with global, i.e., global[glob_num] >= global[value] instead of global[glob_num] >= value. | 0 | Check value against global, and set previous test if less than or equal.
SLTX | Value to check against global. | Global to check against value. If the high bit of the global is on then compare value numbered global with global, i.e., global[glob_num] > global[value] instead of global[glob_num] > value. | 0 | Check value against global, and set previous test if less than.
SNEQ | Value to check against global. | Global to check against value. If the high bit of the global is on then compare value numbered global with global, i.e., global[glob_num] != global[value] instead of global[glob_num] != value. | 0 | Check value against global, and set previous test if not equal.
SUBG | Value to subtract. | Global to store result. If the high bit of the global is on then subtract value numbered global from global, i.e., global[glob_num] -= global[value] instead of global[glob_num] -= value. | 0 | Subtract value from a specified global.
TBIT | Bit number to test. | Global to test. If global has 0x100 set, then previous test must also be true before transferring. | 0 | If the bit number contained in value is set then branch to the named decoder. Bit numbers start with zero as the least significant bit.
TEQU | Value to check against global. | Global to check against value. If global has 0x100 set, then previous test must also be true before transferring. | 0 | Test value against a global and branch to the named decoder if they match.
TGTE | Value to check against global. | Global to check against value. If global has 0x100 set, then previous test must also be true before transferring. | 0 | If value is greater than or equal to a global then branch to the named decoder. (ie. global <= value)
TGTX | Value to check against global. | Global to check against value. If global has 0x100 set, then previous test must also be true before transferring. | 0 | If value is greater than a global then branch to the named decoder. (ie. global < value)
TIME | If value is 1, format is AppleTalk AFP time. If value is 2, format is IP time. If value is 3, format is NTP time. If value is 4, format is ANSI time. If value is 5, format is SMB time. | Result displayed is stored in this global (except in the case of SMB time). | 4 (or 8, in the case of SMB time) | 4 (or 8) bytes are displayed in hexadecimal and then are used to display the corresponding time.
TLSE | not used | not used | 0 | If most recent test is false then branch to the named decoder.
TLTE | Value to check against global. | Global to check against value. If global has 0x100 set, then previous test must also be true before transferring. | 0 | If value is less than or equal to a global then branch to the named decoder. (ie. global >= value)
TLTX | Value to check against global. | Global to check against value. If global has 0x100 set, then previous test must also be true before transferring. | 0 | If value is less than a global then branch to the named decoder. (ie. global > value)
TNEQ | Value to check against global. | Global to check against value. If global has 0x100 set, then previous test must also be true before transferring. | 0 | Test value against a global. If not equal then branch to the named decoder.
TNXT | not used | not used | 0 | Branch to the named decoder.
TRNG | not used | not used | 6 | Six bytes as an 802.5 Token Ring address. Also an attempt is made to translate the address into a DECnet address. Also an attempt is made to find that address and/or DECnet address in the name table. The bit for source routing information is ignored for such searches. If a match is made, then the name will be displayed.
TRTS | not used | not used | 0 | Return from a subroutine. The return is to the instruction following the last TSUB encountered.
TST# | Value to subtract from global | Index into string resource | 0 | A str# resource with the following string name is loaded and an index (in a global) is used to get the name of the decoder to be loaded. If there is a value it is subtracted from the global. If there is no such name, nothing happens, but test result is set to false.
TSB# | Value to subtract from global | Index into string resource | 0 | A str# resource with the following string name is loaded and an index (in a global) is used to get the name of the decoder to be loaded. The decoder that is loaded will return upon completion. If there is a value it is subtracted from the global. If there is no such name, nothing happens, but test result is set to false.
TSUB | not used | not used | 0 | Subroutine branch to the named decoder. Remember the current instruction's location for the TRTS instruction. Subroutine nesting is limited to 16 levels.
TTST | not used | not used | 0 | If the most recent test is true, branch to the named decoder. Will also do a TEQU if a global is specified.
XTST | not used | not used | 0 | Similar to TTST, but after branching to the named decoder, it will return to this location.
XBIT | Bit number to test. | Global to test. If global has 0x100 set, then previous test must also be true before transferring. | 0 | Similar to TBIT, but after branching to the named decoder, it will return to this location.
XEQU | Value to check against global. | Global to check against value. If global has 0x100 set, then previous test must also be true before transferring. | 0 | Similar to TEQU, but after branching to the named decoder, it will return to this location.
XGTE | Value to check against global. | Global to check against value. If global has 0x100 set, then previous test must also be true before transferring. | 0 | Similar to TGTE, but after branching to the named decoder, it will return to this location.
XGTX | Value to check against global. | Global to check against value. If global has 0x100 set, then previous test must also be true before transferring. | 0 | Similar to TGTX, but after branching to the named decoder, it will return to this location.
XLTE | Value to check against global. | Global to check against value. If global has 0x100 set, then previous test must also be true before transferring. | 0 | Similar to TLTE, but after branching to the named decoder, it will return to this location.
XLTX | Value to check against global. | Global to check against value. If global has 0x100 set, then previous test must also be true before transferring. | 0 | Similar to TLTX, but after branching to the named decoder, it will return to this location.
XNEQ | Value to check against global. | Global to check against value. If global has 0x100 set, then previous test must also be true before transferring. | 0 | Similar to TNEQ, but after branching to the named decoder, it will return to this location.
XLSE | not used | not used | 0 | Similar to TLSE, but after branching to the named decoder, it will return to this location.
WHOA | Default index of string within the str# designated by the string field to use in future WHOA. Upper 8 bits, if non-zero, indicate a global number where the packet number of the MARK is placed if a match is found. | Contains the reference point for linking request and response packets, usually transaction ID or port # etc. Used to search the cache along with the string field number, retrieving the value field and packet number. | 0 | See the more detailed overall explanation of MARK and WHOA threading, above. If a packet type can not be determined from data within the packet itself, a cache is searched to determine if some earlier packet did a MARK instruction to give a clue as to how to decode this packet. If no such entry exists in the cache, a question mark is displayed at the bottom of the decode window while a default decode is provided or the user's input is necessarily requested or the previous choice is assumed depending upon the current mode of operation. When the question mark is displayed or any other choice has been made either manually or through the MARK instruction, clicking on the name or question mark displayed at the bottom of the window causes the user's input to be requested again. Any value selected by explicit user input will override any previous choices made through the MARK or other mechanisms. The string should contain the name of a str# resource that contains the names of the decode resource choices that may be used on the next part of the packet.

### Private Instructions

Instruction | Value | Global | Increment | Description
--- | --- | --- | --- | ---
PRV1 | not used | not used | 0 | Display packet timestamp.
PRV2 | not used | Result is stored in this global. | 0 | Display internal packet flags.
PRV3 | not used | Result is stored in this global. | 0 | Display internal packet status.
PRV4 | not used | Result is stored in this global. | 0 | Display packet length.
PRV5 | not used | Result is stored in this global. | 0 | Display packet slice length.
PRV6 | not used | Result is stored in this global. | 0 | Display 802.3 length field (as opposed to the Ethernet Type II protocol field located in the same location).
PRV7 | not used | not used | 0 | Reserved for future use.
PRV8 | not used | not used | 0 | Reserved for future use.

## Data Formats

In every decode instruction the data format is one byte. It can be divided into two 4-bit sections: the high 4 bits signify the columnar location to display the data (the data location bits) and the low 4 bits signify the style (color, etc.) in which the data should be displayed (the data style bits).

### Data Format Representation

Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
Field | Format | Style

### Data Location Field

Value | Meaning
--- | ---
0x0 | Display data immediately with no spaces.
0x1 | Display data after a carriage return.
0x2 | Skip 2 spaces, then display data.
0x3 | Skip 4 spaces, then display data.
0x4 | Display data beginning in column 4.
0x5 | Display data beginning in column 8.
0x6 | Display data beginning in column 12.
0x7 | Display data beginning in column 16.
0x8 | Display data beginning in column 20.
0x9 | Display data beginning in column 24.
0xA | Display data beginning in column 28.
0xB | Display data beginning in column 32.
0xC | Display data beginning in column 36.
0xD | Display data beginning in column 40.
0xE | Display data beginning in column 44.
0xF | Display data beginning in column 48.

### Data Style Field

Value | Meaning
--- | ---
0x0 | Plain data.
0x1 | Layer label.
0x2 | Data label.
0x3 | header label (for use with PRVx instructions).
0x4 | Message.
0x5 | Invisible.
0x6 | Data dump label.
0x7 | Indent.
0x8 | Unindent.
0x9 | Unused.
0xA | Unused.
0xB | Unused.
0xC | Unused.
0xD | Unused.
0xE | Unused.
0xF | Unused.

## Label Formats

In every decode instruction the label format is one byte. The label format byte can be divided into one 1- bit field (the highest bit) which tells whether a new line should precede the label (the newline bit), one 3- bit field that tells the columnar location to display the label (the label location bits), and one 4-bit field (the lowest bits) which tell the style (color, etc.) in which the label should be displayed (the label style bits).

### Label Format Representation

Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
Field | Line | Format | Style

### Label Newline Field

Value | Meaning
--- | ---
0x0 | No new line before label.
0x1 | New line before label.

### Label Location Field

Value | Meaning
--- | ---
0x0 | Display label immediately with no spaces.
0x1 | Skip 2 spaces, then display data.
0x2 | Skip 4 spaces, then display data.
0x3 | Display label beginning in column 0.
0x4 | Display label beginning in column 2.
0x5 | Display label beginning in column 24.
0x6 | Display label beginning in column 32.
0x7 | Display label beginning in column 36.

### Label Style Field

Value | Meaning
--- | ---
0x0 | Plain.
0x1 | Layer label.
0x2 | Data label.
0x3 | Header label (for use with PRVx instructions).
0x4 | Message.
0x5 | Invisible.
0x6 | Unused.
0x7 | Indent.
0x8 | Unindent.
0x9 | Unused.
0xA | Unused.
0xB | Unused.
0xC | Unused.
0xD | Unused.
0xE | Unused.
0xF | Unused.

## Instruction Index

A | B | C |  | D |  | E | F | G
ADDG | BBIT | CBIT | CRLF | D64B | DMPE | EBC# | FCSC | GBIT
ANDG | BBYT | CEQU | CST# | DBIT | DUMP | ETHR | FTPL | GBYT
AT01 | BEEP | CGTE | CSTR | DBRK | DWRD |  |  | GLNG
AT03 | BGLB | CHR# |  | DBYT |  |  |  | GSTR
ATLG | BITO | CKSM |  | DECR |  |  |  | GWRD
| BLNG | CLSE |  | DGLB |  |  |  |
| BREM | CLTE |  | DIVG |  |  |  |
| BST# | CNEQ |  | DLNG |  |  |  |
| BWRD |  |  |  |  |  |  |
| BYTO |  |  |  |  |  |  |
H | I | L | M | N | O | P | S |
HBIT | INCR | LABL | MARK | NBNM | ORRG | POPX | SBIT | SKIP
HBYT | IPLG | LSTE | MODG | NOTG | OSTP | PORT | SCMP | SLTE
HEX# | IPV6 | LSTS | MOVE |  |  | PRTO | SEQU | SLTX
HGLB |  | LSTZ | MULG |  |  | PSTR | SGTE | SNEQ
HLNG |  |  |  |  |  | PUSH | SGTX | SUBG
HWRD |  |  |  |  |  |  | SHFL |
|  |  |  |  |  |  | SHFR |
T |  | W | X |  |  |  |  |
TBIT | TRAK | WHOA | XBIT |  |  |  |  |
TEQU | TRNG |  | XEQU |  |  |  |  |
TGTE | TRTS |  | XNEQ |  |  |  |  |
TGTX | TSB# |  | XGTE |  |  |  |  |
TIME | TST# |  | XGTX |  |  |  |  |
TLSE | TSUB |  | XLSE |  |  |  |  |
TLTE | TTST |  | XLTE |  |  |  |  |
TLTX | TYPE |  | XLTX |  |  |  |  |
TNEQ |  |  | XNEQ |  |  |  |  |
TNXT |  |  | XTST |  |  |  |  |

WildPackets, Inc.
1340 Treat Blvd., Suite 500
Walnut Creek, CA 94597 USA
925-937-3200
http://www.wildpackets.com/
sdkhelp@wildpackets.com
Copyright © 1991-2003 WildPackets, Inc.
All rights reserved.