MISC. VIC 20 NOTES/TRICKS/QUICKREF - ae/June 2002




MULTICOLOR


Bits    Color           Range           Register

%00     background      $00-$0f         $900f   high nybble
%01     border          $00-$07         $900f   bits 0-2(*)
%10     character       $00-$07         -       color ram(**)
%11     auxiliary       $00-$0f         $900e   high nybble

* bit 3 in $900f selects reverse mode (0=reverse 1=normal). Reverse only
  affects hires characters, multicolor bit patterns are not changed

** bit 3 in color ram selects multicolor (0=hires 1=multi)




GRAPHICS MEMORY


High nybble in $9005 and bit 7 in $9002 select the screen matrix
address:

$9005   Screen
Value   Matrix          (add $0200 if bit 7 in $9002 is set)

$8x     $0000           ($0200)
$cx     $1000           ($1200)
$dx     $1400           ($1600)
$ex     $1800           ($1a00)
$fx     $1c00           ($1e00)

Other values are unusable because they either address the character
ROM or unconnected address space.


Bit 7 in $9002 also selects the color RAM used:
        
0       $9400
1       $9600


Low nybble in $9005 selects the character generator address:

$9005   Character
Value   Generator

$x8     $0000           ($0400-$0fff unusable)
$xc     $1000
$xd     $1400
$xe     $1800
$xf     $1c00           (reads 128-255 from character ROM)

$x0     $8000           Character ROM
$x1     $8400
$x2     $8800
$x3     $8c00

Other values are unusable.



Related bugs in VICE 1.8 xvic:

Bit 7 in $9005 is ignored (works as if it's always set). Values $0x-$7x
address RAM in VICE but ROM or unconnected address space on a real VIC.

3K memory expansion area $0400-$0fff is not accessible by VIC but seems to
work in VICE.

Color RAM at $9400-$97ff is only 4 bit memory (high nybble reads garbage).
In VICE it works like 8 bit memory.




KEYBOARD SCAN MATRIX


                                  $9120
             +-----+-----+-----+-----+-----+-----+-----+-----+
             |Bit 7|Bit 6|Bit 5|Bit 4|Bit 3|Bit 2|Bit 1|Bit 0|
       +-----+-----+-----+-----+-----+-----+-----+-----+-----+
       |Bit 7|  F7 |  F5 |  F3 |  F1 |C_U/D|C_L/R|  CR | DEL |
       +-----+-----+-----+-----+-----+-----+-----+-----+-----+
       |Bit 6|HOME | A_UP|  =  | S_R |  /  |  ;  |  *  |    |
       +-----+-----+-----+-----+-----+-----+-----+-----+-----+
       |Bit 5|  -  |  @  |  :  |  .  |  ,  |  L  |  P  |  +  |
       +-----+-----+-----+-----+-----+-----+-----+-----+-----+
       |Bit 4|  0  |  O  |  K  |  M  |  N  |  J  |  I  |  9  |
$9121  +-----+-----+-----+-----+-----+-----+-----+-----+-----+
       |Bit 3|  8  |  U  |  H  |  B  |  V  |  G  |  Y  |  7  |
       +-----+-----+-----+-----+-----+-----+-----+-----+-----+
       |Bit 2|  6  |  T  |  F  |  C  |  X  |  D  |  R  |  5  |
       +-----+-----+-----+-----+-----+-----+-----+-----+-----+
       |Bit 1|  4  |  E  |  S  |  Z  | S_L |  A  |  W  |  3  |
       +-----+-----+-----+-----+-----+-----+-----+-----+-----+
       |Bit 0|  2  |  Q  |  C= |SPACE| R/S | CTRL|A_LFT|  1  |
       +-----+-----+-----+-----+-----+-----+-----+-----+-----+

C_L/R = Cursor left/right;  C_U/D = Cursor up/down
S_L = Shift, left  ;  S_R = Shift, right  ;  R/S = RUN/STOP
A_UP = Arrow up    ;  A_LFT = Arrow left


Example:

lda     #%11111110              ; scan key column '13579+DEL'
sta     $9120

lda     $9121                   ; check key '7'
and     #%00001000
beq     key7down




RASTER INTERRUPT


VIC 20 has no raster interrupt but you can generate a timer interrupt exactly
once a frame by setting $9126/$9127 to $5686 (PAL).

There are at least two methods to achieve cycle exact timing. You can use two
timers where the other timer counts the error. Or, trig the light pen, read
the x-coordinate from light pen registers, then wait the appropriate number
of cycles.




VIA TRICK

$9110-$911f     VIA #1
$9120-$912f     VIA #2
$9130-$913f     Writes to both VIA's at the same time
                (or reads from both anded)




VERTICAL SMOOTH SCROLL


Register $9001 sets vertical position of screen with two pixel granularity.
The values are equal to those read from the raster counter register $9004.

Odd raster line placement is possible with the following code:

1) first place the screen one pixel below the desired position
2) wait until the raster counter reaches the line two pixels above that
3) dec $9001

The drawing of screen is then delayed by one raster line.

Example:

1100 sei
1101 ldy #$02
1103 tya
1104 jsr $1113
1107 ldx #$90
1109 cpx $9004
110c bne $1109
110e iny
110f bne $1103
1111 beq $1101

1113 lsr                ; subroutine: set top of screen to a (2-255)
1114 tax
1115 bcs $111e
1117 jsr $111e
111a dec $9001
111d rts
111e stx $9001
1121 dex
1122 cpx $9004
1125 bne $1122
1127 rts

This doesn't work in VICE 1.9 unless you add a small delay there:

1127 ldx #$08
1129 dex
112a bne $1129
112c rts


There's also another method to do one pixel vertical scrolling but it is more
limited. You need two screens, the other one shifted right by one char.

Setting $9000 to $00 starts drawing the screen one pixel late.

Setting $9000 to $02 starts drawing at the normal position and, compared to
$00, horizontally moved to right by one character. You can compensate this
movement by using the other screen.

This doesn't work in VICE 1.9.




FREQUENCY TABLE


Suggested note frequency table with perfectly tuned octaves:

C-1     131             C-2     193             C-3     224
C#1     137             C#2     196
D-1     145             D-2     200
D#1     151             D#2     203
E-1     157             E-2     206
F-1     163             F-2     209
F#1     167             F#2     211
G-1     173             G-2     214
G#1     177             G#2     216
A-1     181             A-2     218
A#1     185             A#2     220
B-1     189             B-2     222

(PAL A = 468 Hz, NTSC A = 432 Hz)




DETUNE/PULSE MODULATION SOUND


The example below uses two oscillators to produce a sound similar to pulse
width modulation:

onceaframe:
        lda     #193                    ; c-2
        sta     $900a                   ; $900a plays octave below $900b

        lda     #131+modspeed           ; c-1 + modulation speed
        sta     $900b

        ldx     #$40                    ; run oscillators out of sync for
_delay                                  ; a short time
        dex
        bne     _delay

        dec     $900b                   ; oscillators back in sync
