Document Title: [Atari_xy.html (html file)]
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!