Disclaimer: This information is provided as is. There may be errors in this information. You may use this information only if you agree that Minimalist / Coinop.org, its employees, and noted authors will never be held responsible for any damage, injury, death, mayhem, etc. caused by errors in the information. When working with high voltage, never work alone and always follow safety precautions.

Document Title: [Atari_xy.html (html file)]

Programming the Atari XY Vector Generator


  The information in this document is not guaranteed to be accurate,
use at your own risk.

  The Atari Analogue Vector Generator (or AVG) is the circuitry used to
draw lines on the special XY monitors of some games from the late seventies 
and early eighties. These include Asteroids, Battlezone, Tempest, Gravitar
and Star Wars, all of which used a slightly different AVG as the games evolved.

  The AVG is a small computer in its own right, it has its own ROM, RAM,
instruction set and stack for subroutines. There are only a few instructions,
which makes it quite easy to decode, and different games use similar ones 
even if they have different hardware (any takers for an AVG assembler / 
disassembler, maybe with GUI shape editing? ).


  The following information is for the Star Wars game, but is very similar
to other games.

  The basic AVG instructions are as follows:

  1. Draw vector relative X, Y.    This instruction draws a vector from
                                   the last position to a new relative 
                                   offset.

  2. Centre.                       Returns beam to centre of display.

  3. Set colour / intensity.       Sets new colour and intensity for
                                   subsequent vectors.

  4. Jump to new address.          Jumps to specified address in vector 
                                   ROM/RAM.

  5. Jump to subroutine.           Pushes current position to stack and 
                                   jumps to specified subroutine in vector
                                   ROM/RAM.

  6. Return from subroutine.       Pops previous pushed address from stack.

  7. Halt.                         Stops AVG until VGGO signal from main 
                                   game processor.

  The main game processor fills the vector RAM with a list of instructions
telling the AVG where to draw vectors on the display, and then writes to the
VGGO address port which starts the AVG executing.  The main processor can 
also reset the AVG by writing to the VGRST address. The AVG always starts 
executing instructions from address 0x0000 in the vector RAM after a reset
or HALT instruction. The vector ROM probably holds the shapes and character
set for the game as subroutines (I've never looked!) to be called from RAM
when required. The character set is comprised of short vectors, so a special
'Draw Short Vector' instruction is implemented which uses less bytes per
instruction.

  All vector instructions are two or four bytes long. The operand is packed
with the opcode as the upper 3 bits. The instruction is stored in low 
byte-high byte format, as seen from the main processor. When calculating a
vector jump address, note that the AVG sees the vector memory as 8K x 16
words, while the main processor sees 16K x 8 bytes.

  The draw instruction always draws relative to the end of the last vector
with a negative number represented by the upper bit being set.

  There are 8 basic colors from the RGB bits and 256 intensity levels of
these 8 colors. Further to this each vector draw instruction holds 8 levels 
of intensity which controls the overall intensity. I believe that this may
have something to do with the fact that a long vector drawn in the same time 
period as a short vector will need to have more intensity to give the same
apparent intensity on the screen.


  The scale instruction determines the size of subsequent vectors, so a
shape can be magnified or shrunk by simply changing the scale factor without
having to re-calculate all the vector points. The lower 8 bits of the scale
instruction control a DAC which alters the analogue output swing of the X
and Y DAC's. The upper 3 bits of the scale instruction are a digital scaling
which I believe may shift the X and Y position data to achieve a binary
multiplying effect on the vectors. I think a scale of 0x0FF gives a
magnification of one.

  For subroutines there is a stack for holding return addresses. On earlier
games the stack and instruction counter was built from discrete logic, but 
with Gravitar and Star Wars an 'Address Controller' gate array was introduced
to replace this logic. With the discrete versions the stack was 4 deep, but 
with the gate array it could possibly be more.

  The last instruction after drawing all the required vectors must be a halt
instruction, so that the main processor can poll the VGHALT bit and then
update the new positions.


 Bit Key:
          X - X coordinate bits
          Y - Y coordinate bits
          I - Vector intensity(brightness) bits
          A - Vector address bits
          R - Red color bit
          G - Green color bit
          B - Blue color bit
          S - Scale (size)
          U - Unused bit

  For Star Wars the codes are as follows:


    Opcode                     Hex      Binary

    Draw relative vector.      0x00     000YYYYY YYYYYYYY IIIXXXXX XXXXXXXX

    Halt                       0x20     00100000 00000000

    Draw short relative vector 0x40     010YYYYY IIIXXXXX

    New color/intensity        0x60     0110URGB IIIIIIII

    New scale                  0x70     0111USSS SSSSSSSS

    Center                     0x80     10000000 00000000

    Jump to subroutine         0xA0     101AAAAA AAAAAAAA

    Return from subroutine     0xC0     11000000 00000000

    Jump to new address        0xE0     111AAAAA AAAAAAAA

  I think that the instructions for Battle Zone, Gravitar and Tempest are
the same as Star Wars, but older games are different.

  For Asteroids (and probably Asteroids deluxe and Lunar Lander):

    Draw relative vector       0x80      1000YYYY YYYYYYYY IIIIXXXX XXXXXXXX

    Draw relative vector
    and load scale             0x90      1001YYYY YYYYYYYY SSSSXXXX XXXXXXXX

    Beam to absolute
    screen position            0xA0      1010YYYY YYYYYYYY UUUUXXXX XXXXXXXX

    Halt                       0xB0      1011UUUU UUUUUUUU

    Jump to subroutine         0xC0      1100AAAA AAAAAAAA

    Return from subroutine     0xD0      1101UUUU UUUUUUUU

    Jump to new address        0xE0      1110AAAA AAAAAAAA

    Short vector draw          0xF0      1111YYYY IIIIXXXX


  If you wish to see a constant image on the screen, remember that the main
processor will have to poll the VGHALT until all the vector instructions 
have been executed, then write to VGGO to start again.

  Also make sure that you return the beam to the centre of the screen
before halting the AVG, because if the beam were fully deflected and left 
there the monitor deflection power transistors may not like it!