                            _Bonkers_

Level #03
                        (c) Curtis White

         FREEWARE: NO SALE OF THIS MAGAZINE IS ALLOWED WITHOUT
                    PRIOR WRITTEN PERMISSION.

This time we have a ton of stuff that we will be covering! We will make
the leap from the monitor to the assembler, start building our library
of routines, and maybe learn a few more instructions. No time to waste;
let's venture on!
                                                     The Bonker's Staff

Editor: Coolhand             < Send your opinions, thanks,
Technical Dude: Dokken       < and gripes to these clowns!
Author: Light                <
Support Web Site:       
http://soho.ios.com/~coolhnd/bonkers/planet.htm


Stage #01 Info Highway equals one way street and 23,000 cars going in
both directions.

First, we have been coding in the machine language monitor which, as we
know, is used primarily for viewing and changing memory locations. Now,
we will be coding in an assembler, which will allow us to edit and
understand our code better by using labels, directives, comments, and
symbols.

There are several good assemblers for the c64/128.  It is not the
purpose of this magazine to determine which is the best for you. But all
of our source code will be Turbo Assembler compatible; we will list some
common Turbo Assembler commands below, followed by common assembly
terms.

+----------------------------------------------------------------------+
|                       Turbo Assembler Commands                       |
+----------------------------------------------------------------------+

LEFT ARROW 2 - Comment line.
LEFT ARROW 3 - Assemble to memory.                       
LEFT ARROW 5 - Assemble to disk.                       
LEFT ARROW 1 - Return to basic.                        
LEFT ARROW S - Save source to disk in program format.        
LEFT ARROW W - Save source to disk in sequential format.     
LEFT ARROW L - Load source from disk in program format.      
LEFT ARROW E - Load source from disk in sequential format.   
LEFT ARROW INST DEL - Delete line of code

+-----------------------------------------------------------------------+
|                           Common Assembly Terms                       |
+-----------------------------------------------------------------------+

  Assembler: Program that takes source code and produces object code.
             Note each instruction in the source code becomes the same
             object code instruction after it's assembled.

  Constants: As we have already learned, the prefix that determines the
             number base used, like $ for hex and % for binary.

 Directives: These are used to communicate with the assembler. They are
             powerful and they are used frequently.

Expressions: A string of operators (+, /, -, *), NOTE that these are
             performed during assembly and not during run time.
     
      Label: Name for a line of code in the assembler. This is used
             to replace actual addresses that are used in the monitor.

Object Code: The code that the assembler makes and the computer runs.
             Also the code that can be viewed in a monitor.

     Opcode: Machine/Assembly language instruction. Example 
             LDA, STA, BEQ, RTS.

    Operand: Data which the opcode or instruction uses, not all
             instructions have operands.
     
Source Code: The code that you edit in the assembler, includes comments.


Let's get started on our first assembly language program. We will cover
every detail of this short program.

      *= 8192      ; Start address of object code

chrout = $ffd2

printa  lda #"a"   ; get letter a
        jsr chrout ; print letter to screen
        rts        ; return to basic

Note: to run this program either type 'SYS 8192' from BASIC or hit
LEFT ARROW 3 from Turbo Assembler.

First the * is a directive which is used to change the program counter.
The PC (Program Counter) as we know dictates what code is currently
running and going to be executed or run. SYS 49152 sets the program
counter to address 49152. The *= just assigns where our object code will
be placed in memory and usually it is also the start address of our
code.

The = is also a directive which has a variety of uses. In the example
chrout = $ffd2, we assign the address $ffd2 to the label chrout.

Printa is a label which can used just as an address or location is used
in the monitor.

The ; declares that comments are to follow and they are to be ignored
when assembling, hence we can now type the comments in along with the
actual code. The ; (semi-colon) is almost identical to the Basic command
REM.

A Task... (Yeah right, who is going to ever use this?)

The task is to create a simple word processor which will allow us to
leave memos on the computer and then highlight those memos. To use the
program simply SYS 8192 or LEFT ARROW 3 (FOR TASM ONLY) and type your
message (no cursor will be displayed). This sounds like fun so let's do
it!

          *= 8192            ; start address
chrout     = $ffd2           ; KERNAL ROUTINE TO OUTPUT A CHAR
getin      = $ffe4           ; KERNAL ROUTINE TO INPUT A CHAR

;//////////////////Setup Screen

             lda #$93        ;Clear screen char
             jsr chrout      ;Clear it
             lda #$00        ;Color Black
             sta $d020       ;53280 DECIMAL BORDER COLOR
             sta $d021       ;53281 DECIMAL BACKGROUND COLOR

;//////////////////Main Loop

main         jsr wordproc    ;INPUT/OUTPUT
             jsr memodisplay ;HIGHLIGHT BORDER
             jmp main        ;BACK TO MAIN

;//////////////////Word Processor

wordproc     jsr getin       ;KERNAL ROUTINE TO GET CHAR 
             jsr chrout      ;Now output char that getin copied
             rts             ;Return to main loop

;//////////////////Highlight Memo

memodisplay
             ldx #$00        ;Set Index Register X To Value 0
coloop       lda colors,x    ;Get data colors, indexed to X.
             sta $d020       ;Store those colors 2 border
             inx             ;Increase our index
             cpx #9          ;Compare X TO 9 (9 colors) 
             bne coloop      ;Branch coloop until 9 cols
             rts             ;End Subroutine

colors       .byte 6,14,3,7,1,7,3,14,6
                   
Now, it is time to dissect the more interesting parts of the above code.
First, notice the $d020/$d021 (53280/53281). These are memory locations
that will change the entire border or background color of the screen.
Sixteen unique colors are available for us to use (numbers 0 through
15), and it just so happens that zero is the color black.

Also, notice the JSR GETIN. We use this kernal subroutine to get a
character from the keyboard into the A Register. Since the kernal
subroutine CHROUT outputs the character that is stored in the A register
to the screen, we can use these together to copy letters from the
keyboard to the screen.

Notice the JMP (JUMP Instruction). This instruction is similar to the
JSR (Jump Saving Return Address), except that the JMP instruction does
not save the return address. For those who already know BASIC, you can
compare it to the GOTO rather then the GOSUB, as with JSR.

Now, as a quick reminder that we are using an assembler, below is what
the same code looks like in the MONITOR.

<<----------------------- BEGIN MACHINE LANGUAGE CODE
. 8192 LDA #147
. 8194 jsr 65490
. 8197 lda #0
. 8199 sta 53280
. 8202 sta 53281
. 8205 jsr 8214
. 8208 jsr 8221
. 8211 jmp 8205
. 8214 jsr 65508
. 8217 jsr 65490
. 8220 rts
. 8221 ldx #0
. 8223 lda 8235,x
. 8226 sta 53280
. 8229 inx
. 8230 cpx #9
. 8232 bne -11 (223)
. 8234 rts
. 8235 b 6 14 3 7 1
. 8240 b 7 3 14 6 3
<<---------------------- END MACHINE LANGUAGE CODE

Preparing to code a beast..

First, as with programming any computer, the systems architecture will
be of utmost importance when deciding how to achieve the results that we
want. We will not ignore the unique properties of the c64/128; but our
goal is to explain machine language to the beginner.

Inside your c64/128 is a chip called the VIC II. It is responsible for
everything you see on the screen. When we changed the background ($d021)
and border ($d020) colors, we were changing the registers of the VIC II
chip. It has several modes of operation, including high resolution,
medium resolution, character set graphics, extended background color
mode, multicolor mode, and many more features. We will cover those areas
that are important to us, but we will not indulge on these topics. It is
in your interest to learn more about these graphics features, as they
can make some cool effects possible

Anyhow.. there is a mode called EXTENDED BACKGROUND COLOR mode. We can
enable that mode with a basic statement of POKE53265,PEEK(53265)OR64.
Now, if you have it enabled, type the following: lower case a, shifted
a, reversed lower case a, shifted reverse a. As you can see, instead of
getting the normal characters, you can have several background colors.
In fact, we are limited to 64 characters, but we have a total of FOUR
background colors. These are determined by the registers $d021 (NORMAL),
$d022(SHIFTED), $d023 (REVERSED), and $d024 (REVERSE SHIFTED). So normal
characters get their background color from $d021 as usual, shifted
characters get their background color from $d022, and so on.

What if we could get reversed characters with these additional
background colors? Then, cycle the colors in that background color
register, and it would look as if the letters were changing colors. If
you type some reversed text and change the background colors, you see
that the background color shows through the letters. If you fill the
screen with the character color and then cycle the background color, it
looks as if the color of the letters is changing. But, in the normal
text mode we only have two colors (foreground and background), so all
the words would be cycling colors. This is no good if we want to draw
attention to one word or a few words.

Now, with extended background color we can cycle three of the background
registers with different sets of colors and leave one the same. But, it
is not that simple, since we are limited to the first 64 characters.
These are the normal characters and are not reversed. The character
color would not change, and it would look as if the background colors
were changing. This could be used to draw attention to words or letters.
But I'd rather have the colors cycling inside the letters, wouldn't you?

So are we at a dead end? No! We can use what is called a custom
character set. The characters are stored in ROM. The first 64 characters
just happen to be the normal characters (not reversed like we need). The
ROM character set is located at 53248 to 56832. Notice that these
locations are the same as the VIC II chip's registers. The VIC II can
swap memory in and out without much trouble; how the heck we don't care!
But, if we swap out the VIC II and copy those locations to RAM and tell
the VIC II to look in ram and not ROM for the characters, we can get our
custom character set which equals reversed characters with the extended
background color mode!

So, being the all powerful coder that I am. I know that 54272 through
54272+512 contain the sixty four reversed characters that we need. You
can arrive at the 512 by multiplying 8 bytes of memory for each
character times 64 characters. Really though, I never bother typing in
numbers or code or anything - the tech dude does all the work. Below is
what this looked like before the tech dude changed it.

(DIAG A1)
So *insert arrogant words here*. I know that *tech word* through *tech
word* will *explanation*. *Humble reader* *tech word*. Really though, I
never bother *action* in numbers or *whatever* the tech dude does all
the work. *REF DIAG A1* is what this looked like *REF DIAG A1* the tech
dude *action*.

That is the way the entire magazine is drafted, no joke!

-- Note from technical dude:  Not! --

Okay.. anyhow back to our awesome program. We need to set extended
background color mode, copy the reversed characters to ram, and then
tell the VIC II to look in RAM not ROM for the characters. Sounds like a
mission briefing.. but maybe it will not be that hard. HAHAH

A Task..(The Best Note Maker Ever Published) -catchy!

Here is this awesome note maker.. with explanations throughout. This is
not the final program, but we will make a full fledged operational note
maker, perhaps even in this Level. To change colors you can SHIFT what
you type, REVERSE on, and even SHIFT reverse. (Below is the documented
program. I will repeat it without added comments)

; Bonkers Note Maker v1

          *= 8192
chrout     = $ffd2
getin      = $ffe4

             lda #0
             sta 646

Location 646 sets the foreground color which will actually be the
background color sense our characters will be reversed!  On newer VIC
chips, when #$96 is JSR'd to chrout, the value that is in 646 is used
to initialize color memory.

             lda #$93
             jsr chrout

Here we clear the screen.
            
             lda #$00
             sta $d020

We set the border color register to black
             
             lda #$01
             sta $d021

Do not be fooled.. ehhe, we are setting the background color register to
white, but our characters are reversed so this is actually the
foreground color.

              sei

This turns off the interrupts, it is a new opcode which you may use
quite a bit or you may not use much at all. SEI (Set Enable Interrupt),
turn em off!  We do this because we are switching out ROM. If an
interrupt occured when ROM is switched out, the KERNAL calls during this
time would crash our program!  This, by the way, would be bad.

copychar     lda 1
             and #251
             sta 1

What we do here is switch out the VIC chip's memory in our to access the
ROM behind the chip. The AND is also a new opcode, it can be used to
turn bits off. Do not worry about it, we will devote a lot of time to it
in the future.

             ldx #$00
Getchl       lda 54272,x
             sta 12288,x
             lda 54272+256,x
             sta 12288+256,x
             inx
             cpx #255
             bne getchl

Here is a loop to get our 64 characters. Notice that we use two sets of
LDA/STA to access more then 256 locations, since the X register can hold
only values 0 through 255.

             lda 1
             ora #4
             sta 1

Here we switch the VIC II back into memory. Notice that the ORA is a new
opcode, it can be used to turn bits on. Again, we will devote several
pages to these new bit operations.

             cli

Now that we have switched ROM back in, we allow the VIC II chip to
interrupt so it can do its own maintenence things like processing
keyboard inputs.

             lda 53272
             and #240
             ora #12
             sta 53272

These 4 instructions, which do the same as the BASIC statement:
poke 53272, (peek(53272) and 240) or 12, tells the VIC II chip to use
the charset located at 12288 in RAM.  From now on, we use the
reversed charset that we copied from ROM.

             lda 53265
             ora #64
             sta 53265

Here we set the VIC II chip to EXTENDED BACKGROUND COLOR mode, giving us
access to four background colors.

main         jsr wordproc
             jsr memodisplay
             jmp main

The powerhouse is this loop. The processor will jsr wordproc, and when it
gets to the rts, it will return to jsr memodisplay. The next instruction
will be jmp main, and it will start all over again.

wordproc     jsr getin
             jsr chrout
             rts

This subroutine calls two kernal subroutines which get a keyboard
character and output a keyboard character.

memodisplay  ldx #$00
memloop      lda col1,x
             sta 53282
             lda col2,x
             sta 53283
             lda col3,x
             sta 53284
             inx
             cpx #9
             bne memloop
             rts

This code puts 9 colors in each of the 3 registers for a smooth cycling
effect.

col1      .byte 6,14,3,7,1,7,3,14,6
col2      .byte 11,12,15,7,1,7,15,12,11
col3      .byte 9,4,8,7,1,7,4,8,9

Here is our color data. First we have a smooth blue blend, then a gray
blend, and finally an orange blend.

Here is the code without the comments. Note you can add your own
comments with the ";" and make notes and reminders to yourself. It is
always a good idea to comment programs.

; Bonkers Note Maker v1

       *= 8192
chrout  = $ffd2
getin   = $ffe4
         
          lda #0
          sta 646
          lda #$93
          jsr chrout
          lda #$00
          sta $d020
          lda #$01
          sta $d021
          sei
copychar  lda 1
          and #251
          sta 1
          ldx #$00
getchl    lda 54722,x
          sta 12288,x
          lda 54272+256,x
          sta 12288+256,x
          inx
          cpx #255
          bne getchl
          lda 1
          ora #4
          sta 1
          cli
          lda 53272
          and #240
          ora #12
          sta 53272
          lda 53265
          ora #64
          sta 53265
main      jsr wordproc
          jsr memodisplay
          jmp main
wordproc  jsr getin
          jsr chrout
          rts
memodsiplay
          ldx #$00
memloop   lda col1,x
          sta 53282
          lda col2,x
          sta 53283
          lda col3,x
          sta 53284
          inx
          cpx #9
          bne memloop
          rts
col1      .byte 6,14,3,7,1,7,3,14,6
col2      .byte 11,12,15,7,1,7,15,12,11
col3      .byte 9,4,8,7,1,7,4,8,9


Did you have fun playing with the note maker? I did, but it wasn't easy
hitting shift, reverse on, and reverse off. And since this isn't UNIX, we
can actually make it easy to use, so we will!  What we will do is assign
the function key F3 as a reverse on, reverse off switch. So that one tap
and you get your colors, tap again and it will turn off reverse mode.
And you get the other colors if you shift with it on or off. It would be
even better to assign each color a function key, but that will have to
wait.. below is the code you should change..


wordproc             jsr getin  
                     cmp #134      ;Check for F3
                     beq rvsmode   ;If so then go set rvsmode
                     jsr chrout
                     rts
rvsmode              lda flip1     ;On/Off variable
                     cmp #0        ;If it is off then turn it on
                     bne rvsoff
rvson                lda #18       ;It is off, turn rvs mode on
                     jsr chrout    ;output rvs on
                     lda #1        ;Set our variable to on
                     sta flip1     ;mode
                     rts          
rvsoff               lda #146      ;It is on, turn rvs mode off
                     jsr chrout    ;output rvs off
                     lda #0        ;set our variable to off mode
                     sta flip1     ;be sure to save it
                     rts

flip1               .byte 0

Check out the BEQ this means (Branch If Equal) it is the opposite of BNE
(Branch If Not Equal).

The above code runs off of the simple concept: if flip1 is on turn it
off, if flip1 is off turn it on. It will always be equal to one or zero.
Sometimes, these little things can get confusing, but a little trial and
error will always help!

___ Power-up Time ____

Questions //\\//\\//

1.  Tell what the instructions SEI, CLI, BNE, BEQ, AND, and ORA do.
    (Note we did not truly go into detail on AND/OR, so a general idea
    will do)

2.  What is a monitor? What is an assembler? Compare and contrast.

3.  Can we address more then 256 locations with indexing? Explain how.

4.  Replace the existing .byte statements with different numbers.
    (Check a chart to get the specific colors that you want)

5.  Change the number of colors that the memloop uses. Hint: change the
    cpx #9 and  col1, col2, and col3.

6.  Change the F3 RVS/RVS OFF key to F5 RVS/RVS OFF. Hint: F5 has a
    value of 135.

___Stage Boss___


Add some text telling how to use the program. Like a simple text
introduction. If you're really brave, add a pop-up help feature. This
could be quite a challenge. You will have to save the contents of the
screen memory, which starts at location $0400, and restore it.

Stage #01 Completed.

______Things You've Learned_____

Well.. you learned how to code in an assembler. You modified a useful
note program. You learned the most common assembly terms. You increased
your programming skills, and you have a general idea of how the new
instructions work.

_____Level #03 Completed_____

Sorry to end it up so soon, but we do have deadlines. You can look
forward to the next issue though; we will continue to develop our note
program (the final version will have save, music, edit, and multiple
pages!). We will also look into common assembly problems, and we, of
course, will have a follow up on some of those new mysterious
instructions and much more! In addition we may have some special issues
coming up soon. Well no more delays.. so enjoy and grab another!

                                                      The Bonkers Staff
