From: duck@pembvax1.pembroke.edu
Newsgroups: comp.sys.cbm
Subject: C= Hacking Issue #4 2/5
Date: 5 Oct 92 14:00:55 GMT
Organization: Pembroke State University
NNTP-Posting-Host: pembvax1.pembroke.edu


     | To Play:                                                    |
     |    Use joystick in port 2, mouse in port 1 or keyboard:     |
     |            A - Left, Z - Right   Space - Fire               |
     |              F1 - Restart                                   |
     |                                                             |
     +-------------------------------------------------------------+

  Title Screen Formatting
  -----------------------
  We come into a problem here -- the screen is some 1000 characters on the C64,
  and 2000 characters for the C=128.  It would be extremely wasteful to store
  that many characters in memory just to reproduce a title screen - and most of
  them consisting of spaces at that!!  

  What we'll do is to just specify the address on screen, the # of characters
  and then list the characters. It will be similair to our custom character
  table driver above but will be different enough that a new routine is 
  warrented. We will however use the two subroutines writebyte and setadrs
  that were developed in the previous routine. The data will look like the
  following:

       .word address
       .byte num_of_chars ($00= end of data)
       .ascii "text"
       .byte address .... etc.... 

  and we'll enter with .AY containing the address of the table.

  So basically we come up with the following:

-------------------------------------------------------------------------------
       write'txt = *
               sta zp1         ; save .ay in table address
               sty zp1+1
               ldy #$00
   loop'w'text = *
               jsr get'byte   ; set address.
               sta wrk
               jsr get'byte
               sta wrk+1
               jsr get'byte    ; get # of chars to write out.
               cmp #$00
               beq +           ; if zero then exit.
               tax
               jsr setadrs     ; set address to wrk,wrk+1
             - jsr get'byte
               jsr writebyte   ; write out byte.
               dex
               bne -
               sec
               bcs loop'w'text ; this is an absolute jump to loop 
             + rts             ; return.

-------------------------------------------------------------------------------

  This is similair to our previous routine, and was in fact copied and modified 
  from the previous routine. 


VIII. Debugging
      ---------

  Now, not all programs are perfect, and during the development of this 
  portion of the game there were several errors found. Tracing an error in
  Machine/Assembly-Language is like trying to find a grammatical error in a
  language you don't know. ;-) But seriously, there are several ways to track
  down errors in your code.

  1 - Try tracing it through by hand playing "What if I were the computer" and
      following what each register does.

  2 - Are you switching the LoHi order of variables? Ie: is it lda #< or 
      lda #>?? 

  3 - Set BRK points and run the program / subroutine within a machine language
      monitor and make sure the registers / memory locations contain the values
      that they should. If not, find out why.

  4 - Try to simplify your code in terms of programming ease - Make the 
      assembler do the work for you - it's a lot less likely to make errors 
      than you are.
  
  5 - Think logically!!!
  
  6 - Change something at random and pray.

  I can't stress numbers 3 and 5 enough. During the writing of the install'char 
  routine there were numerous bugs that were eventually tracked down by 
  setting a BRK instruction further along in the code and seeing exactly what
  the register / memory locations were. Also the use of temporary load and
  store instructions into "safe" regions of memory helped me monitor what some
  of the values were.

  For example, at one point I had a section of code similair to the following:

             clc
             lda value
             adc data
             bne +
             inc data+1
           + [.... ]

  And it's purpose was to add value to data. Now I've found simple errors are
  usually found last, after complex errors. And not until a set a break point
  like:

             clc
             lda value
             adc data    <-----Missing Instruction after here-------------+
             bne +                                                        |
             inc data+1                                                   |
           + BRK                                                          |
             [.... ]                                                      |   
                                                                          |
  did I actually figure out that I was missing the STA DATA instruction --+

  So, when writing, modifying, and trying to debug code try to take your time
  and isolate every possible problem. Also don't be afraid to stop the code
  mid-stream as in the above with use of the BRK. You can always remove it
  (and probahly should) in the final code and it serves as a very valuable 
  debugging tool with the aid of a machine-language monitor.

  
IX. Memory Map Considerations
    -------------------------

  Before you start a program it's a good idea to consider where in memory you
  will have everything. Now we've already started some of the program above
  and just blindly picked numbers at random it seemed like $3000 for the 
  character set for the C=64 etc... We didn't - I'm introducing the Memory
  Map Considerations here to show the example of what if we didn't think
  about how memory was going to be organized.

  The C=64 only has 64k of memory of which typically the range $0800-$a000
  is available and $c000-$cfff is also.  If we had blindly picked numbers
  all over the place to store our code then we would have a disorganized
  program that would most likely accidentally use one subroutines storage
  as temporary data for another. It's like shooting randomly in Laser Tag
  not checking to see if there is a target there or not first... The end
  result: Chaos.

  Currently we're not following the rule for "temporary variables" but as
  we gradually fade out of the normal C-64/128 default mode and write our
  own routines / interrupt handlers we'll switch things over. Also, on the
  C=128 instead of using Bank 0 with the I/O block enabled we're currently
  using the BANK 15 configuration as the program doesn't extend past $4000
  yet ($0000-$4000 is common memory in the normal C=128 configuartion).

  64 Considerations
  -----------------
  The 64 will have free memory in the following areas: $0800-$a000, and
  $c000-$cfff. However, if we disable the Basic Rom we can have the whole
  area from $0800-$cfff free for our program. Because we don't need the
  Basic Rom we will do just that (in the listing now we currently won't but 
  it will be done in a future issue). Therefore having the character set
  at $3000-$5000, the music data at $5000-$8000, the program will have the
  area free from $8000-$cfff. $0800-$3000 will be available if needed for
  routines who need temporary storage. 

  Temporary Storage is going to be defined as follows. Each routine that needs
  temporary storage will be assigned a "level" number. The lower levels will
  be assigned level 1 on up to level 3. The range $0800-$3000 will be 
  broken down into the following sub-ranges.

       Level 1: $0800-$1000
       Level 2: $1000-$1800
       Level 3: $1800-$3000
  
  This way when writing the sub-routines we can be assured that a section of
  memory is not overwritten by a subroutine we call. When we actually start
  programming we'll decide where in each sub-range the routine will have 
  access to.

  128 Considerations
  ------------------
  The 128 has two "banks" of 64k each. Normally for large programs we would 
  think about using both banks - (from the idea: Hey! - We got it, why not
  flaunt it?) but we won't be using both banks.

  Free memory on the C128 typically consists of the range $0400-$09ff
  (where we'll be overwriting the 40 column screen (which we're gonna blank
  anyway) and the Basic run-time stack.) Also the area from $0b00-$0fff
  is free (overwriting the tape area, the rs-232 buffers,l and the sprite
  definition area). Also $1300-$cfff will be free. 

  Now, the C=128 has different memory maps it can configure itself to - 
  Bank 15 is the standard mode under most basic programs and allows the
  programmer to directly "sys" to calls. The MMU (memory management unit -
  the chip that does everything) sees memory in a slightly differant way
  than from basic. We'll cover it in more detail when we examine the mem_init
  routine. For now, we're just gonna set up in the program and not in the
  coding segments. The explanation of what we're doing will be "revealed"
  in a future issue. 

  We will use Bank 0 of memory and from $1300+ will be the program. The ranges
  of $0400-$09ff and $0b00-$0fff will be used in a similair mannar as the C64
  ranges were for Temporary Storage. We will also have the I/O section from
  $d000-$dfff swapped in. This is not a standard "basic BANK #" but when we
  cover the init'memory routine we'll see how we can do this. Music data
  will be from $a000-$d000. 
  

X.  Looking Forward / Back
    ----------------------

  Hopefully through the listing and the discussion of the routines you have
  started to understand the basic concept of programming: breaking down problems
  into smaller solvable steps. Try looking back over the code asking yourself
  why that instruction is there. What would happen if you switched the order?
  Is there an easier, better way to do the same thing? Why? Better yet, how?
  Examine the code, mess with it, muck it up so it doesn't work and then figure
  out exactly why. The only way to learn is by experimentation. (BTW, muck up
  a _copy_ of it - not the original ... *grins*)

  Take a look at the different sections of code and analyze them to see how
  they do what they do. Take a look at how the code was organized in terms
  of simplification. Trace through each subroutine so that you're able to 
  know what the return values will be. In other words: Study, Study, Study!!
  I'm in school and so I know I just used the dreaded 'S' word but that's 
  what you're going to have to do if you're interested in learning 65xx/85xx
  machine language. The only way to learn it (easily) is to study other 
  people's code and try to understand why they did what they did.

  Next time we will take a look at the input routines for the mouse, joystick
  and keyboard scanning. In addition we will also allow the player to move
  the ship around on the screen to test the input drivers. 

  In addation, I am still looking for an individual to help with music and
  sound composition for this program. A knowledge of the SID chip and 
  programming is helpful but not required. If you're willing to help then
  please email me at duck@pembvax1.pembroke.edu


XI. Listings
    --------

  Because of the enormity of the program listing (some 1,500+ lines) it will 
  not be listed in this article but will instead be available via anonymous
  ftp at ccosun.caltech.edu under pub/rknop/HACKING.MAG as invas1.sfx. 

  For those of you on the mailing list who would like to recieve it, a Mail-
  Server will be set up soon to handle requests and information will be
  sent to you concerning information about using it as soon as it's completed.

  In the invasion1.sfx file there are the following files:

       invasion.src - the main file
       graphics.src - handles all graphics routines
       logo.dat     - custom character logo
       chars64.dat  - alien custom characters for C=64
       chars128.dat - alien custom characters for C=128
       titletxt.dat - text data for title screen
       titlecol.dat - color data for title screen
       invasion-128 - executable version of Space Invasion so far for C=128
       invasion-64  - executable version of Space Invasion so far for C=64

  Note: For the Commodore 128 it's recommended that you do a run/stop-restore
  and then a "BANK15:SYS7168" to execute the program. For the Commodore 64 it's
  recommended the border be changed via: "POKE53280,0:POKE53281,0:SYS 32768" to
  run the program.
 
==============================================================================
The Demo Corner:

FLI - more color to the screen   
by Pasi 'Albert' Ojala (po87553@cs.tut.fi or albert@cc.tut.fi)
                        Written on 16-May-91   Translation 01-Jun-92
    
(All timings are in PAL, altho the principles will apply to NTSC too)

All of us have heard complaints about the color constraints on C64. One 8x8
pixel character position may only carry four different colors.  FLI picture
can have all of the 16 colors in one char position.  What then is this FLI
and how it is done ?

In the normal multicolor mode can one character position (4x8 pixels) have
only four different colors and one of them is the common background color.
Color codes are stored in half bytes (nybbles) to the video matrix memory
(anywhere video matrix pointer points at, normally $0400) and to the color
memory ($D800-$DBFF). In multicolor mode the color of each pixel is
determined by two bits in the graphics memory. Bit pair 11 will refer to
color memory, background color is the color for bit pair 00, and video
matrix will define the colors for bit pairs 01 and 10.


_What happens in the VIC ?_

VIC (Video Interface Controller) fetches color information from memory on
each bad line. This will steal time from processor, because VIC needs to use
processor's bus cycles. Bad line is a curse in the C64 world. Fortunately
VIC's data bus is 12 bits wide and so the color data fetch for each character
position will take only one bus cycle. Color memory is physically wired to
the VIC databus lines D8-D11.

How does VIC know where to fetch the graphical information ? Some of you know
the mystical formulas needed to mess with the pixels in the hires screen.
How are these functions obtained ? Are they just magic ? No, there are some
internal counters in VIC. They always point to the right place in grafix
memory and the address is determined like this:

A13  A12 A11 A10 A9  A8  A7  A6  A5  A4  A3  A2  A1  A0
CB13 VC9 VC8 VC7 VC6 VC5 VC4 VC3 VC2 VC1 VC0 RC2 RC1 RC0

Address bits A15 and A14 change according to the selected video bank.
Address bit A13 is CB13, which may be found in VIC register $18. It
selects the right side of the video bank to be the bitmap memory. With
these bits you can set the bitmap to eight different places in memory.
However, some of them are useless because of the character ROM images and
zero page/stack. Rest of the bits come from the internal counters.

VC9-VC0 (Video Counter) forms the address bits 12-3. The counter rolls
through all 1000 character positions, 0-39 on the first eight lines, 40-79
on the second eight lines and so on. The lowest three bits come from the row
counter, RC2-RC0. This is another VIC counter and it counts the scan lines
from zero to seven.


_A software graphics mode - FLI_

VIC will systematically go through every byte in the bitmap memory, but how
does it know where and when to get the color information ? This is where
the main principle of FLI (Flexible Line Interpretation) lies. Color data
is fetched (and this means it is a bad line), when the line counter matches
with the vertical scroll register. VC9-VC0 defines where the color data is
inside the video matrix and color memory.

If we change the vertical scroll register, we can fool VIC to think that
every line is a bad line, so it will fetch the color information on every
line too. Because VIC will fetch the colors continuosly, we can get
independent colors on each scan line. We just have to change colors and VIC
will handle the rest. Unfortunately the result is the loss of 40 processor
cycles per line (see the Missing Cycles article for more information about
VIC stealing cycles).


_Doing it in practice_

In practice there is no time to change color memory, but in multicolor
mode VIC uses video matrix for color information too. We have just enough
time to change the video matrix pointer, $D018. Now VIC will see a
different video matrix on each scan line, different block of memory. With
the four upper bits in the register we select one of the 16 video memories
in the video bank. Just remember that the register also selects the position
of the graphics memory (bitmap) inside the video bank.

Because we have to keep the bitmap in the same video bank, we only have half
of the bank free for video matrices. Fortunately, that's all we need to get
individual multicolor colors for each line and character position.
VIC will fetch the color data from the eight video matrices and then it will
roll on to the next 40 bytes. After eight lines and matrices we will select
the first video matrix again. (See picture 1)

Usually it is not necassary to use the whole screen for a FLI picture,
especially if you want to have a scroller or some other effects. You just
have to make sure that VIC is foolable in the usual way. The timing is also
very important, even one cycle variations in the routine entry are not
allowed. There is many ways to do the synchronization. One way is to use a
sprite, as in the previous article. (See C= Hacking, Vol. 1, Iss. 3, The
Demo Corner: Missing Cycles).


_Not much time_

Because a bad line will steal 40 cycles, there is only 23 cycles left on
each scan line. It is enough for changing the video matrix and backgroud
color. There is not a moment to lose, because you must change the vertical
scroll register, video matrix pointer and the background color. This is why
you can't have sprites in front of a FLI picture.

With FLI we get two selectable colors for each character position and line,
each scan line can have it's own background color and each character position
still has its own character color from color memory. In theory each character
position could have 25 different colors, unfortunately VIC only has 16.


_A little feature_

VIC does not like it when we change the vertical scroll register ($D011),
and is a bit annoyed. It 'sees' code 255 (light gray) in video matrix
and 9 (brown) in the color memory instead of the correct values stored there.
Actually the color value seems to be the lower nybble of the data byte
currently on the data bus (accessed by the processor (LDA#=$A9)).
Unfortunately there is no chance to do the register change in the border
and thus the three leftmost character columns are a bit useless, because
the colors are fixed.

However, this doesn't mean that you can't use those three columns. FLI
editors may not support the fixed colors though, so it may be hard to use
them.


_What to do with FLI ?_

Because FLI will eat up all the available processor time (no Copper :-),
it is not suitable for any action-games. Each FLI picture takes about 17 kB
of memory: not so many pictures fit on one floppy. So, the only place for FLI
is demos, intros, board-type games and maybe a GIF viewer..

--------------------------------------------------------------------------
Picture 1: From which matrix VIC fetches the multicolor values

 _          ___________________________________________________________
|      ... | Matrix0       | Matrix0       | Matrix0       |
|      ,  .|____3__________|____4__________|____5__________|  ...
|       U .| Matrix1       | Matrix1       | Matrix1       |
|       s .|____3__________|____4__________|____5__________| .
|Char   e  | Matrix2       | Matrix2       | Matrix2       | .
|Line   l  |____3__________|____4__________|____5__________| .
|Zero   e  | Matrix3       | Matrix3       | Matrix3       |
|       s  |____3__________|____4__________|____5__________|
|       s, | Matrix4       | Matrix4       | Matrix4       |
|          |____3__________|____4__________|____5__________|
|       c  | Matrix5       | Matrix5       | Matrix5       |
|       o  |____3__________|____4__________|____5__________|
|       l  | Matrix6       | Matrix6       | Matrix6       |
|       u  |____3__________|____4__________|____5__________|
|       m  | Matrix7       | Matrix7       | Matrix7       |
|_      n  |____3__________|____4__________|____5__________|
        s  | Matrix0       | Matrix0       | Matrix0       |
           |___43__________|___44__________|___45__________|
           | Matrix1       | Matrix1       | Matrix1       |
           |___43__________|___44__________|___45__________|
           |
           |   ...
           | .
           | .
           | .

--------------------------------------------------------------------------
_Additional reading_

If you have an Amiga you might want to get your hands into my conversion
programs in C64GFX1.lha. The packet also includes FLI viewer for PAL C64's
and some documentation about the FLI file format. It also has the same
utilities for Koala format pictures.

Available from:
cwaves.stfx.ca
nic.funet.fi:/pub/amiga/graphics/applications/convert


C64GFX.doc
                        C64Gfx1.0
           A C64 grafix format conversion package
           )1991,1992  Pasi 'Albert' Ojala

           E-mail: po87553@cs.tut.fi
                   albert@cc.tut.fi

This package contains programs which are used to convert portable
pixmap (ppm) files to C64 graphics formats (FLI and koala) under
AmigaOS. The package includes C source codes for the programs, so
it is possible to port the programs to another environment. C64GFX1.1
includes Unix-compilable sources.

In addition to this package you need e.g. PBMPlus to convert Amiga
ilbm files to ppm first. And of course some way to transfer files
between the machines.

=============================================================================
RS-232 Converter
by Warren Tustin (warren@col.hp.com)

  This article presents a way to interface from the C= rs232 hardware
behind the user port to a standard 25pin female rs232 connector using only
one IC and a few capacitors.  It is not a UART or a SWIFTLINK type interface
which take place of the internal C= rs232 circuitry, but a simple level shifting
interface that uses the internal rs232 routines and translates the user port
levels to rs232 levels.  Therefore you can only get upto 2400baud/9600baud
(C=64/C=128) with this design.

  The "old" way to do this was to used MC1488 and MC1489 parts (a line
driver and line receiver), however these required a negative supply to interface
properly.  The user port only supplies +5volts, hence this presents a problem.
There has been success using these parts or discrete transistors and resistors
since many modems are somewhat friendly and seem to work even though the levels
were marginal.  Also, some signals were not used, allowing for potential
problems.  Another way to solve this problem was to buy a $25-30 interface.  If
you can find the IC below, you have another choice that is relatively
inexpensive.

   The LT1133 is basically the MC1488 and 1489 put together into one part
with an internal charge pump scheme that allows the internal drivers to output
+5 and -5 volts to the rs232 connector.  It also has enough drivers and
receivers to handle all of the signals that the C= uses for rs232.

   So with this IC, 5 capacitors and the two connectors (user port and
rs232) you can build your own interface to the standard 25 pin modem cable.

   Here are the plans for an User port TO RS232 connector using just ONE IC and
4 capacitors.  It uses a Linear Technology LT1133 buffer that has 3 RS232
drivers and 5 receivers.  It has worked for me with no problems and takes
a minimum amout of wiring to get to work.  My board is only the width of
the user port and about 1.5 inches deep in size.

Parts list:
----------
     LT1133CN plastic dip or LT1133CJ ceramic dip RS232 driver from Linear
        Technologies

        (It takes 27mA max (17mA typical) so is well below the 100mA 
         limit of the user port)

         Driver In pins  (15,19,21)  TTL/CMOS compatible.  Unused inputs
                           |  |  |   should be tied to +5v.
         Driver Out pins (11, 7, 5)  RS232 compatible.  Short circuit 
                                     protected from -30v to +30v.
         Receiver In pins  (6, 8, 9, 10,12)  Accept RS232 levels (+-30v)
                            |  |  |   |  |   and have 0.4v of hysteresis to
                            |  |  |   |  |   provide noise immunity.
         Receiver Out pins (20,18,17,16,14)  TTL/CMOS outputs.

         NOTE: Lines above indicate which inputs go with which outputs, and
               the pairs can be interchanged freely.  I connected them as
               described below because the wiring worked out the best for me. 

     4 - >= 1uF capacitors   Used to generate RS232 voltages by a charge pump
                             technique inside IC
     1   1uF capacitor  To bypass the 5volt supply for noise rejection.

     1   User port female connector.  (I just dug this up, I'm not sure 
         where these can be found, I think it is 0.159" spacing, 24pin.

     1   RS232 25pin female connector.  Can be found at R-Shack
        
     Some sort of .1" spacing proto board

Connections:
-----------

  User port connector (Looking into the C64 or C128)

         1  2  3  4  5  6  7  8  9 10 11 12
        ------------------------------------
        |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|
        ------------------------------------
         A  B  C  D  E  F  H  J  K  L  M  N

Ground & Power:
--------------

  Pins 1, A, 12, N to Ground of board.
  LT1133 pin 2 to pin 2 of User port connector (+5 volts)
  1uF capacitor between pin2 and ground (bypass cap)
  LT1133 pin 13 to Ground.
  RS232 connector pins 7 & 1 to Ground.
 
LT1133 capacitors:
  1uF from pin 1 (V+) to ground  (If polarized (electrolytic) + side to pin 1)
  1uF from pin 24 (V-) to ground (As above but + side to ground)
  1uF from pin 3 (C1+) to pin 4 (C1-) (Again if polarized, + side to pin 3)
  1uF from pin 22 (C2+) to pin 23 (C2-) (Again if polarized, + side to pin 22)
    

    Commodore side                                       RS232 side
  User port    Signal    Pin of       Signal        Pin of       RS232
  pin          name      LT1133      direction      LT1133       connector
  ---------    ------    ------      ---------      ------       ---------
   B  FLAG2     Din        20         <--             6              3
   C   PB0      Din     also connect to above pin 20
   D   PB1      RTS        21             -->         5              4
   E   PB2      DTR        19         <--             7              20
   F   PB3      RI         18             -->         8              22
   H   PB4      DCD        17             -->         9              8
   J   PB5      Not used
   K   PB6      CTS        16             -->         10             5
   L   PB7      DSR        14         <--             12             6
   M   PA2      Dout       15             -->         11             2


This assumes that you want to connect all of the communication lines.  I did
it this way because the C128 programmers reference guide had all of the signals
above listed.  If you want to drop RI (ring indicator) you could also use an
LT1134 which has 4 drivers and 4 receivers.

Parts Substitution:

   There are other IC's available which will work in this application.
The rs232 bus levels for the LT parts are spec'ed at ~ +/- 7v typical, while
the MAXIM parts are +/-9v typical.  (Both are min at +/- 5v which should work
in all applications).  I think that an interface can be done with only 3
lines, Din(Rx), Dout(Tx), and either DSR or CTS, so if you can't get the
LT1133 one of these others might work, although the pinouts would be different.
The max you would need is what the LT1133 supplies, 3 drivers & 5 receivers.

Here is a description of parts that might be substituted:
(Note, with all of them you should use a bypass cap on the +5v supply which
 I have NOT included in the counts below.)

                 RS232     RS232    # of EXTERNAL
NAME     PINS   DRIVERS  RECEIVERS       CAPS       COMMENTS
-------------------------------------------------------------------------
Linear Technology parts...
(On the parts with shutdown (SD), the pin must be tied to +5 to operate)
LT1133    24       3         5             4        In article above
-------------------------------------------------------------------------
LT1130    28       5         5             4        Overkill (SDp14)
LT1131    28       5         4             4        2 ex Dr, 1 < Rcvr
LT1132    24       5         3             4        2 ex Dr, 2 < Rcvr
LT1134    24       4         4             4        1 < Rcvr
LT1136    28       4         5             4        1 ex Dr  (SDp14)
LT1137    28       3         5             4        SDp13
LT1138    28       5         3             4        LT1132 w/SDp13

MAXIM parts... (Some also have a TTL EN_ pin that must be tied to 0v to operate)
               (On these parts, SD must be tied to 0v to operate!)
MAX232    16       2         2             4        May work
MAX233    20       2         2             0!       No external caps
MAX235    24       5         5             0!       Overkill, but NO caps,
                                                    SDp21, EN_p20
MAX236    24       4         3             4        1 ex Dr, 2 < Rcvr,
                                                    SDp21, EN_p20
MAX237    24       5         3             4        2 ex DR, 2 < Rcvr
MAX238    24       4         4             4        1 ex DR, 1 < Rcvr

  In summary, you can see there are many different parts you could use,
especially if you don't need all the signals.  The MAXIM parts seem to
do the job in fewer pins and a little better typical drive spec and I
would recommend the MAX235 overall since you only need 1 bypass cap to
make it operate!

=============================================================================
Introduction to the VIC-II
by Pasi 'Albert' Ojala ( ... )

The Video Interface Controller used in C64 have several different operating
modes and different graphical primitives. Basically there is a) character
mode, b) bitmap mode and c) movable objects that can be mixed with the
other graphics. These primitives can also be put into a more colorful mode,
but you lose half of the resolution in that process.


I. Standard Character Display Mode

In the character display mode, VIC fetches character pointers from video
matrix, which consists of 1000 8-bit bytes formatted as 25 rows of 40
characters each. The 8-bit character code implies 256 different characters
simultaneously onscreen.

Each character code can have an unique image, which consists of 8 bytes in
character memory. The position of the character memory can be moved with the
character base pointer and thus it is possible to have several character sets
simultaneosly in memory. One character memory is 2048 bytes.

In addition to the character code, each position in video matrix has an
associated color nybble (4 bits) in color memory ($D800-$DFFF). For each
zero-bit in the charset the background color from register $21 is displayed,
the color-nybble is used for the one-bit.


II. Character Multicolor Mode

In character multicolor mode, color selection is increased. Each byte is
fetched from the character memory just like in the standard character mode,
but they are interpreted differently. In this mode bytes are divided into
bit-pairs. For bit pair "00" the background color from register $21 is
displayed, background color #1 is used for bit pair "01" and background
color #2 for bit pair "10". The color nybble will define the color for bit
pair "11".

The highest bit in the color memory defines whether the character is to be
displayed in multicolor ("1") or in standard mode ("0"). Because of this,
only colors in the range from 0 to 7 are possible for bit pair "11". And since
two bits are required to specify one dot color, the character is now displayed
as a 4x8 matrix instead of the 8x8 matrix and the size of the dots are doubled
horizontally.


III. Extended Color Mode

The extended color mode allows the selection of one background color from four
possibilities for each character position in the normal 8x8 resolution. The
character image data is processed like in standard character mode, but the
two most significant bits in the character code (video matrix) are used to
select the right background color register. Only character images from 0 to 63
are accessible, because two of the most significant bits are used for the
background color selection.

Extended color mode and multicolor mode should not be selected simultaneosly,
because this will result a black screen. However, this is a very easy way to
hide something if needed.


IV. Standard Bit Map Mode

In bit map mode, a one-to-one correspondence exists between each displayed
dot and a memory bit. The bit map provides a resolution of 320H x 200V
individually controlled pixels. The video matrix is still accessed as in
character mode, but the data is interpreted as color data. When a bit is "0"
in the bit map data, the color from the lower nybble is selected. The
higher nybble from the video matrix is used for the bit "1".


V. Multicolor Bit Map Mode

In multicolor bit map mode two bits in the bit map memory determine the color
of one pixel. If the bit pair is "11", the color found from the color memory
is used. The background color is used for bit pair "00" and the video matrix
defines the colors for bit pairs "01" and "10". As it takes two bits to define
one pixel color, the horizaontal resolution is halved to 160H x 200V.


VI. Movable Object Blocks (MOBs)

The movable object block is a special type of graphical object which can be
displayed independently from the other graphics. Each one of the MOBs can
be moved independently anywhere in the screen. Eight unique MOBs can be
displayed simulataniously, each defined by 64 bytes in memory which are
displayed as a 24 x 21 pixel array.

Each MOB can be selectively enabled (MnE="1") or disabled (MnE="0"). A MOB
is positioned via its X and Y position registers. Nine bits are needed to
define the vertical position and the most significant bits of all MOBs are
stored in the register $10. As X locations 23 to 347 and Y locations 50 to
249 are entirely visible on the screen, MOBs can be smoothly moved to an
off-screen position.

Each MOB has its own color register and a MOB can be displayed either in
standard or multicolor mode (MnMC="1"). As usually, multicolor mode gives
more colors, but halves the horizontal resolution. In multicolor mode bit
pair "00" is transparent, the MOB color register defines the color for pair
"10", and MOB multicolor registers give the colors for pairs "01" and "11".

MOBs can be selectively expanded in both directions. When MOB is expanded,
the pixel size also expands and it is still displayed as 24 x 21 matrix
(12 x 21 in multicolor mode).

MOB priorities define whether a MOB appears behind or on top of the character
or bit map graphics. A "1" in MnDP means MOB is displayed behind. MOB
collision registers may be used to detect if a non-transparent data of two
MOBs or a MOB and character or bitmap foreground data is colliding.

[Ed's Note: MOB's are Sprites. Commodore initially referred to them as MOB's
and still does in some areas.]


VII. Other features

The display screen may be blanked by setting the DEN bit to a "0". The entire
screen will be filled with the border color as set in register 32 ($20).
When the screen is blanked, VIC will need only transparent memory cycles and
the processor is not slowed down. However, MOB data is still fetched, if
the MOBs are not also disabled.

The normal display consists of 25 rows of 40 characters each. The display
window can be reduced to 24 rows and 38 characters. This has no effect on how
the data is interpreted, only the characters next to the border are covered
by the border. RSEL controls the number of rows ("1" for 25 rows) and CSEL
controls the number of columns ("1" for 40 columns).

The display data may be scrolled up to one character space in both vertical
and horizontal direction. Position of the screen is set with the 3 lowest
order (least significant) bits in registers 22 ($16) and 17 ($11).

Light pen latch is used to catch the position of the light pen when a pulse
is received in the LP pin. The value is latched only once in a frame.

The raster register is a dual-function register. A read from the raster
register returns the current raster position and a write to it will set the
raster compare value. When the written value and the current raster line
matches, a raster interrupt is generated if enabled. Raster register has its
most significant (9th) bit in register 17 ($11).

The interrupt register shows the status of the four sources of interrupt.
A corresponding bit will be set to "1" when an interrupt source has generated
an interrupt request. To enable an interrupt request to set the /IRQ output
to zero, the corresponding enable bit in register 26 ($1a) must be set to
"1". The interrupt latch may only be cleared by writing a "1" to the
desired latch in the interrupt register.

-----------------------------------------------------------------------------
VIC register map (Base address $d000)

Address DB7   DB6   DB5   DB4   DB3   DB2   DB1   DB0   Description
-------------------------------------------------------------------
00 $00  M0X7  M0X6  M0X5  M0X4  M0X3  M0X2  M0X1  M0X0  MOB 0 X-position
01 $01  M0Y7  M0Y6  M0Y5  M0Y4  M0Y3  M0Y2  M0Y1  M0Y0  MOB 0 Y-position
02 $02  M1X7  M1X6  M1X5  M1X4  M1X3  M1X2  M1X1  M1X0  MOB 1 X-position
03 $03  M1Y7  M1Y6  M1Y5  M1Y4  M1Y3  M1Y2  M1Y1  M1Y0  MOB 1 Y-position
04 $04  M2X7  M2X6  M2X5  M2X4  M2X3  M2X2  M2X1  M2X0  MOB 2 X-position
05 $05  M2Y7  M2Y6  M2Y5  M2Y4  M2Y3  M2Y2  M2Y1  M2Y0  MOB 2 Y-position
06 $06  M3X7  M3X6  M3X5  M3X4  M3X3  M3X2  M3X1  M3X0  MOB 3 X-position
07 $07  M3Y7  M3Y6  M3Y5  M3Y4  M3Y3  M3Y2  M3Y1  M3Y0  MOB 3 Y-position
08 $08  M4X7  M4X6  M4X5  M4X4  M4X3  M4X2  M4X1  M4X0  MOB 4 X-position
09 $09  M4Y7  M4Y6  M4Y5  M4Y4  M4Y3  M4Y2  M4Y1  M4Y0  MOB 4 Y-position
10 $0a  M5X7  M5X6  M5X5  M5X4  M5X3  M5X2  M5X1  M5X0  MOB 5 X-position
11 $0b  M5Y7  M5Y6  M5Y5  M5Y4  M5Y3  M5Y2  M5Y1  M5Y0  MOB 5 Y-position
12 $0c  M6X7  M6X6  M6X5  M6X4  M6X3  M6X2  M6X1  M6X0  MOB 6 X-position
13 $0d  M6Y7  M6Y6  M6Y5  M6Y4  M6Y3  M6Y2  M6Y1  M6Y0  MOB 6 Y-position
14 $0e  M7X7  M7X6  M7X5  M7X4  M7X3  M7X2  M7X1  M7X0  MOB 7 X-position
15 $0f  M7Y7  M7Y6  M7Y5  M7Y4  M7Y3  M7Y2  M7Y1  M7Y0  MOB 7 Y-position
16 $10  M7X8  M6X8  M5X8  M4X8  M3X8  M2X8  M1X8  M0X8  MSB of X-position

17 $11  RC8   ECM   BMM   DEN   RSEL  Y2    Y1    Y0    (See text)
18 $12  RC7   RC6   RC5   RC4   RC3   RC2   RC1   RC0   Raster register
19 $13  LPX8  LPX7  LPX6  LPX5  LPX4  LPX3  LPX2  LPX1  Light Pen X
20 $14  LPY7  LPY6  LPY5  LPY4  LPY3  LPY2  LPY1  LPY0  Light Pen Y
21 $15  M7E   M6E   M5E   M4E   M3E   M2E   M1E   M0E   MOB Enable
22 $16  -     -     RES   MCM   CSEL  X2    X1    X0    (See text)
23 $17  M7YE  M6YE  M5YE  M4YE  M3YE  M2YE  M1YE  M0YE  MOB Y-expand
-- 

- Craig Taylor   || Standard Disclaimer Applies (of course!)
duck@pembvax1.pembroke.edu (Pembroke State University)

Oregon, n.:
	Eighty billion gallons of water with no place to go on Saturday
	night.