AVATAR/0+

Advanced Video Attribute Terminal Assembler and Recreator by George A. Stanislav (August 23 1988 ~ Pittsburg PA).

Historical Overview

Wynn Wagner III, the author of Opus-CBCS, developed a method of storing video control codes in a file sent to the Opus caller which was meant as a replacement of ANSI escape codes. Its main advantages were:

Because of lack of an appropriate name, Wynn temporarily named the codes oANSI with the understanding that a better name was needed.

When I (George S.) started working on my TinyTerm communications program, I had the idea that if Opus-CBCS could send the “oANSI” codes directly over the phone lines, it would speed up the communications considerably. A typical ANSI sequence contains 4 times as many bytes as the codes developed by Wynn Wagner.

A phone call to Wynn resulted in two things:

I took over the coding of the part of Opus handling the video codes. I realized the codes were offering us much more power than just translating them to ANSI escape sequences. I proposed to call the codes AVATAR, the Advanced Video Attribute Terminal Assembler and Recreator. Wynn readily accepted the new name.

The Two Levels of Avatar/0+

Avatar is more than a video attribute controller. It is a protocol which, if need be, can totally eliminate the interference of line noise. However, this document is not concerned with the advanced topics of Avatar (which no program is using as of this writing 1988).

A full Avatar session with all its advanced features starts by exchanging the AVINIT packets. The caller sends a packet which describes the video capabilities of his/her system. It also contains the caller's name, password and some other optional information. It also tells the BBS if the user is calling in person or just emulating a BBS session with an Avatar terminal program.

The called system (the BBS) replies to the AVINIT packet with a packet that informs the user of his current status, e.g. you can stay till 16:30 GMT, or you are denied access, or I am processing mail now but you can call back at 10:43 GMT, etc.

Until such AVINIT packets are exchanged, only the Avatar commands that were part of the original oANSI codes can be sent from the BBS to the caller. The caller's term program should send no Avatar commands, with the exception of function key codes, before the AVINIT packets are exchanged. This assures that a BBS program which does not support full Avatar can still take advantage of the faster transfer of video codes using Avatar as opposed to ANSI escape sequences. It also permits the caller whose term program does not support full Avatar but can interpret the basic codes to take advantage of the term program's abilities.

The two levels of Avatar then are: a full session and a basic session. This document is concerned with the BASIC Avatar session only. The full session will be defined in a separate document.

Basic Avatar Commands

Before the AVINIT packets are exchanged, the BBS can send the basic Avatar commands if so permitted by the user's choice, typically recorded in the user datafile (e.g. USER.BBS). Because Avatar is window oriented, in a basic session the full screen is considered the default window. Further, the default color of the window is assumed to be 3 (cyan/teal text on a black background). All bytes are taken at their face value without escaping. However, save for one exception described below, no basic Avatar code will have the high bit set. Therefore, the term program should reset the high bit of all bytes except as described below.

The basic commands are:

SEQUENCE HEX MEANING
^L 0x0C Clear the current window and set current attribute to
default. In the basic session this means:
Clear the screen and set its attribute to 3.
^Y 0x19 Read two bytes from the modem. Send the first one to the
screen as many times as the binary value of the second one. This is the exception where the two bytes may have their high bit set.
Do not reset it here!
^V^A<attr> 0x16 0x01 <attr> Set the color attribute to <attr>.
The default attribute remains unchanged.
However, all text will be displayed in <attr> until the
next ^V^A, ^V^B, or ^L.
^V^B 0x16 0x02 Turn the high bit of current attribute on. In other words,
turn blink on.
^V^C 0x16 0x03 Move the cursor one line up. Do nothing, if you already are
at the top line of the current window.
^V^D 0x16 0x04 Move the cursor one line down. Do nothing, if you already
are at the bottom of the current window.
^V^E 0x16 0x05 Move the cursor one column to the left. Do nothing, if you
already are at the leftmost column of the current window.
^V^F 0x16 0x06 Move the cursor one column to the right. Do nothing, if you
already are at the rightmost column of the current window.
^V^G 0x16 0x07 Clear the rest of the line in the current window using the
current attribute (not to be confused with the default attribute).
^V^G<row><col> 0x16 0x08 <row> <col> Move the cursor to the <row> <col> position within the
current window.

Comments:

Current attribute and default attribute are not necessarily the same. Whenever the window is cleared by the <^L> command, the current attribute is made equal to the default attribute. There is also another command to make the current attribute equal to the default attribute. However, this command is not a part of the basic Avatar command set and therefore cannot be used before the AVINIT packets are exchanged.

Whatever characters are sent to the screen, they should be displayed using the CURRENT attribute. There is an exception to this, but only after the AVINIT packets have been exchanged.

The attribute byte is an eight-bit value. As basic Avatar can only transfer 7-bit commands, the high bit of the attribute byte can be set only by the <^V><^B> command. The <attr> byte of the <^V><^A><attr> command should be AND-ed with 7F (hexadecimal). The colors set by the attribute byte are the same as are the colors of the text mode of an IBM color graphics adapter.

That means the bits of the attribute byte have the following meaning:

   bit:         7   6   5   4   3   2   1   0
                -   -   -   -   -   -   -   -
                |   |       |   |           |
                |   |       |   |           |
                |   +---+---+   +-----+-----+
                |       |             |
                |       |             |
                |       |
                |       |         text color
                |       |
                |
                |    background color
                |
  
              blink

If the blink bit is set, the text is blinking, else it is not blinking.

The bits of background color can have values 0 - 7, the bits of the text color can have values 0 - 15. The value indicates the following colors:

               0      black
               1      blue
               2      green
               3      cyan
               4      red
               5      magenta
               6      brown
               7      gray  (i.e. non-itense white)
               8      dark gray
               9      light blue
              10      light green
              11      light cyan
              12      light red
              13      light magenta
              14      yellow
              15      white (intense)

Colors 8 - 15 are the same as 0 - 7 but with high intensity.

Please note that these values are different from the numbers used by ANSI escape codes.

The Function Key Codes

An Avatar capable BBS can accept function keys from the remote caller. This feature is optional (for the term program) but highly recommended.

On an IBM (compatible) computer this means that if a caller hits a function key (e.g., left arrow, page up, F7, insert, alt-H, etc.), the term program should send two bytes to the Avatar capable BBS: A binary zero followed by the keyboard scan code. Please note that control keys (^A, ^B, etc.) are not function keys but have an ASCII value which is the only byte that should be transferred.

There are two keys on the IBM keyboard that do have an ASCII value but also offer a separate scan code. These are the gray-plus and the gray-minus. If one of these keys is hit, treat it as a function key - send the binary zero followed by the scan code. This way if the BBS treats them differently from a regular plus and minus keys, the caller can take advantage of the keys.

On the other hand, BBS writers who do not want to assign the gray keys a special value, should watch for their codes and treat them as a regular plus and minus.

Systems that use a different keyboard layout (and scan codes) than IBM can emulate IBM by declaring which keys are considered the arrows, f-keys, etc. If you have the arrow keys, for example, but their scan codes are different, still send the binary zero and the scan code that an IBM keyboard would assign to that particular key. This should be transparent to the user.

There is an obvious problem here. All terminal programs I have seen use function keys internally. A switch is needed so the user can decide whether a function key is meant for the internal use of the term program or it should be transferred to the BBS. Most but not all IBM clones have a scroll lock key, some even have an LED indicator on it. The IBM programs could use that as a switch to know what the user means by hitting a function key. Since some compatibles do not have a scroll lock key (e.g. Tandy 1000), the Avatar capable BBS should never expect the <shift> <F1> combination to be transferred. That way the term program can use <shift> <F1> to switch between the local and remote use of function keys if the scroll lock key is not available.

Conclusion

This should about summarize the basic Avatar commands. I have written this document one day before leaving for Fidocon '88 realizing it would be nice to give the software developers (both of BBS's and term programs) something before releasing the specs of the full Avatar implementation.

Here is also some sample C code. It assumes you have some low level communications functions of your own. For the screen output it uses Turbo C library, but you can use anything you want.

  #include <conio.h>
  
  int def_attr = 3;
  int cur_attr = 3;
  int lastline = 25;
  int lastrow  = 80;
  
  /* WARNING: This code has not been tested. It is just meant as an example  */
  
  void pascal avatar() {
     int c,i,j;
  
  switch (mgetchar()) {           /* Read a char from the modem */
      case 12 :       textattr(cur_attr = def_attr);  /* ^L */
                      clrscr();
                      break;
  
      case 25 :       c = mgetchar();                 /* ^Y */
                      j = mgetchar();
                      for (i = 0; i < j; i++)
                              cprintf("%c",c);        /* print in color */
                      break;
  
      case 22 :       switch(mgetchar())              /* ^V */
                      {
                       case 1 : cur_attr = mgetchar() & 0x7f;
                                textattr(cur_attr);
                                break;
  
                       case 2 : cur_attr |= 0x80;
                                textattr(cur_attr);
                                break;
  
                       case 3 : if ((i = wherey()) > 1)
                                      gotoxy(wherex(),i - 1);
                                break;
  
                       case 4 : if ((i = wherey()) < lastline)
                                      gotoxy(wherex(), i + 1);
                                break;
  
                       case 5 : if ((i = wherex()) > 1)
                                      gotoxy(i - 1,wherey());
                                break;
  
                       case 6 : if ((i = wherex()) < lastrow)
                                      gotoxy(i + 1,wherey());
                                break;
  
                       case 7 : cleol();
                                break;
  
                       case 8 : i = mgetchar();
                                gotoxy(mgetchar(),i);
                      }
    }
  }