
INTELLIVISION PROGRAMMING DOCUMENT v0.2
Reverse Engineered by Carl Mueller
simon17@ix.netcom.com

Thanks to:

Sean Kelly
William Moeller
Ian Farquhar
The Blue Sky Rangers
Keith Robinson
Tim Smith

who in someway (knowingly or not) helped make this document possible.

COLORS
  There are 16 colors available, encompassing the Primary and Pastel
  range of colors.

  PRIMARY colors are colors 0 - 7:
  0 = Black      3 = Tan             6 = Yellow
  1 = Blue       4 = Dark Green      7 = White
  2 = Red        5 = Green

  PASTELS are colors 8 - 15:
  8 = Gray       11 = Brown         14 = Yellow-Green
  9 = Cyan       12 = Pink          15 = Purple
  10 = Orange    13 = Light Blue

SYSTEM RAM (16-bit)
  352 words total memory, mapped from $0200 - $035F.
  BACKTAB information
    240 words, mapped from $0200 - $02EF.
    The background is organized of 12 rows of 20 columns of cards.
    The BACKTAB corresponds to each card by a word of data (12 x 20 = 240)
    as follows:

      FOREGROUND / BACKGROUND MODE
      15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
       ?  ?  B  b  t  b  b  n  n  n  n  n  n  f  f  f

    where:

      bBbb     is the background color (off bits), either pastel or primary
               colors (0 - 15).
      t        is a toggle which tells the STIC where to grab the card from:
               0 = GROM, 1 = GRAM
      NNnnnnnn is the actual # of the card corresponding to it's position in
               GRAM or GROM, (0 - 63) or (0 - 212).  The top two bits (NN)
               are only used when plotting a GROM card, so for a GRAM card
               you can use them as user-defined flags.
      nnnnnn   is the actual # of the card corresponding to it's position in
               GRAM or GROM, (0 - 63).
      fff      is the foreground color (on bits), primaries only (0 - 7).

      COLOR STACK / COLORED SQUARES MODE
      15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
       ?  ?  a cF  t  N  N  n  n  n  n  n  n  f  f  f

    where:

      c        when set and bit #11 = 0, invokes colored squares mode
               for this card (see colored squares).
      a        if set, advances to next background color on color stack.
      Ffff     foreground color (on bits), pastels or primary (0 - 15).
      t        is a toggle which tells the STIC where to grab the card from:
               0 = GROM, 1 = GRAM
      NNnnnnnn is the actual # of the card corresponding to it's position in
               GRAM or GROM, (0 - 63) or (0 - 212).  The top two bits (NN)
               are only used when plotting a GROM card, so for a GRAM card
               you can use them as user-defined flags.

      COLORED SQUARES MODE
      +---+---+
      | 1 | 2 |
      +---+---+
      | 3 | 4 |
      |---+---+
      15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
       ?  ?  4  c  0  4  4  3  3  3  2  2  2  1  1  1

      colors can range from 0 - 7, but when color 7 is specified
      the current color on the color stack is used instead of white.

      c      must be 1 (colored squares mode)
      0      must be 0
      111    color for square at position 1
      222    position 2
      333    position 3
      444    position 4

  CPU STACK
    112 words, mapped from $02F0 - $035F.

GRAM (8-bit)
  512 memory locations, mapped from $3800 - $38FF.
  Stores up to 64 (8 x 8 bit) images for moving objects or the background.

GROM (8-bit)
  2048 memory locations, mapped $3000 - $37FF.
  - 1,704 bytes (213 chars) of predefined 8x8 bitmaps
    (alphabetic characters, punctuation, graphics, etc).
  - 344 bytes overflow of Executive code (semi-compressed).

  NOTE:  Code is decompressed by the EXEC onto the BACKTAB region of memory
         during initialization.  The code seems to load in background cards,
         with options of flipping, rotating, and/or inverting the images
         to save room on the catridge.  Since the STIC cannot flip/rotate
         or invert cards on it's own, seperate images would need to be
         stored in the cart ROM.

EXEC ROM (10-bit)
  4096 words of code, mapped $1000 - $1FFF.

  Cartridge ROM usually originates at address $5000.  The EXEC ROM, upon
  intialization, checks addresses $4800 and $7000 for viable ROM, and if
  it exists, starts running there.  This is why some games start their
  map at $4800, to nearly completely bypass the EXEC start-up sequence.

  NOTE:  Pacman by Atari actually maps into the $7000 region, which is
         why the cartridge doesn't work with the ECS module plugged in.

  SUBROUTINES
  $1668  Extend sign from low byte of R0 into full word.

  $1DDC  Multiply: R0 and R1.  Result in R2.

  $1DFB  Divide:  Dividend is R1, divisor is R2.
         Quotient placed in R0, remainder placed in R1.

  $1738  Zeros memory.
         R0 = count
         R4 = address

  $1741  Fills memory with value in R1.
         R0 = count
         R1 = value
         R4 = address

  $1777  R1 = start addr.
         Returns:
         R2 = x.pos
         R3 = y.pos

  $18C5  Write a numeric string, padded with spaces on the left instead of
         0 digits.  R4 is positioned at the begining of where the numeric
         was written to, instead of positioned just after.
         R0 = numeric value
         R1 = number of digits
         R3 = attribute word (same as BACKTAB word format)
         R4 = destination address to write to (i.e. BACKTAB location)

  $18AD  Write a numeric string like $18C5, but pad with 0's.
         R0 = numeric value
         R1 = number of digits
         R3 = attribute word (same as BACKTAB word format)
         R4 = destination address to write to (i.e. BACKTAB location)

  $1867  Same as $187B, except you can specify an address from where to
         fetch the string data.  The address is incremented to point to
         the character after the null terminator, but is placed in R5.
         R1 = address of string data, which must end with a null
              terminating character ($0).
         R3 = attribute word (same as BACKTAB word format)
         R4 = destination address to write to (i.e. BACKTAB location)

  $187B  Write a string of words to a memory location (such as BACKTAB).
         The string of words must follow the JSR instruction, and must
         end with a null-terminated word (0h).  The R7 register will be
         automatically incremented to start running the instruction
         right after the null-terminated word.
         R3 = attribute word (same as BACKTAB word format)
         R4 = destination address to write to (i.e. BACKTAB location)

  $1B95  Possibly triggers a "stock" sound effect.
         Parameter is passed as a string of words after the JSR instruction,
         and is terminated by a null-terminated word. The R7 register will
         be automatically incremented to start running the instruction
         right after the null-terminated word.

  $1BBE, Possibly generates a noise envelope.  The data is passed after the
  $1BBB  JSR instruction, and the R7 register is automatically incremented
         to start running the instruction right after a null-terminated word
         of $02CF (??).

  SPECIAL MEMORY LOCATIONS

    HEADER (memory addresses are stored lo, hi)
      $5000 Moving object graphics address, used for EXEC-assisted animation.
            Also used by the "SUCKY" feature on the ECS.
      $5002 Pointer to "periodically called routine" table.
      $5004 Start program address (after title screen).
      $5006 Pointer to background graphics (?)
      $5008 ??
      $500A Pointer to title screen and copyright date, first word is the
            year, then follows the title in ASCII terminated by a $0.
            The code after may be called for additions to the title screen.
      $500C if bit #7 set, run code directly after title string null word.
      $500D moved into $0032 (block out h/v card rows)
      $500E graphics mode
      $500F + cs_element = color
      $5013 border color
    ...
    HAND CONTROLS
      $01FF Left controller data direct from AY8910
      $01FE Right controller data direct from AY8910
      $035D Pointer to HANDTAB
      HANDTAB (each a pointer to a handler routine, stored lo, hi)
        + $00 DISC          R0 = disc value (0 - 15) or negative if released
        + $02 KEYPAD        R0 = keypad value (0 - 9, 10 = clear, 11 = enter)
        + $04 UPPER BUTTONS R0 = 1 if pressed, -1 if depressed (?)
        + $06 LOWER RIGHT   same
        + $08 LOWER LEFT    same
        R1 = 0 for left controller, 1 for right (?)

    MOVING OBJECT RELATED DATA / RECORDS

    n = moving object # 0 - 7

    $107 + n : STIC Collision register (lo byte), moving object #n.

    $10F : Background collision word

            07 06 05 04 03 02 01 00
             7  6  5  4  3  2  1  0
            where:
              0 = if set, background collided with MO # 0
              1 = if set, background collided with MO # 1
              etc.

    $110 : Screen boundary collision word

            07 06 05 04 03 02 01 00
             7  6  5  4  3  2  1  0
            where:
              0 = if set, MO # 0 intersected with screen boundaries
              1 = if set, MO # 1 intersected with screen boundaries
              etc.

    $31D + (n * 8) : Attribute word

            15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
             ?  ? xs  v  c ym xm ys yf  r  p  F  t  f  f  f
            where:
            Ffff = foreground color
            t = toggle (0 = GROM, 1 = GRAM)
            p = priority (1 = behind ON bits of background, 0 = in front of)
            r = resolution (0 = 8 rows, 1 = 16 rows)
            yf = YFULL: doubles the scanline height
            ys = YSIZE: quadruples the scanline height
            xm = mirror MO horizontally (mirror = 1, 0 = not)
            ym = mirror MO vertically (mirror = 1, 0 = not)
            c = flag collisions (1 = yes, 0 = no)
            v = visability (1 = yes, 0 = no)
            xs = XSIZE: doubles the width

    $31E + (n * 8) : Pointer to collision tab (COLLTAB), moving object #n.

    $31F + (n * 8) : X position in 8.8 fixed point, moving object #n.

    $320 + (n * 8) : Y position in 8.8 fixed point, moving object #n.

    $321 + (n * 8) : X / Y velocity: signed 8-bit stored in hibyte, lobyte
                     (resp.), moving object #n.

    $322 + (n * 8) : Sequence Speed and Frame #, moving object #n.

            15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
             d  d  d  d  d  d  s  s  s  s  s  s  n  n  n  n
            where:
            n = frame # 0 - 15.
            s = sequence speed (0 = slowest, 63 = fastest)
            d = counter (used internally by EXEC)

      NOTE:  There seems to be a "bug" involving this word and an MO with 16
             frames of animation.  This combo causes the sequence speed to be
             incremented each time the object goes through it's animation
             sequence.  So the sequence speed gets faster & faster, until it
             wraps around to 0, causing the animation to stop completely.

      COLLISION TAB HEADER

        + $00 : Collision with screen boundaries

                The type of collision checking is indentified by bits
                8 - 9.  There are 4 different types available (numbered
                0 - 3).

                  0 = Intersection w/ screen frame (in hardware)
                  1 =
                  2 = Off physical screen boundaries (anywhere outside of
                      the fixed 160 x 92 screen region)
                  3 = Off virtual screen boundaries (stored in [$116..$119])

                The lower byte of this register and the lower byte of the
                next register combine to form the address that's called
                when the collision condition is true.  The adress is stored
                in the usual LO, HI manner.

        + $02 : Routine called when MO's timer reaches 0 ([$323 + (mo# * 8)])
                Stored LO, HI.

        + $04 : # of frames in animation sequence, 0 - 15 (0 = 16 frames).

        + $05 : Picture # used as base of sequence (0 - 127).

                The actual address of the graphic is calculated as:
                  Addr = MO graphics address + Picture # * 8

        + $06 : Number of entries in collision table / bkg collision.

                03 02 01 00
                 n  n  n  b
            where:
              nnn   number of entries (collisions with other MOs), 0 - 7
              b     if set, the first entry will point to a routine that
                    handles collisions with the background.

        COLLISION ENTRIES

        Each "entry" in this table is two words in size.

          1st word:
          09 08 07 06 05 04 03 02 01 00
           1  2  l  l  l  l  l  l  l  l

          2nd word:
          09 08 07 06 05 04 03 02 01 00
           x  0  h  h  h  h  h  h  h  h

          where:
            hhhhhhhhllllllll  address called if condition is true
            210               bits 0 - 2 of MO # collided with.
                              Yes, the top two bits are swapped.
              x               not used

  Also contains:
    - "Creating sound and music", probably has routines for creating
      tone and noise envelopes.

SCRATCHPAD RAM (8-bit)
  256 memory locations, mapped $100 - $1FF (??)
  Used by the SOUND and EXEC ROM chip for temporary data storage.
  147 locations (bytes) left over for use by the game program.

STIC
  Registers are mapped $00 - $32 (??)

  Displays one 20 x 12 tiled background, made up of 8x8 cards.  It grabs
  card positions from the BACKTAB area in SYSTEM RAM.  The background can
  be told to delay up to 7 pixels rows or columns.  It can be told to block
  out the top 8 pixel rows or columns with a strip (same color as border
  color).

  Can be set to two different graphics modes: FOREGROUND / BACKGROUND and
  COLOR STACK / COLORED SQUARES.

  Displays 8 moving objects, of 8x8 size, or 8x16 size.  MO's can also be
  doublesized horizontally and 2, 4, or 8 times the size vertically (see
  YRES, YFULL, and YSIZE bits).  They can also be flipped horizontally
  and/or vertically.

  MOVING OBJECTS
    Moving objects are numbered 0 - 7.

    For moving objects, the x and y positions seem to locate the right bottom
    most pixel, then over and down one.  This is consistant for single and
    double resolution sprites, however, when doublesizing, it still considers
    the same point before you doublesized it.

    For instance, an x and y position of 0 would not show anything since the
    MO is off-screen, but once you doublesized it, you'd see part of the MO
    even though it's still considered to be at 0.  This also explains why
    doublesized (etc) objects tend to "pop" on the screen from the top or
    left edges.

    $00 + n : X position register, moving object #n.

            15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
             ?  ?  ?  ?  ? xs  v  c  x  x  x  x  x  x  x  x
            where:
            x = (0 - 255).
            c = flag collisions (1 = yes, 0 = no)
            v = visability (1 = yes, 0 = no)
            xs = XSIZE: doubles the width

    $08 + n : Y position register, moving object #n.

            15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
             ?  ?  ?  ? ym xm ys yf  r  y  y  y  y  y  y  y
            where:
            y = (0 - 127).
            r = resolution (0 = 8 rows, 1 = 16 rows)
            yf = YFULL: doubles the scanline height
            ys = YSIZE: quadruples the scanline height
            xm = mirror MO horizontally (mirror = 1, 0 = not)
            ym = mirror MO vertically (mirror = 1, 0 = not)

    $10 + n : Attribute register, moving object #n.

            15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
             ?  ?  p  F  t  ?  ?  n  n  n  n  n  n  f  f  f
            where:
            Ffff = foreground color
            n = card # in GRAM or GROM
            t = toggle (0 = GROM, 1 = GRAM)
            p = priority (1 = behind ON bits of background, 0 = in front of)

  COLLISION DETECTION

    The format of a collision register is as follows:

    $18 + n : Collision register, moving object #n.

            15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
             ?  ?  ?  ?  ?  ?  o  b  7  6  5  4  3  2  1  0
            where:
              0 = if set, collision with MO # 0
              1 = if set, collision with MO # 1...
              etc.
              b = collision with any bkg ON bit
              o = collision with screen boundaries

  COLOR STACK
    The background (OFF bits) during COLOR STACK mode can be set to 4
    different colors, either primary or pastels (0 - 15).  However, they
    must be used in a predetermined order.  When plotting a card, that
    card can tell the STIC to advance (or not) to the next color on the
    COLOR STACK.  When it gets to the last color (stored in $2B), it wraps
    back to the 1st color (stored in $28).  COLOR STACK also allows access to
    the "extended set" of GROM characters (lower case, etc): #64 - #212.

    $28 + n : Color stack register, color element #n (0 - 3).

  OTHER
    $20 : Display enable
      Must be written to during each vblank to enable STIC output.
    $21 : Graphics mode
      Read register = COLOR STACK, Write register = FOREGROUND / BACKGROUND
    $2C : Border color
      Primary or pastels (0 - 15).
    $30 : Horizontal delay (0 - 7)
    $31 : Vertical delay (0 - 7)
    $32 : Block out horizontal / vertical card rows or columns
      Block out first card column if bit #0 set, and first card row
      if bit #1 set.
