*********

  Welcome to Project 64!

    The goal of Project 64 is to preserve Commodore 64 related documents
  in electronic text format that might otherwise cease to exist with the
  rapid advancement of computer technology and declining interest in 8-
  bit computers on the part of the general population. If you would like
  to help by converting C64 related hardcopy documents to electronic
  texts please contact the manager of Project 64, Cris Berneburg, at
  <74171.2136@compuserve.com>.

    Extensive efforts were made to preserve the contents of the original
  document.  However, certain portions, such as diagrams, program
  listings, and indexes may have been either altered or sacrificed due
  to the limitations of plain vanilla text.  Diagrams may have been
  eliminated where ASCII-art was not feasible.  Program listings may be
  missing display codes where substitutions were not possible.  Tables
  of contents and indexes may have been changed from page number
  references to section number references. Please accept our apologies
  for these limitations, alterations, and possible omissions.

    The author(s) of the original document and members of Project 64 make
  no representations about the accuracy or suitability of this material
  for any purpose.  This etext is provided "as-is".  Please refer to the
  warantee of the original document, if any, that may included in this
  etext.  No other warantees, express or implied, are made to you as to
  the etext or any medium it may be on.  Neither the author(s) nor the
  members of Project 64 will assume liability for damages either from
  the direct or indirect use of this etext or from the distribution of
  or modification to this etext.

  *********

    The Project 64 etext of the Commodore 64 Programmer's Reference Guide,
  first edition. Converted to etext by Ville Muikkula. Some errors in
  the original document were corrected in this etext.

  C64PRG10.TXT, June 1996, etext #46

  *********

  I would like to thank the following persons for their valuable help:

    Jouko Valta for the memory maps on pages 310-334.
    Marko Makela for the combined table of memory maps on pages 264-266.
    Cris Berneburg for proof reading.
    Kimmo Hamalainen for proof reading.

    There was a lot of work, but finally, after five weeks of correcting
  OCR-errors and formatting the text to readable format, it is ready. I
  hope that this massive project shows to the C= community that it is in
  a fact possible for one man to convert a 500 page book to ASCII text.
  One just have to be dedicated, believe that it can be done and have
  the PATIENCE for it... and lots of free time. So, who's going to etext
  Inside Commodore DOS?
    If you find errors in the text, please report them so that they can
  be fixed. There should not be many, though...

    There are some pictures missing on pages 132,157,162-163,195,364-365,
  377-378,380-381,404,406-407,416-417,421,459,476-477 and 481. Also the
  schematics of C-64 are not available. I apologize for the possible
  inconvenience this might cause.

  Ville Muikkula <vmuikku@yrttis.ratol.fi> or <vmuikku@raahenet.ratol.fi>.

  *********

  Note: To extract the ascii text basic programs all at once from this
  etext use "tok64" by Cris Berneburg <74171.2136@compuserve.com>.

  *********

    Windows 95 MS-DOS Edit is the ideal program for reading this
  etext.  Just check that ANSI.SYS is loaded in CONFIG.SYS and issue
  the command:

    mode con lines=50

  Now a whole page fits nicely on the screen and you can use Page Up/Page
  Down keys to flip pages. Just be sure that the ~ characters are always
  on the last line of the screen.

  *********

                                COMMODORE 64
                                PROGRAMMER'S
                               REFERENCE GUIDE

                                Published by
                      Commodore Business Machines, Inc.
                                     and
                          Howard W. Sams & Co., Inc.

                                      i

  FIRST EDITION
  FOURTH PRINTING-1983

  Copyright (C) 1982 by Commodore Business Machines, Inc.
  All rights reserved.

  This manual is copyrighted and contains proprietary information. No part
  of this publication may be reproduced, stored in a retrieval system, or
  transmitted in any form or by any means, electronic, mechanical, photo-
  copying, recording, or otherwise, without the prior written permission
  of COMMODORE BUSINESS MACHINES, Inc.

                                     ii

  TABLE OF CONTENTS

  INTRODUCTION .......................................................   ix
     o What's Included? ..............................................    x
     o How to Use This Reference Guide ...............................   xi
     o Commodore 64 Applications Guide ...............................  xii
     o Commodore Information Network ................................. xvii

  1. BASIC PROGRAMMING RULES .........................................    1
     o Introduction ..................................................    2
     o Screen Display Codes (BASIC Character Set) ....................    2
         The Operating System (OS) ...................................    2
     o Programming Numbers and Variables .............................    4
         Integer, Floating-Point and String Constants ................    4
         Integer, Floating-Point and String Variables ................    7
         Integer, Floating-Point and String Arrays ...................    8
     o Expressions and Operators .....................................    9
         Arithmetic Expressions ......................................   10
         Arithmetic Operations .......................................   10
         Relational Operators ........................................   12
         Logical Operators ...........................................   13
         Hierarchy of Operations .....................................   15
         String Operations ...........................................   16
         String Expressions ..........................................   17
     o Programming Techniques ........................................   18
         Data Conversions ............................................   18
         Using the INPUT Statement ...................................   18
         Using the GET Statement .....................................   22
         How to Crunch BASIC Programs ................................   24

  2. BASIC LANGUAGE VOCABULARY .......................................   29
     o Introduction ..................................................   30
     o BASIC Keywords, Abbreviations, and Function Types .............   31
     o Description of BASIC Keywords (Alphabetical) ..................   35
     o The Commodore 64 Keyboard and Features ........................   93
     o Screen Editor .................................................   94

                                     iii

  3. PROGRAMMING GRAPHICS ON THE
     COMMODORE 64 ....................................................   99
     o Graphics Overview .............................................  100
         Character Display Modes .....................................  100
         Bit Map Modes ...............................................  100
         Sprites .....................................................  100
     o Graphics locations ............................................  101
         Video Bank Selection ........................................  101
         Screen Memory ...............................................  102
         Color Memory ................................................  103
         Character Memory ............................................  103
     o Standard Character Mode .......................................  107
         Character Definitions .......................................  107
     o Programmable Characters .......................................  108
     o Multi-Color Mode Graphics .....................................  115
         Multi-Color Mode Bit ........................................  115
     o Extended Background Color Mode ................................  120
     o Bit Mapped Graphics ...........................................  121
         Standard High-Resolution Bit Map Mode .......................  122
         How It Works ................................................  122
     o Multi-Color Bit Map Mode ......................................  127
     o Smooth Scrolling ..............................................  128
     o Sprites .......................................................  131
         Defining a Sprite ...........................................  131
         Sprite Pointers .............................................  133
         Turning Sprites On ..........................................  134
         Turning Sprites Off .........................................  135
         Colors ......................................................  135
         Multi-Color Mode ............................................  135
         Setting a Sprite to Multi-Color Mode ........................  136
         Expanded Sprites ............................................  136
         Sprite Positioning ..........................................  137
         Sprite Positioning Summary ..................................  143
         Sprite Display Priorities ...................................  144
         Collision Detects ...........................................  144
     o Other Graphics Features .......................................  150
         Screen Blanking .............................................  150
         Raster Register .............................................  150
         Interrupt Status Register ...................................  151
         Suggested Screen and Character Color Combinations ...........  152

                                     iv

     o Programming Sprites-Another Look ..............................  153
         Making Sprites in BASIC-A Short Program .....................  153
         Crunching Your Sprite Programs ..............................  156
         Positioning Sprites on the Screen ...........................  157
         Sprite Priorities ...........................................  161
         Drawing a Sprite ............................................  162
         Creating a Sprite ... Step by Step ..........................  163
         Moving Your Sprite on the Screen ............................  165
         Vertical Scrolling ..........................................  166
         The Dancing Mouse-A Sprite Program Example ..................  166
         Easy Spritemaking Chart .....................................  176
         Spritemaking Notes ..........................................  177

  4. PROGRAMMING SOUND AND MUSIC
     ON YOUR COMMODORE 64 ............................................  183
     o Introduction ..................................................  184
         Volume Control ..............................................  186
         Frequencies of Sound Waves ..................................  186
     o Using Multiple Voices .........................................  187
         Controlling Multiple Voices .................................  191
     o Changing Waveforms ............................................  192
         Understanding Waveforms .....................................  194
     o The Envelope Generator ........................................  196
     o Filtering .....................................................  199
     o Advanced Techniques ...........................................  202
     o Synchronization and Ring Modulation ...........................  207

  5. BASIC TO MACHINE LANGUAGE .......................................  209
     o What is Machine Language? .....................................  210
         What Does Machine Code Look Like? ...........................  211
         Simple Memory Map of the Commodore 64 .......................  212
         The Registers Inside the 6510 Microprocessor ................  213
     o How Do You Write Machine Language Programs? ...................  214
         64MON .......................................................  215
     o Hexadecimal Notation ..........................................  215
         Your First Machine Language Instruction .....................  218
         Writing Your First Program ..................................  220
     o Addressing Modes ..............................................  221
         Zero Page ...................................................  221
         The Stack ...................................................  222

                                      v

     o Indexing ......................................................  223
         Indirect Indexed ............................................  223
         Indexed Indirect ............................................  224
         Branches and Testing ........................................  226
     o Subroutines ...................................................  228
     o Useful Tips for the Beginner ..................................  229
     o Approaching a Large Task ......................................  230
     o MCS6510 Microprocessor Instruction Set-
       Alphabetic Sequence ...........................................  232
         Instruction Addressing Modes and
           Related Execution Times ...................................  254
     o Memory Management on the Commodore 64 .........................  260
     o The KERNAL ....................................................  268
     o KERNAL Power-Up Activities ....................................  269
         How to Use the KERNAL .......................................  270
         User Callable KERNAL Routines ...............................  272
         Error Codes .................................................  306
     o Using Machine Language From BASIC .............................  307
         Where to Put Machine Language Routines ......................  309
         How to Enter Machine language ...............................  309
     o Commodore 64 Memory Map .......................................  310
         Commodore 64 Input/Output Assignments .......................  320

  6. INPUT/OUTPUT GUIDE ..............................................  335
     o Introduction ..................................................  336
     o Output to the TV ..............................................  336
     o Output to Other Devices .......................................  337
         Output to Printer ...........................................  338
         Output to Modem .............................................  339
         Working With Cassette Tape ..................................  340
         Data Storage on Floppy Diskettes ............................  342
     o The Game Ports ................................................  343
         Paddles .....................................................  346
         Light Pen ...................................................  348
     o RS-232 Interface Description ..................................  348
        General Outline ..............................................  348
        Opening an RS-232 Channel ....................................  349
        Getting Data From an RS-232 Channel ..........................  352
        Sending Data to an RS-232 Channel ............................  353
        Closing an RS-232 Data Channel ...............................  354
        Sample BASIC Programs ........................................  356

                                     vi

        Receiver/Transmitter Buffer Base Location Pointers ...........  357
        Zero-Page Memory Locations and Usage
          for RS-232 System Interface ................................  358
        Nonzero-Page Memory Locations and Usage
          for RS-232 System Interface ................................  358
     o The User Port .................................................  359
         Port Pin Description ........................................  359
     o The Serial Bus ................................................  362
         Serial Bus Pinouts ..........................................  363
     o The Expansion Port ............................................  366
     o Z-80 Microprocessor Cartridge .................................  368
         Using Commodore CP/M (R) ....................................  369
         Running Commodore CP/M (R) ..................................  369

  APPENDICES .........................................................  373
     A.  Abbreviations for BASIC Keywords ............................  374
     B.  Screen Display Codes ........................................  376
     C.  ASCII and CHR$ Codes ........................................  379
     D.  Screen and Color Memory Maps ................................  382
     E.  Music Note Values ...........................................  384
     F.  Bibliography ................................................  388
     G.  VIC Chip Register Map .......................................  391
     H.  Deriving Mathematical Functions .............................  394
     I.  Pinouts for Input/Output Devices ............................  395
     J.  Converting Standard BASIC Programs to
           Commodore 64 BASIC ........................................  398
     K.  Error Messages ..............................................  400
     L.  6510 Microprocessor Chip Specifications .....................  402
     M.  6526 Complex Interface Adapter (CIA)
           Chip Specifications .......................................  419
     N.  6566/6567 (VIC-II) Chip Specifications ......................  436
     0.  6581 Sound Interface Device (SID) Chip Specifications .......  457
     P.  Glossary ....................................................  482

  INDEX ..............................................................  483

  COMMODORE 64 QUICK REFERENCE CARD ..................................  487

  SCHEMATIC DIAGRAM OF THE COMMODORE 64 ..............................  491

                                     vii

  INTRODUCTION

    The COMMODORE 64 PROGRAMMER'S REFERENCE GUIDE has been developed as a
  working tool and reference source for those of you who want to maximize
  your use of the built-in capabilities of your COMMODORE 64. This manual
  contains the information you need for your programs, from the simplest
  example all the way to the most complex. The PROGRAMMER'S REFERENCE GUIDE
  is designed so that everyone from the beginning BASIC programmer to the
  professional experienced in 6502 machine language can get information to
  develop his or her own creative programs. At the same time this book
  shows you how clever your COMMODORE 64 really is.
    This REFERENCE GUIDE is not designed to teach the BASIC programming
  language or the 6502 machine language. There is, however, an extensive
  glossary of terms and a "semi-tutorial" approach to many of the sections
  in the book. If you don't already have a working knowledge of BASIC and
  how to use it to program, we suggest that you study the COMMODORE 64
  USER'S GUIDE that came with your computer. The USER'S GUIDE gives you an
  easy to read introduction to the BASIC programming language. If you still
  have difficulty understanding how to use BASIC then turn to the back of
  this book (or Appendix N in the USER'S GUIDE) and check out the
  Bibliography.
    The COMMODORE 64 PROGRAMMER'S REFERENCE GUIDE is just that; a
  reference. Like most reference books, your ability to apply the
  information creatively really depends on how much knowledge you have
  about the subject. In other words if you are a novice programmer you will
  not be able to use all the facts and figures in this book until you
  expand your current programming knowledge.

                                     ix

    What you can do with this book is to find a considerable amount of
  valuable programming reference information written in easy to read,
  plain English with the programmer's jargon explained. On the other hand
  the programming professional will find all the information needed to use
  the capabilities of the COMMODORE 64 effectively.

  WHAT'S INCLUDED?

    o Our complete "BASIC dictionary" includes Commodore BASIC language
      commands, statements and functions listed in alphabetical order.
      We've created a "quick list" which contains all the words and their
      abbreviations. This is followed by a section containing a more
      detailed definition of each word along with sample BASIC programs
      to illustrate how they work.
    o If you need an introduction to using machine language with BASIC
      programs our layman's overview will get you started.
    o A powerful feature of all Commodore computers is called the KERNAL.
      It helps insure that the programs you write today can also be used
      on your Commodore computer of tomorrow.
    o The Input/Output Programming section gives you the opportunity to
      use your computer to the limit. It describes how to hook-up and use
      everything from lightpens and joysticks to disk drives, printers,
      and telecommunication devices called modems.
    o You can explore the world of SPRITES, programmable characters, and
      high resolution graphics for the most detailed and advanced animated
      pictures in the microcomputer industry.
    o You can also enter the world of music synthesis and create your own
      songs and sound effects with the best built-in synthesizer available
      in any personal computer.
    o If you're an experienced programmer, the soft load language section
      gives you information about the COMMODORE 64's ability to run CP/M*
      and high level languages. This is in addition to BASIC.

    Think of your COMMODORE 64 PROGRAMMER'S REFERENCE GUIDE as a useful
  tool to help you and you will enjoy the -hours of programming ahead
  of you.

  -----------
  * CP/M is a registered trademark of Digital Research, Inc.

  x   INTRODUCTION

  HOW TO USE THIS REFERENCE GUIDE

    Throughout this manual certain conventional notations are used to de-
  scribe the syntax (programming sentence structure) of BASIC commands or
  statements and to show both the required and optional parts of each BASIC
  keyword. The rules to use for interpreting statement syntax are as
  follows:

    1. BASIC keywords are shown in capital letters. They must appear where
       shown in the statement, entered and spelled exactly as shown.
    2. Items shown within quotation marks (" ") indicate variable data
       which you must put in. Both the quotation marks and the data inside
       the quotes must appear where shown in each statement.
    3. Items inside the square brackets ([ ]) indicate an optional state-
       ment parameter. A parameter is a limitation or additional qualifier
       for your statements. If you use an optional parameter you must
       supply the data for that optional parameter. In addition, ellipses
       (...) show that an optional item can be repeated as many times as
       a programming line allows.
    4. If an item in the square brackets ([ ]) is UNDERLINED, that means
       that you MUST use those certain characters in the optional para-
       meters, and they also have to be spelled exactly as shown.
    5. Items inside angle brackets (< >) indicate variable data which you
       provide. While the slash (/) indicates that you must make a choice
       between two mutually exclusive options.

  EXAMPLE OF SYNTAX FORMAT:

    OPEN <file-num>,<device>[,<address>],["<drive>:<filename>][,<mode>]"

  EXAMPLES OF ACTUAL STATEMENTS:

    10 OPEN 2,8,6,"0:STOCK FOLIO,S,W"
    20 OPEN 1,1,2,"CHECKBOOK"
    30 OPEN 3,4

    When you actually apply the syntax conventions in a practical situa-
  tion, the sequence of parameters in your statements might not be exactly
  the same as the sequence shown in syntax examples. The examples are not
  meant to show every possible sequence. They are intended to present all
  required and optional parameters.

                                                          INTRODUCTION   xi

    Programming examples in this book are shown with blanks separating
  words and operators for the sake of readability. Normally though, BASIC
  doesn't require blanks between words unless leaving them out would give
  you an ambiguous or incorrect syntax.
    Shown below are some examples and descriptions of the symbols used for
  various statement parameters in the following chapters. The list is not
  meant to show every possibility, but to give you a better understanding
  as to how syntax examples are presented.

    SYMBOL        EXAMPLE                 DESCRIPTION
  <file-num>        50              A logical file number
  <device>          4               A hardware device number
  <address>         15              A serial bus secondary
                                    device address number
  <drive>           0               A physical disk drive number
  <file-name>       "TEST.DATA"     The name of a data or program file
  <constant>        "ABCDEFG"       Literal data supplied by
                                    the programmer
  <variable>        X145            Any BASIC data variable name or
                                    constant
  <string>          AB$             Use of a string type variable required
  <number>          12345           Use of a numeric type variable
                                    required
  <line-number>     1000            An actual program line number
  <numeric>         1.5E4           An integer or floating-point variable

  COMMODORE 64 APPLICATIONS GUIDE

    When you first thought about buying a computer you probably asked
  yourself, "Now that I can afford to buy a computer, what can I do with
  it once I get one?"
    The great thing about your COMMODORE 64 is that you can make it do what
  YOU want it to do! You can make it calculate and keep track of home and
  business budget needs. You can use it for word processing. You can make
  it play arcade-style action games. You can make it sing. You can even
  create your own animated cartoons, and more. The best part of owning a
  COMMODORE 64 is that even if it did only one of the things listed below
  it would be well worth the price you paid for it. But the 64 is a
  complete computer and it does do EVERYTHING listed and then some!

  xii   INTRODUCTION

    By the way, in addition to everything here you can pick up a lot of
  other creative and practical ideas by signing up with a local Commodore
  Users' Club, subscribing to the COMMODORE and POWER/PLAY magazines, and
  joining the COMMODORE INFORMATION NETWORK on CompuServe(TM)

      APPLICATION               COMMENTS/REQUIREMENTS

  ACTION PACKED           You can get real Bally Midway arcade games GAMES
                          like Omega Race, Gorf and Wizard of War, as well
                          as "play and learn" games like Math Teacher 1,
                          Home Babysitter and Commodore Artist.

  ADVERTISING &           Hook your COMMODORE 64 to a TV, put it in
  MERCHANDISING           a store window with a flashing, animated, and
                          musical message and you've got a great point of
                          purchase store display.

  ANIMATION               Commodore's Sprite Graphics allow you to create
                          real cartoons with 8 different levels so that
                          shapes can move in front of or behind each
                          other.

  BABYSITTING             The COMMODORE 64 HOME BABYSITTER cartridge can
                          keep your youngest child occupied for hours and
                          teach alphabet/ keyboard recognition at the same
                          time. It also teaches special learning concepts
                          and relationships.

  BASIC PROGRAMMING       Your COMMODORE 64 USER'S GUIDE and the TEACH
                          YOURSELF PROGRAMMING series of books and tapes
                          offer an excellent starting point.

  BUSINESS                The COMMODORE 64 offers the "Easy" series
  SPREADSHEET             of business aids including the most powerful
                          word processor and largest spreadsheet
                          available for any personal computer.

  COMMUNICATION           Enter the fascinating world of computer "net-
                          working." If you hook a VICMODEM to your
                          COMMODORE 64 you can communicate with other
                          computer owners all around the world.

                                                        INTRODUCTION   xiii

                          Not only that, if you join the COMMODORE
                          INFORMATION NETWORK on CompuServe(TM) you can
                          get the latest news and updates on all Commodore
                          products, financial information, shop at home
                          services, you can even play games with the
                          friends you make through the information systems
                          you join.

  COMPOSING SONGS         The COMMODORE 64 is equipped with the most
                          sophisticated built-in music synthesizer
                          available on any computer. It has three com-
                          pletely programmable voices, nine full music
                          octaves, and four controllable waveforms.
                          Look for Commodore Music Cartridges and
                          Commodore Music books to help you create or
                          reproduce all kinds of music and sound effects.

  CP/M*                   Commodore offers a CP/M* add-on and access to
                          software through an easy-to-load cartridge.

  DEXTERITY TRAINING      Hand/Eye coordination and manual dexterity
                          are aided by several Commodore games...
                          including "Jupiter lander" and night driving
                          simulation.

  EDUCATION               While working with a computer is an education in
                          itself, The COMMODORE Educational Resource Book
                          contains general information on the educational
                          uses of computers. We also have a variety of
                          learning cartridges designed to teach everything
                          from music to math and art to astronomy.

  FOREIGN LANGUAGE        The COMMODORE 64 programmable character set
                          lets you replace the standard character set
                          with user defined foreign language characters.

  GRAPHICS AND ART        In addition to the Sprite Graphics mentioned
                          above, the COMMODORE 64 offers high-resolution,
                          multi-color graphics plotting, programmable

  -----------
  * CP/M is a Registered trademark of Digital Research, Inc.

  xiv   INTRODUCTION

                          characters, and combinations of all the
                          different graphics and character display modes.

  INSTRUMENT              Your COMMODORE 64 has a serial port, RS-232 port
  CONTROL                 and a user port for use with a variety of special
                          industrial applications. An IEEE/488 cartridge is
                          also available as an optional extra.

  JOURNALS AND            The COMMODORE 64 will soon offer an exceptional
  CREATIVE WRITING        wordprocessing system that matches or exceeds
                          the qualities and flexibilities of most "high-
                          priced" wordprocessors available. Of course you
                          can save the information on either a 1541 Disk
                          Drive or a Datassette TM recorder and have it
                          printed out using a VIC-PRINTER or PLOTTER.

  LIGHTPEN CONTROL        Applications requiring the use of a lightpen
                          can be performed by any lightpen that will fit
                          the COMMODORE 64 game port connector.

  MACHINE CODE            Your COMMODORE 64 PROGRAMMER'S REFERENCE GUIDE
  PROGRAMMING             includes a machine language section, as well as
                          a BASIC to machine code interface section.
                          There's even a bibliography available for more
                          in-depth study.

  PAYROLL & FORMS         The COMMODORE 64 can be programmed to handle
  PRINTOUT                a variety of entry-type business applications.
                          Upper/lower case letters combined with C64
                          "business form" graphics make it easy for you
                          to design forms which can then be printed on
                          your printer.

  PRINTING                The COMMODORE 64 interfaces with a variety of
                          dot matrix and letter quality printers as well
                          as plotters.

  RECIPES                 You can store your favorite recipes on your
                          COMMODORE 64 and its disk or cassette storage
                          unit, and end the need for messy recipe cards
                          that often get lost when you need them most.

                                                          INTRODUCTION   xv

  SIMULATIONS             Computer simulations let you conduct dangerous
                          or expensive experiments at minimum risk and
                          cost.

  SPORTS DATA             The Source (TM) and CompuServe (TM) both offer
                          sports information which you can get using
                          your COMMODORE 64 and a VICMODEM.

  STOCK QUOTES            With a VICMODEM and a subscription to any of the
                          appropriate network services, your COMMODORE 64
                          becomes your own private stock ticker.

    These are just a few of the many applications for you and your
  COMMODORE 64. As you can see, for work or play, at home, in school
  or the office, your COMMODORE 64 gives you a practical solution for
  just about any need.
    Commodore wants you to know that our support for users only STARTS
  with your purchase of a Commodore computer. That's why we've created
  two publications with Commodore information from around the world, and
  a "two-way" computer information network with valuable input for users
  in the U.S. and Canada from coast to coast.
    In addition, we wholeheartedly encourage and support the growth of
  Commodore Users' Clubs around the world. They are an excellent source
  of information for every Commodore computer owner from the beginner
  to the most advanced. The magazines and network, which are more fully
  described below, have the most up-to-date information about how to get
  involved with the Users' Club in your area.
    Finally, your local Commodore dealer is a useful source of Commodore
  support and information.

  POWER/PLAY
  The Home Computer Magazine

    When it comes to entertainment, learning at home and practical home
  applications, POWER/PLAY is THE prime source of information for Com-
  modore home users. Find out where your nearest user clubs are and
  what they're doing, learn about software, games, programming techniques,
  telecommunications, and new products. POWER/PLAY is your personal
  connection to other Commodore users, outside software and hardware
  developers, and to Commodore itself. Published quarterly. Only $10.00
  for a year of home computing excitement.

  xvi   INTRODUCTION

  COMMODORE
  The Microcomputer Magazine

    Widely read by educators, businessmen and students, as well as home
  computerists, COMMODORE Magazine is our main vehicle for sharing
  exclusive information on the more technical use of Commodore systems.
  Regular departments cover business, science and education, programming
  tips, "excerpts from a technical notebook," and many other features of
  interest to anyone who uses or is thinking about purchasing Commodore
  equipment for business, scientific or educational applications.
  COMMODORE is the ideal complement to POWER/PLAY. Published bimonthly.
  Subscription price: $15.00 per year.

  AND FOR EVEN MORE INFORMATION...
  ...DIAL UP OUR PAPERLESS USER MAGAZINE

  COMMODORE INFORMATION NETWORK

    The magazine of the future is here. To supplement and enhance your
  subscription to POWER/PLAY and COMMODORE magazines, the COMMODORE
  INFORMATION NETWORK - our "paperless magazine" - is available now over
  the telephone using your Commodore computer and modem.
    Join our computer club, get help with a computing problem, "talk" to
  other Commodore friends, or get up-to-the-minute information on new
  products, software and educational resources. Soon you will even be
  able to save yourself the trouble of typing in the program listings you
  find in POWER/PLAY or COMMODORE by downloading direct from the
  Information Network (a new user service planned for early 1983). The
  best part is that most of the answers are there before you even ask the
  questions. (How's that for service?)
    To call our electronic magazine you need only a modem and a sub-
  scription to CompuServe TM, one of the nation's largest telecommunica-
  tions networks. (To make it easy for you Commodore includes a FREE year's
  subscription to CompuServe TM in each VICMODEM package.) Just dial your
  local number for the CompuServe (TM) data bank and connect your phone to
  the modem. When the CompuServe (TM) video text appears on your screen
  type G CBM on your computer keyboard. When the COMMODORE INFORMATION
  NETWORK'S table of contents, or "menu," appears on your screen choose
  from one of our sixteen departments, make yourself comfortable, and enjoy
  the paperless magazine other magazines are writing about.

                                                        INTRODUCTION   xvii

    For more information, visit your Commodore dealer or contact Com-
  puserve(TM) customer service at 800-848-8990 (in Ohio, 614-457-8600).

                        COMMODORE INFORMATION NETWORK
  +-----------------------------------+-----------------------------------+
  |  Main Menu Description            |  Commodore Dealers                |
  |  Direct Access Codes              |  Educational Resources            |
  |  Special Commands                 |  User Groups                      |
  |  User Questions                   |  Descriptions                     |
  |  Public Bulletin Board            |  Questions and Answers            |
  |  Magazines and Newsletters        |  Software Tips                    |
  |  Products Announced               |  Technical Tips                   |
  |  Commodore News Direct            |  Directory Descriptions           |
  +-----------------------------------+-----------------------------------+

  xviii   INTRODUCTION

                                                 CHAPTER 1

                                                     BASIC
                                               PROGRAMMING
                                                     RULES

                           o Introduction
                           o Screen Display Codes (BASIC
                             Character Set)
                           o Programming Numbers and
                             variables
                           o Expressions and Operators
                           o Programming Techniques

                                      1

  INTRODUCTION

    This chapter talks about how BASIC stores and manipulates data. The
  topics include:

    1) A brief mention of the operating system components and functions
       as well as the character set used in the Commodore 64.
    2) The formation of constants and variables. What types of variables
       there are. And how constants and variables are stored in memory.
    3) The rules for arithmetic calculations, relationship tests, string
       handling, and logical operations. Also included are the rules for
       forming expressions, and the data conversions necessary when you're
       using BASIC with mixed data types.

  SCREEN DISPLAY CODES (BASIC CHARACTER SET)

  THE OPERATING SYSTEM (OS)

    The Operating System is contained in the Read Only Memory (ROM) chips
  and is a combination of three separate, but interrelated, program
  modules.

    1) The BASIC Interpreter
    2) The KERNAL
    3) The Screen Editor

    1) The BASIC Interpreter is responsible for analysing BASIC statement
       syntax and for performing the required calculations and/or data
       manipulation. The BASIC Interpreter has a vocabulary of 65
       "keywords" which have special meanings. The upper and lower case
       alphabet and the digits 0-9 are used to make both keywords and
       variable names. Certain punctuation characters and special symbols
       also have meanings for the Interpreter. Table 1-1 lists the special
       characters and their uses.
    2) The KERNAL handles most of the interrupt level processing in the
       system (for details on interrupt level processing, see Chapter 5).
       The KERNAL also does the actual input and output of data.
    3) The Screen Editor controls the output to the video screen (tele-
       vision set) and the editing of BASIC program text. In addition, the
       Screen Editor intercepts keyboard input so that it can decide
       whether the characters put in should be acted upon immediately, or
       passed on to the BASIC Interpreter.

  2  BASIC PROGRAMMING RULES

                    Table 1 - 1. CBM BASIC Character Set
  +-------------+---------------------------------------------------------+
  |  CHARACTER  |                NAME and DESCRIPTION                     |
  +-------------+---------------------------------------------------------+
  |             | BLANK - separates keywords and variable names           |
  |      ;      | SEMI-COLON - used in variable lists to format output    |
  |      =      | EQUAL SIGN - value assignment and relationship testing  |
  |      +      | PLUS SIGN - arithmetic addition or string concatenation |
  |             |            (concatenation: linking together in a chain) |
  |      -      | MINUS SIGN - arithmetic subtraction, unary minus        |
  |      *      | ASTERISK - arithmetic multiplication                    |
  |      /      | SLASH - arithmetic division                             |
  |      ^      | UP ARROW - arithmetic exponentiation                    |
  |      (      | LEFT PARENTHESIS - expression evaluation and functions  |
  |      )      | RIGHT PARENTHESIS - expression evaluation and functions |
  |      %      | PERCENT - declares variable name as an integer          |
  |      #      | NUMBER - comes before logical file number in input/     |
  |             |          output statements                              |
  |      $      | DOLLAR SIGN - declares variable name as a string        |
  |      ,      | COMMA - used in variable lists to format output; also   |
  |             |         separates command parameters                    |
  |      .      | PERIOD - decimal point in floating point constants      |
  |      "      | QUOTATION MARK - encloses string constants              |
  |      :      | COLON - separates multiple BASIC statements in a line   |
  |      ?      | QUESTION MARK - abbreviation for the keyword PRINT      |
  |      <      | LESS THAN - used in relationship tests                  |
  |      >      | GREATER THAN - used in relationship tests               |
  |     {pi}    | PI - the numeric constant 3.141592654                   |
  +-------------+---------------------------------------------------------+

    The Operating System gives you two modes of BASIC operation:

    1) DIRECT Mode
    2) PROGRAM Mode

    1) When you're using the DIRECT mode, BASIC statements don't have
       line numbers in front of the statement. They are executed whenever
       the <RETURN> key is pressed.
    2) The PROGRAM mode is the one you use for running programs.

                                                BASIC PROGRAMMING RULES   3

       When using the PROGRAM mode, all of your BASIC statements must have
       line numbers in front of them. You can have more than one BASIC
       statement in a line of your program, but the number of statements is
       limited by the fact that you can only put 80 characters on a logical
       screen line. This means that if you are going to go over the 80
       character limit you have to put the entire BASIC statement that
       doesn't fit on a new line with a new line number.

         Always type NEW and hit <RETURN> before starting a new program.

    The Commodore 64 has two complete character sets that you can use
  either from the keyboard or in your programs.
    In SET 1, the upper case alphabet and the numbers 0-9 are available
  without pressing the <SHIFT> key. If you hold down the <SHIFT> key
  while typing, the graphics characters on the RIGHT side of the front of
  the keys are used. If you hold down the <C=> key while typing, the
  graphics characters on the LEFT side of the front of the key are used.
  Holding down the <SHIFT> key while typing any character that doesn't
  have graphic symbols on the front of the key gives you the symbol on the
  top most part of the key.
    In SET 2, the lower case alphabet and the numbers 0-9 are available
  without pressing the <SHIFT> key. The upper case alphabet is available
  when you hold down the <SHIFT> key while typing. Again, the graphic
  symbols on the LEFT side of the front of the keys are displayed by press-
  ing the <C=> key, while the symbols on the top most part of any key
  without graphics characters are selected when you hold down the <SHIFT>
  key while typing.
    To switch from one character set to the other press the <C=> and
  the <SHIFT> keys together.

  PROGRAMMING NUMBERS AND VARIABLES

  INTEGER, FLOATING-POINT AND STRING CONSTANTS

    Constants are the data values that you put in your BASIC statements.
  BASIC uses these values to represent data during statement execution.
  CBM BASIC can recognize and manipulate three types of constants:

    1) INTEGER NUMBERS
    2) FLOATING-POINT NUMBERS
    3) STRINGS

  4   BASIC PROGRAMMING RULES

    Integer constants are whole numbers (numbers without decimal points).
  Integer constants must be between -32768 and +32767. Integer constants
  do not have decimal points or commas between digits. If the plus (+) sign
  is left out, the constant is assumed to be a positive number. Zeros
  coming before a constant are ignored and shouldn't be used since they
  waste memory and slow down your program. However, they won't cause an
  error. Integers are stored in memory as two-byte binary numbers. Some
  examples of integer constants are:

                               -12
                              8765
                            -32768
                               +44
                                 0
                            -32767
  +-----------------------------------------------------------------------+
  |  NOTE: Do NOT put commas inside any number. For example, always type  |
  |  32,000 as 32000. If you put a comma in the middle of a number you    |
  | will get the BASIC error message ?SYNTAX ERROR.                       |
  +-----------------------------------------------------------------------+

    Floating-point constants are positive or negative numbers and can
  contain fractions. Fractional parts of a number may be shown using a
  decimal point. Once again remember that commas are NOT used between
  numbers. If the plus sign (+) is left off the front of a number, the
  Commodore 64 assumes that the number is positive. If you leave off the
  decimal point the computer will assume that it follows the last digit of
  the number. And as with integers, zeros that come before a constant
  are ignored. Floating-point constants can be used in two ways:

    1) SIMPLE NUMBER
    2) SCIENTIFIC NOTATION

    Floating-point constants will show you up to nine digits on your
  screen. These digits can represent values between -999999999. and
  +999999999. If you enter more than nine digits the number will be
  rounded based on the tenth digit. if the tenth digit is greater than or
  equal to 5 the number will be rounded upward. Less than 5 the number
  be rounded downward. This could be important to the final totals of
  some numbers you may want to work with.
    Floating-point numbers are stored (using five bytes of memory) and
  are manipulated in calculations with ten places of accuracy. However,

                                                BASIC PROGRAMMING RULES   5

  the numbers are rounded to nine digits when results are printed. Some
  examples of simple floating-point numbers are:

                  1.23                 .7777777
                  -.998877         -333.
                 +3.1459               .01

    Numbers smaller than .01 or larger than 999999999. will be printed in
  scientific notation. In scientific notation a floating-point constant is
  made up of three parts:

    1) THE MANTISSA
    2) THE LETTER E
    3) THE EXPONENT

    The mantissa is a simple floating-point number. The letter E is used to
  tell you that you're seeing the number in exponential form. In other
  words E represents * 10 (eg., 3E3 = 3*10^3 = 3000). And the exponent is
  what multiplication power of 10 the number is raised to.
    Both the mantissa and the exponent are signed (+ or -) numbers. The
  exponent's range is from -39 to +38 and it indicates the number of places
  that the actual decimal point in the mantissa would be moved to the left
  (-) or right (+) if the value of the constant were represented as a
  simple number.
    There is a limit to the size of floating-point numbers that BASIC can
  handle, even in scientific notation: the largest number is
  +1.70141183E+38 and calculations which would result in a larger number
  will display the BASIC error message ?OVERFLOW ERROR. The smallest
  floating-point number is +2.93873588E-39 and calculations which result
  in a smaller value give you zero as an answer and NO error message. Some
  examples of floating-point numbers in scientific notation (and their
  decimal values) are:

 	235.988E-3	(.235988)
        2359E6          (2359000000.)
        -7.09E-12       (-.00000000000709)
	-3.14159E+5	(-314159.)

    String constants are groups of alphanumeric information like letters,
  numbers and symbols. When you enter a string from the keyboard, it
  can have any length up to the space available in an 80-character line

  6   BASIC PROGRAMMING RULES

  (that is, any character spaces NOT taken up by the line number and other
  required parts of the statement).
    A string constant can contain blanks, letters, numbers, punctuation
  and color or cursor control characters in any combination. You can even
  put commas between numbers. The only character which cannot be included
  in a string is the double quote mark ("). This is because the double
  quote mark is used to define the beginning and end of the string.
  A string can also have a null value-which means that it can contain no
  character data. You can leave the ending quote mark off of a string if
  it's the last item on a line or if it's followed by a colon (:). Some
  examples of string constants are:

               ""         ( a null string)
               "HELLO"
               "$25,000.00"
               "NUMBER OF EMPLOYEES"

  +-----------------------------------------------------------------------+
  |  NOTE: Us CHR$(34) to include quotes (") in strings.                  |
  +-----------------------------------------------------------------------+

  INTEGER, FLOATING-POINT AND STRING VARIABLES

    Variables are names that represent data values used in your BASIC
  statements. The value represented by a variable can be assigned by
  setting it equal to a constant, or it can be the result of calculations
  in the program. Variable data, like constants, can be integers, floating-
  point numbers, or strings. If you refer to a variable name in a program
  before a value has been assigned, the BASIC Interpreter will auto-
  matically create the variable with a value of zero if it's an integer or
  floating-point number. Or it will create a variable with a null value if
  you're using strings.
    Variable names can be any length but only the first two characters are
  considered significant in CBM BASIC. This means that all names used for
  variables must NOT have the same first two characters. Variable names may
  NOT be the same as BASIC keywords and they may NOT contain keywords in
  the middle of variable names. Keywords include all BASIC commands, state-
  ments, function names and logical operator names. If you accidentally use
  a keyword in the middle of a variable name, the BASIC error message
  ?SYNTAX ERROR will show up on your screen.
    The characters used to form variable names are the alphabet and the
  numbers 0-9. The first character of the name must be a letter. Data

                                                BASIC PROGRAMMING RULES   7

  type declaration characters (%) and ($) can be used as the last char-
  acter of the name. The percent sign declares the variable to be an
  integer and the dollar sign ($) declares a string variable. If no type
  declaration character is used the Interpreter will assume that the vari-
  able is a floating-point. Some examples of variable names, value as-
  signments and data types are:

            A$="GROSS SALES"        (string variable)
            MTH$="JAN"+A$           (string variable)
            K%=5                    (integer variable)
            CNT%=CNT%+1             (integer variable)
            FP=12.5                 (floating-point variable)
            SUM=FP*CNT%             (floating-point variable)

  INTEGER, FLOATING-POINT AND STRING ARRAYS

    An array is a table (or list) of associated data items referred to by
  a single variable name. In other words, an array is a sequence of related
  variables. A table of numbers can be seen as an array, for example.
  The individual numbers within the table become "elements" of the array.
    Arrays are a useful shorthand way of describing a large number of
  related variables. Take a table of numbers for instance. Let's say that
  the table has 10 rows of numbers with 20 numbers in each row. That makes
  total of 200 numbers in the table. Without a single array name to call
  on you would have to assign a unique name to each value in the table. But
  because you can use arrays you only need one name for the array and all
  the elements in the array are identified by their individual locations
  within the array.
    Array names can be integers, floating-points or string data types and
  all elements in the array have the same data type as the array name.
  Arrays can have a single dimension (as in a simple list) or they can have
  multiple dimensions (imagine a grid marked in rows and columns or a
  Rubik's Cube(R)). Each element of an array is uniquely identified and re-
  ferred to by a subscript (or index variable) following the array name,
  enclosed within parentheses ( ).
    The maximum number of dimensions an array can have in theory is 255
  and the number of elements in each dimension is limited to 32767. But
  for practical purposes array sizes are limited by the memory space
  available to hold their data and/or the 80 character logical screen line.
  If an array has only one dimension and its subscript value will never

  8   BASIC PROGRAMMING RULES

  exceed 1 0 (1 I items: 0 thru 1 0) then the array will be created by the
  Interpreter and filled with zeros (or nulls if string type) the first
  time any element of the array is referred to, otherwise the BASIC DIM
  statement must be used to define the shape and size of the array. The
  amount of memory required to store an array can be determined as follows:

                5 bytes for the array name
              + 2 bytes for each dimension of the array
              + 2 bytes per element for integers
           OR + 5 bytes per element for floating-point
           OR + 3 bytes per  element for strings
          AND + 1 byte per character in each string element

    Subscripts can be integer constants, variables, or an arithmetic ex-
  pression which gives an integer result. Separate subscripts, with com-
  mas between them, are required for each dimension of an array. Sub-
  scripts can have values from zero up to the number of elements in the
  respective dimensions of the array. Values outside that range will cause
  the BASIC error message ?BAD SUBSCRIPT. Some examples of array names,
  value assignments and data types are:

        A$(0)="GROSS SALES"     (string array)
        MTH$(K%)="JAN"          (string array)
        G2%(X)=5                (integer array)
        CNT%(G2%(X))=CNT%(1)-2  (integer array)
        FP(12*K%)=24.8          (floating-point array)
        SUM(CNT%(1))=FP^K%      (floating-point array)

     A(5)=0     (sets the 5th element in the 1 dimensional
                 array called "A" equal to 0)

     B(5,6)=0   (sets the element in row position 5 and column position 6
                 in the 2 dimensional array called "B" equal to 0)

     C(1,2,3)=0 (sets the element in row position 1, column position 2,
                 and depth position 3 in the 3 dimensional array called
                 "C" equal to 0)

  EXPRESSIONS AND OPERATORS

    Expressions are formed using constants, variables and/or arrays. An
  expression can be a single constant, simple variable, or an array vari-

                                                BASIC PROGRAMMING RULES   9

  able of any type. It can also be a combination of constants and variables
  with arithmetic, relational or logical operators designed to produce a
  ingle value. How operators work is explained below. Expressions can be
  separated into two classes:

    1) ARITHMETIC
    2) STRING

    Expressions are normally thought of as having two or more data items
  called operands. Each operand is separated by a single operator to
  produce the desired result. This is usually done by assigning the value
  of the expression to a variable name. All of the examples of constants
  and variables that you've seen so for, were also examples of expressions.
    An operator is a special symbol the BASIC Interpreter in your Commodore
  64 recognizes as representing an operation to be performed on the
  variables or constant data. One or more operators, combined with one or
  more variables and/or constants form an expression. Arithmetic,
  relational and logical operators are recognized by Commodore 64 BASIC.

  ARITHMETIC EXPRESSIONS

    Arithmetic expressions, when solved, will give an integer or floating-
  point value. The arithmetic operators (+, -, *, /, ^) are used to perform
  addition, subtraction, multiplication, division and exponentiation opera-
  tions respectively.

  ARITHMETIC OPERATIONS

    An arithmetic operator defines an arithmetic operation which is per-
  formed on the two operands on either side of the operator. Arithmetic
  operations are performed using floating-point numbers. Integers are
  converted to floating-point numbers before an arithmetic operation is
  performed. The result is converted back to an integer if it is assigned
  to an integer variable name.

    ADDITION (+): The plus sign (+) specifies that the operand on the
  right is added to the operand on the left.

  10   BASIC PROGRAMMING RULES

    EXAMPLES:
                     2+2
                     A+B+C
                     X%+1
                     BR+10E-2

    SUBTRACTION (-): The minus sign (-) specifies that the operand on the
  right is subtracted from the operand on the left.

    EXAMPLES:
                     4-1
                     100-64
                     A-B
                     55-142

    The minus can also be used as a unary minus. That means that it is the
  minus sign in front of a negative number. This is equal to subtracting
  the number from zero (0).

    EXAMPLES:
                     -5
                     -9E4
                     -B
                     4-(-2) same as 4+2

    MULTIPLICATION (*): An asterisk (*) specifies that the operand on the
  left is multiplied by the operand on the right.

    EXAMPLES:
                     100*2
                     50*0
                     A*X1
                     R%*14

    DIVISION (/): The slash (/) specifies that the operand on the left is
  divided by the operand on the right.

    EXAMPLES:
                     10/2
                     6400/4
                     A/B
                     4E2/XR

                                               BASIC PROGRAMMING RULES   11

    EXPONENTIATION     The up arrow (^) specifies that the operand on the
  left is raised to the power specified by the operand on the right (the
  exponent). If the operand on the right is a 2, the number on the left is
  squared; if the exponent is a 3, the number on the left is cubed, etc.
  The exponent can be any number so long as the result of the operation
  gives a valid floating-point number.

    EXAMPLES:
                     2^2        Equivalent to: 2*2
                     3^3        Equivalent to: 3*3*3
                     4^4        Equivalent to: 4*4*4*4
                     AB^CD
                     3^-2       Equivalent to: 1/3*1/3

  RELATIONAL OPERATORS

    The relational operators (<, =, >, <=, >=, <>) are primarily used
  to compare the values of two operands, but they also produce an arith-
  metic result. The relational operators and the logical operators (AND,
  OR, and NOT), when used in comparisons, actually produce an arithmetic
  true/false evaluation of an expression. If the relationship stated in
  the expression is true the result is assigned an integer value of - 1
  and if it's false a value of 0 is assigned. These are the relational
  operators:
                   <   LESS THAN
                   =   EQUAL TO
                   >   GREATER THAN
                   <=  LESS THAN OR EQUAL TO
                   >=  GREATER THAN OR EQUAL TO
                   <>  NOT EQUAL TO

    EXAMPLES:

      1 =5-4          result true (-1)
      14>66           result false (0)
      15>=15          result true (-1)

    Relational operators can be used to compare strings. For comparison
  purposes, the letters of the alphabet have the order A<B<C<D, etc.
  Strings are compared by evaluating the relationship between corre-
  sponding characters from left to right (see String Operations).

  12   BASIC PROGRAMMING RULES

    EXAMPLES:

      "A" < "B"       result true (-1)
      "X" = "YY"      result false (0)
      BB$ <> CC$

    Numeric data items can only be compared (or assigned) to other numeric
  items. The same is true when comparing strings, otherwise the BASIC error
  message ?TYPE MISMATCH will occur. Numeric operands are compared by first
  converting the values of either or both operands from integer to
  floating-point form, as necessary. Then the relationship of the floating-
  point values is evaluated to give a true/false result.
    At the end of all comparisons, you get an integer no matter what data
  type the operand is (even if both are strings). Because of this,
  a comparison of two operands can be used as an operand in performing
  calculations. The result will be - 1 or 0 and can be used as anything but
  a divisor, since division by zero is illegal.

  LOGICAL OPERATORS

    The logical operators (AND, OR, NOT) can be used to modify the meanings
  of the relational operators or to produce an arithmetic result. Logical
  operators can produce results other than -1 and 0, though any nonzero
  result is considered true when testing for a true/false condition.
    The logical operators (sometimes called Boolean operators) can also be
  used to perform logic operations on individual binary digits (bits) in
  two operands. But when you're using the NOT operator, the operation is
  performed only on the single operand to the right. The operands must be
  in the integer range of values (-32768 to +32767) (floating-point
  numbers are converted to integers) and logical operations give an integer
  result.
    Logical operations are performed bit-by-corresponding-bit on the two
  operands. The logical AND produces a bit result of 1 only if both operand
  bits are 1. The logical OR produces a bit result of I if either operand
  bit is 1. The logical NOT is the opposite value of each bit as a single
  operand. In other words, it's really saying, "if it's NOT 1 then it is 0.
  If it's NOT 0 then it is 1."
    The exclusive OR (XOR) doesn't have a logical operator but it is per-
  formed as part of the WAIT statement. Exclusive OR means that if the bits
  of two operands are equal then the result is 0 otherwise the result is 1.
    Logical operations are defined by groups of statements which, taken
  together, constitute a Boolean "truth table" as shown in Table 1-2.

                                               BASIC PROGRAMMING RULES   13

                      Table 1-2. Boolean Truth Table
  +-----------------------------------------------------------------------+
  | The AND operation results in a 1 only if both bits are 1:             |
  |                                                                       |
  |                            1 AND 1 = 1                                |
  |                            0 AND 1 = 0                                |
  |                            1 AND 0 = 0                                |
  |                            0 AND 0 = 0                                |
  |                                                                       |
  | The OR operation results  in a 1 if either bit is 1:                  |
  |                                                                       |
  |                            1 OR 1 = 1                                 |
  |                            0 OR 1 = 1                                 |
  |                            0 OR 0 = 1                                 |
  |                            0 OR 0 = 0                                 |
  |                                                                       |
  | The NOT operation logically complements each bit:                     |
  |                                                                       |
  |                            NOT 1 = 0                                  |
  |                            NOT 0 = 1                                  |
  |                                                                       |
  | The exclusive OR (XOR) is part of the WAIT statement!                 |
  |                                                                       |
  |                            1 XOR 1 = 0                                |
  |                            1 XOR 0 = 1                                |
  |                            0 XOR 1 = 1                                |
  |                            0 XOR 0 = 0                                |
  +-----------------------------------------------------------------------+

    The logical operators AND, OR and NOT specify a Boolean arithmetic
  operation to be performed on the two operand expressions on either side
  of the operator. In the case of NOT, ONLY the operand on the RIGHT is
  considered. Logical operations (or Boolean arithmetic) aren't performed
  until all arithmetic and relational operations in an expression have been
  completed.

    EXAMPLES:

    IF A=100 AND B=100 THEN 10    (if both A and B have a value
                                   of 100 then the result is true)

    A=96 AND 32: PRINT A          (A = 32)

  14   BASIC PROGRAMMING RULES

    IF A=100 OR B=100 THEN 20     (if A or B is 100 then the
                                   result is true)

    A=64 OR 32: PRINT A           (A = 96)

    IF NOT X<Y THEN 30            (if X>=Y the result is true)

    X= NOT 96                     (result is -97 (two's complement))

  HIERARCHY OF OPERATIONS

    All expressions perform the different types of operations according to
  a fixed hierarchy. In other words, certain operations are performed be-
  fore other operations. The normal order of operations can be modified
  by enclosing two or more operands within parentheses ( ), creating a
  "subexpression." The parts of an expression enclosed in parentheses will
  be reduced to a single value before working on parts outside the par-
  entheses.
    When you use parentheses in expressions, they must be paired so that
  you always have an equal number of left and right parentheses. Otherwise,
  the BASIC error message ?SYNTAX ERROR will appear.
    Expressions which have operands inside parentheses may themselves
  be enclosed in parentheses, forming complex expressions of multiple
  levels. This is called nesting. Parentheses can be nested in expressions
  to a maximum depth of ten levels-ten matching sets of parentheses.
  The inner-most expression has its operations performed first. Some
  examples of expressions are:

                     A+B
                     C^(D+E)/2
                     ((X-C^(D+E)/2)*10)+1
                     GG$>HH$
                     JJ$+"MORE"
                     K%=1 AND M<>X
                     K%=2 OR (A=B AND M<X)
                     NOT (D=E)

    The BASIC Interpreter will normally perform operations on expressions
  by performing arithmetic operations first, then relational operations,
  and logical operations lost. Both arithmetic and logical operators have

                                               BASIC PROGRAMMING RULES   15

  an order of precedence (or hierarchy of operations) within themselves. On
  the other hand, relational operators do not have an order of precedence
  and will be performed as the expression is evaluated from left to right.
    If all remaining operators in an expression have the same level of
  precedence then operations happen from left to right. When performing
  operations on expressions within parentheses, the normal order of pre-
  cedence is maintained. The hierarchy of arithmetic and logical opera-
  tions is shown in Table 1-3 from first to last in order of precedence.

     Table 1-3. Hierarchy of Operations Performed on Expressions
  +---------------+---------------------------------+---------------------+
  |   OPERATOR    |           DESCRIPTION           |       EXAMPLE       |
  +---------------+---------------------------------+---------------------+
  |       ^       |    Exponentiation               |      BASE ^ EXP     |
  |               |                                 |                     |
  |       -       |    Negation (Unary Minus)       |         -A          |
  |               |                                 |                     |
  |      * /      |    Multiplication               |       AB * CD       |
  |               |    Division                     |       EF / GH       |
  |               |                                 |                     |
  |      + -      |    Addition                     |       CNT + 2       |
  |               |    Subtraction                  |       JK - PQ       |
  |               |                                 |                     |
  |     > = <     |    Relational Operations        |       A <= B        |
  |               |                                 |                     |
  |      NOT      |    Logical NOT                  |        NOT K%       |
  |               |    (Integer Two's Complement)   |                     |
  |               |                                 |                     |
  |      AND      |    Logical AND                  |      JK AND 128     |
  |               |                                 |                     |
  |      OR       |    Logical OR                   |       PQ OR 15      |
  +---------------+---------------------------------+---------------------+

  STRING OPERATIONS

    Strings are compared using the same relational operators (=, <>,
  <=, >=, <, >) that are used for comparing numbers. String compari-
  sons are mode by taking one character at a time (left-to-right) from
  each string and evaluating each character code position from the PET/
  CBM character set. If the character codes are the same, the characters
  are equal. If the character codes differ, the character with the lower
  code number is lower in the character set. The comparison stops when

  16   BASIC PROGRAMMING RULES

    the end of either string is reached. All other things being equal, the
  shorter string is considered less than the longer string. Leading or
  trailing blanks ARE significant.
    Regardless of the data types, at the end of all comparisons you get
  an integer result. This is true even if both operands are strings.
  Because of this a comparison of two string operands can be used as an
  operand in performing calculations. The result will be - 1 or 0 (true or
  false) and can be used as anything but a divisor since division by zero
  is illegal.

  STRING EXPRESSIONS

    Expressions are treated as if an implied "<>0" follows them. This means
  that if an expression is true then the next BASIC statements on. the same
  program line are executed. If the expression is false the rest of the
  line is ignored and the next line in the program is executed.
    Just as with numbers, you can also perform operations on string vari-
  ables. The only string arithmetic operator recognized by CBM BASIC is the
  plus sign (+) which is used to perform concatenation of strings. When
  strings are concatenated, the string on the right of the plus sign is
  appended to the string on the left, forming a third string as a result.
  The result can be printed immediately, used in a comparison, or assigned
  to a variable name. If a string data item is compared with (or set equal
  to) a numeric item, or vice-versa, the BASIC error message ?TYPE MISMATCH
  will occur. Some examples of string expressions and concatenation are:

    10 A$="FILE": B$="NAME"
    20 NAM$=A$+B$                      (gives the string: FILENAME)
    30 RES$="NEW "+A$+B$               (gives the string: NEW FILENAME)
                ^
                |       +-----------------+
                +-------+ Note space here.|
                        +-----------------+

                                               BASIC PROGRAMMING RULES   17

  PROGRAMMING TECHNIQUES

  DATA CONVERSIONS

    When necessary, the CBM BASIC Interpreter will convert a numeric
  data item from an integer to floating-point. or vice-versa, according to
  the following rules:

    o All arithmetic and relational operations are performed in floating
      point format. Integers are converted to floating-point form for
      evaluation of the expression, and the result is converted back to
      integer. logical operations convert their operands to integers an
      return an integer result.
    o If a numeric variable name of one type is set equal to a numeric
      data item of a different type, the number will be converted and
      stored as the data type declared in the variable name.
    o When a floating-point value is converted to an integer, the frac-
      tional portion is truncated (eliminated) and the integer result is
      less than or equal to the floating-point value. If the result is
      outside the range of +32767 thru -32768, the BASIC error message
      ?ILLEGAL QUANTITY will occur.

  USING THE INPUT STATEMENT

    Now that you know what variables are, let's take that information an
  put it together with the INPUT statement for some practical program-
  ming applications.
    In our first example, you can think of a variable as a "storage com-
  partment" where the Commodore 64 stores the user's response to your
  prompt question. To write a program which asks the user to type in a
  name, you might assign the variable N$ to the name typed in. Now
  every time you PRINT N$ in your program, the Commodore 64 will
  automatically PRINT the name that the user typed in.
    Type the word NEW on your Commodore 64. Hit the <RETURN> key
  and try this example:

    10 PRINT"YOUR NAME": INPUT N$
    20 PRINT"HELLO",N$

  18   BASIC PROGRAMMING RULES

  In this example you used N to remind yourself that this variable stands
  for "NAME". The dollar sign ($) is used to tell the computer that you're
  using a string variable. It is important to differentiate between the two
  types of variables:

    1) NUMERIC
    2) STRING

    You probably remember from the earlier sections that numeric vari-
  ables are used to store number values such as 1, 100, 4000, etc. A
  numeric variable can be a single letter (A), any two letters (AB), a
  letter and a number (AI), or two letters and a number (AB1). You can save
  memory space by using shorter variables. Another helpful hint is to use
  letters and numbers for different categories in the same program (AI,
  A2, A3). Also, if you want whole numbers for an answer instead of
  numbers with decimal points, all you have to do is put a percent sign
  (%) at the end of your variable name (AB%, AI%, etc.)
  Now let's look at a few examples that use different types of variables
  and expressions with the INPUT statement.

    10 PRINT"ENTER A NUMBER": INPUT A
    20 PRINT A

    10 PRINT"ENTER A WORD": INPUT A$
    20 PRINT A$

    10 PRINT"ENTER A NUMBER": INPUT A
    20 PRINT A "TIMES 5 EQUALS" A*5
  +-----------------------------------------------------------------------+
  |   NOTE: Example 3 shows that MESSAGES or PROMPTS are inside the       |
  | quotation marks (" ") while the variables are outside. Notice, too,   |
  | that in line 20 the variable A was printed first, then the message    |
  | "TIMES 5 EQUALS", and then the calculation, multiply variable A by 5  |
  | (A*5).                                                                |
  +-----------------------------------------------------------------------+

    Calculations are important in most programs. You have a choice of using
  "actual numbers" or variables when doing calculations, but if you're
  working with numbers supplied by a user you must use numeric variables.
  Begin by asking the user to type in two numbers like this:

    10 PRINT"TYPE 2 NUMBERS": INPUT A: INPUT B

                                               BASIC PROGRAMMING RULES   19

                        INCOME/EXPENSE BUDGET EXAMPLE

start tok64 page20.prg
  5 print"{clear}"
  10 print"monthly income":input in
  20 print
  30 print"expense category 1":input e1$
  40 print"expense amount":input e1
  50 print
  60 print"expense category 2":input e2$
  70 print"expense amount":input e2
  80 print
  90 print"expense category 3":input e3$
  100 print"expense amount":input e3
  110 print"{clear}"
  120 e=e1+e2+e3
  130 ep=e/in
  140 print"monthly income: $"in
  150 print"total expenses: $"e
  160 print"balance equals: $"in-e
  170 print
  180 print e1$"="(e1/e)*100"% of total expenses"
  190 print e2$"="(e2/e)*100"% of total expenses"
  200 print e3$"="(e3/e)*100"% of total expenses"
  210 print
  220 print"your expenses="ep*100"% of your total income"
  230 forx=1to5000:next:print
  240 print"repeat? (y or n)":input y$:if y$="y"then 5
  250 print"{clear}":end
stop tok64

  +-----------------------------------------------------------------------+
  | NOTE:IN can NOT = 0, and E1, E2, E3 can NOT all be 0 at the same time.|
  +-----------------------------------------------------------------------+

  20   BASIC PROGRAMMING RULES

                         LINE-BY-LINE EXPLANATION OF
                        INCOME/EXPENSE BUDGET EXAMPLE
  +-----------+-----------------------------------------------------------+
  |  Line(s)  |                    Description                            |
  +-----------+-----------------------------------------------------------+
  |     5     |  Clears the screen.                                       |
  |    10     |  PRINT/INPUT statement.                                   |
  |    20     |  Inserts blank line.                                      |
  |    30     |  Expense Category 1 = E1$.                                |
  |    40     |  Expense Amount = E1.                                     |
  |    50     |  Inserts blank line.                                      |
  |    60     |  Expense Category 2 = E2.                                 |
  |    70     |  Expense Amount 2 = E2.                                   |
  |    80     |  Inserts blank line.                                      |
  |    90     |  Expense Category 3 = E3.                                 |
  |   100     |  Expense Amount 3 = E3.                                   |
  |   110     |  Clears the screen.                                       |
  |   120     |  Add Expense Amounts = E.                                 |
  |   130     |  Calculate Expense/income%.                               |
  |   140     |  Display Income.                                          |
  |   150     |  Display Total Expenses.                                  |
  |   160     |  Display Incomes - Expenses.                              |
  |   170     |  Inserts blank line.                                      |
  |   180-200 |  lines 180-200 calculate % each expense                   |
  |           |    amount is of total expenses.                           |
  |   210     |  Inserts blank line.                                      |
  |   220     |  Display E/IN %.                                          |
  |   230     |  Time delay loop.                                         |
  +-----------+-----------------------------------------------------------+

  Now multiply those two numbers together to create a new variable C as
  shown in line 20 below:

    20 C=A*B

  To PRINT the result as a message type

    30 PRINT A "TIMES" B "EQUALS" C

  Enter these 3 lines and RUN the program. Notice that the messages are
  inside the quotes while the variables are not.

                                               BASIC PROGRAMMING RULES   21

    Now let's say that you wanted a dollar sign ($) in front of the number
  represented by variable C. The $ must be PRINTed inside quotes and in
  front of variable C. To add the $ to your program hit the <RUN/STOP>
  and <RESTORE> keys. Now type in line 40 as follows:

    40 PRINT"$" C

  Now hit <RETURN>, type RUN and hit <RETURN> again.
  The dollar sign goes in quotes because the variable C only represents
  a number and can't contain a $. If the number represented by C was
  100 then the Commodore 64 screen would display $ 100. But, if you
  tried to PRINT $C without using the quotes, you would get a ?SYNTAX
  ERROR message.
    One last tip about $$$: You can create a variable that represents a
  dollar sign which you can then substitute for the $ when you want to use
  it with numeric variables. For example:

    10 Z$="$"

  Now whenever you need a dollar sign you can use the string variable
  Z$. Try this:

    10 Z$="$": INPUT A
    20 PRINT Z$A

  line 10 defines the $ as a string variable called Z$, and then INPUTs a
  number called A. line 20 PRINTs Z$ ($) next to A (number).
    You'll probably find that it's easier to assign certain characters,
  like dollar signs, to a string variable than to type "$" every time you
  want to calculate dollars or other items which require "" like %.

  USING THE GET STATEMENT

    Most simple programs use the INPUT statement to get data from the
  person operating the computer. When you're dealing with more complex
  needs, like protection from typing errors, the GET statement gives you
  more flexibility and your program more "intelligence." This section shows
  you how to use the GET statement to add some special screen editing
  features to your programs.

  22   BASIC PROGRAMMING RULES

    The Commodore 64 has a keyboard buffer that holds up to 10 characters.
  This means that if the computer is busy doing some operation and it's
  not reading the keyboard, you can still type in up to 10 characters,
  which will be used as soon as the Commodore 64 finishes what it was
  doing. To demonstrate this, type in this program on your Commodore 64:

    NEW
    10 TI$="000000"
    20 IF TI$ < "000015" THEN 20

  Now type RUN, hit <RETURN>  and while the program is RUNning type in the
  word HELLO.
    Notice that nothing happened for about IS seconds when the program
  started. Only then did the message HELLO appear on the screen.
    Imagine standing in line for a movie. The first person in the line is
  the first to get a ticket and leave the line. The last person in line is
  last for a ticket. The GET statement acts like a ticket taker. First it
  looks to see if there are any characters "in line." In other words have
  any keys been typed. If the answer is yes then that character gets placed
  in the appropriate variable. If no key was pressed then an empty value is
  assigned to a variable,
    At this point it's important to note that if you try to put more than
  10 characters into the buffer at one time, all those over the 10th
  character will be lost.
    Since the GET statement will keep going even when no character is
  typed, it is often necessary to put the GET statement into a loop so that
  it will have to wait until someone hits a key or until a character is
  received through your program.
    Below is the recommended form for the GET statement. Type NEW to erase
  your previous program.

    10 GET A$: IF A$ ="" THEN 10

  Notice that there is NO SPACE between the quote marks("") on this line.
  This indicates an empty value and sends the program back to the GET
  statement in a continuous loop until someone hits a key on the computer.
  Once a key is hit the program will continue with the line following line
  10. Add this line to your program:

    100 PRINT A$;: GOTO 10

					       BASIC PROGRAMMING RULES   23

  Now RUN the program. Notice that no cursor appears on the screen, but
  any character you type will be printed in the screen. This 2-line program
  can be turned into part of a screen editor program as shown below.
    There are many things you can do with a screen editor. You can have
  a flashing cursor. You can keep certain keys like <CLR/HOME> from
  accidentally erasing the whole screen. You might even want to be able to
  use your function keys to represent whole words or phrases. And speaking
  of function keys, the following program lines give each function key a
  special purpose. Remember this is only the beginning of a program that
  you can customize for your needs.

    20 IF A$ = CHR$(133) THEN POKE 53280,8: GOTO 10
    30 IF A$ = CHR$(134) THEN POKE 53281,4: GOTO 10
    40 IF A$ = CHR$(135) THEN A$="DEAR SIR:"+CHR$(13)
    50 IF A$ = CHR$(136) THEN A$="SINCERELY,"+CHR$(13)

    The CHR$ numbers in parentheses come from the CHR$ code chart in
  Appendix C. The chart lists a different number for each character. The
  four function keys are set up to perform the tasks represented by the
  instructions that follow the word THEN in each line. By changing the
  CHR$ number inside each set of parentheses you can designate different
  keys. Different instructions would be performed if you changed the
  information after the THEN statement.

  HOW TO CRUNCH BASIC PROGRAMS

  You can pack more instructions - and power - into your BASIC programs by
  making each program as short as possible. This process of shortening
  programs is called "crunching."
    Crunching programs lets you squeeze the maximum possible number of
  instructions into your program. It also helps you reduce the size of
  programs which might not otherwise run in a given size; and if you're
  writing a program which requires the input of data such as inventory
  items, numbers or text, a short program will leave more memory space free
  to hold data.

  ABBREVIATING KEYWORDS

    A list of keyword abbreviations is given in Appendix A. This is helpful
  when you program because you can actually crowd more information on each
  line using abbreviations. The most frequently used abbreviation is

  24   BASIC PROGRAMMING RULES

  the question mark (?) which is the BASIC abbreviation for the PRINT
  command. However, if you LIST a program that has abbreviations, the
  Commodore 64 will automatically print out the listing with the full-
  length keywords. If any program line exceeds 80 characters (2 lines on
  the screen) with the keywords unabbreviated, and you want to change it,
  you will have to re-enter that line with the abbreviations before saving
  the program. SAVEing a program incorporates the keywords without
  inflating any lines because BASIC keywords are tokenized by the Commodore
  64. Usually, abbreviations are added after a program is written and it
  isn't going to be LISTed any more before SAVEing.

  SHORTENING PROGRAM LINE NUMBERS

    Most programmers start their programs at line 100 and number each fine
  at intervals of 10 (i.e., 100, 110, 120). This allows extra lines of
  instruction to be added (111, 112, etc.) as the program is developed.
  One means of crunching the program after it is completed is to change
  the fine numbers to the lowest numbers possible (i.e., 1, 2, 3) because
  longer line numbers take more memory than shorter numbers when referenced
  by GOTO and GOSUB statements. For instance, the number 100 uses 3 bytes
  of memory (one for each number) while the number I uses only 1 byte.

  PUTTING MULTIPLE INSTRUCTIONS ON EACH LINE

    You can put more than one instruction on each numbered line in your
  program by separating them by a colon. The only limitation is that all
  the instructions on each line, including colons, should not exceed the
  standard 80-character line length. Here is an example of two programs,
  before and after crunching:

  BEFORE CRUNCHING:              AFTER CRUNCHING:

  10 PRINT"HELLO...";            10 PRINT "HELLO...";:FORT=1TO500:NEXT:
  20 FOR T=1 TO 500: NEXT           PRINT"HELLO, AGAIN...":GOTO10
  30 PRINT"HELLO, AGAIN..."
  40 GOTO 10

  REMOVING REM STATEMENTS

    REM statements are helpful in reminding yourself-or showing other
  programmers - what a particular section of a program is doing. However,
  when the program is completed and ready to use, you probably

					       BASIC PROGRAMMING RULES   25

  won't need those REM statements anymore and you can save quite a bit of
  space by removing the REM statements. If you plan to revise or study the
  program structure in the future, it's a good idea to keep a copy on file
  with the REM statements intact.

  USING VARIABLES

    If a number, word or sentence is used repeatedly in your program it's
  usually best to define those long words or numbers with a one or two
  letter variable. Numbers can be defined as single letters. Words and
  sentences can be defined as string variables using a letter and dollar
  sign. Here's one example:

  BEFORE CRUNCHING:                 AFTER CRUNCHING:

  10 POKE 54296,15                  10 V=54296:F=54273
  20 POKE 54276,33                  20 POKEV,15:POKE54276,33
  30 POKE 54273,10                  30 POKEF,10:POKEF,40:POKEF,70
  40 POKE 54273,40                  40 POKEV,0
  50 POKE 54273,70
  60 POKE 54296,0

  USING READ AND DATA STATEMENTS

    Large amounts of data can be typed in as one piece of data at a time,
  over and over again ... or you can print the instructional part of the
  program ONCE and print all the data to be handled in a long running list
  called the DATA statement. This is especially good for crowding large
  lists of numbers into a program.

  USING ARRAYS AND MATRICES

  Arrays and matrices are similar to DATA statements in that long amounts
  of data can be handled as a list, with the data handling portion of the
  program drawing from that list, in sequence. Arrays differ in that the
  list can be multi-dimensional

  ELIMINATING SPACES

    One of the easiest ways to reduce the size of your program is to
  eliminate all the spaces. Although we often include spaces in sample

  26   BASIC PROGRAMMING RULES

  programs to provide clarity, you actually don't need any spaces in your
  program and will save space if you eliminate them.

  USING GOSUB ROUTINES

  If you use a particular line or instruction over and over, it might be
  wise to GOSUB to the line from several places in your program, rather
  than write the whole line or instruction every time you use it.

  USING TAB AND SPC

    Instead of PRINTing several cursor commands to position a character
  on the screen, it is often more economical to use the TAB and SPC in-
  structions to position words or characters on the screen.

					       BASIC PROGRAMMING RULES   27

                                                 CHAPTER 2

                                            BASIC LANGUAGE
                                                VOCABULARY

                           o Introduction
                           o BASIC Keywords, Abbreviations,
                             and Function Types
                           o Description of BASIC Keywords
                             (Alphabetical)
                           o The Commodore 64 Keyboard and
                             Features
                           o Screen Editor

  INTRODUCTION

  This chapter explains CBM BASIC Language keywords. First we give you an
  easy to read list of keywords, their abbreviations and what each letter
  looks like on the screen. Then we explain how the syntax and operation of
  each keyword works in detail, and examples are shown to give you an idea
  as to how to use them in your programs.
    As a convenience, Commodore 64 BASIC allows you to abbreviate most
  keywords. Abbreviations are entered by typing enough letters of the
  keyword to distinguish it from all other keywords, with the last letter
  or graphics entered holding down the <SHIFT> key.
    Abbreviations do NOT save any memory when they're used in programs,
  because all keywords are reduced to single-character "tokens" by the
  BASIC Interpreter. When a program containing abbreviations is listed, all
  keywords appear in their fully spelled form. You can use abbreviations to
  put more statements onto a program line even if they won't fit onto the
  80-character logical screen line. The Screen Editor works on an 80-
  character line. This means that if you use abbreviations on any line that
  goes over 80 characters, you will NOT be able to edit that line when
  LISTed. Instead, what you'll have to do is (1) retype the entire line
  including all abbreviations, or (2) break the single line of code into
  two lines, each with its own line number, etc.
    A complete list of keywords, abbreviations, and their appearance on the
  screen is presented in Table 2-1. They are followed by an alphabetical
  description of all the statements, commands, and functions available on
  your Commodore 64.
    This chapter also explains the BASIC functions built into the BASIC
  Language Interpreter. Built-in functions can be used in direct mode
  statements or in any program, without having to define the function
  further. This is NOT the case with user-defined functions. The results of
  built-in BASIC functions can be used as immediate output or they can be
  assigned to a variable name of an appropriate type. There are two types
  of BASIC functions:

    1) NUMERIC
    2) STRING

    Arguments of built-in functions are always enclosed in parentheses ().
  The parentheses always come directly after the function keyword and NO
  SPACES between the last letter of the keyword and the left parenthesis (.

  30   BASIC LANGUAGE VOCABULARY

    The type of argument needed is generally decided by the data type in
  the result. Functions which return a string value as their result are
  identified by having a dollar sign ($) as the last character of the
  keyword. In some cases string functions contain one or more numeric
  argument. Numeric functions will convert between integer and floating-
  point format as needed. In the descriptions that follow, the data type of
  the value returned is shown with each function name. The types of argu-
  ments are also given with the statement format.

		    Table 2-1. COMMODORE 64 BASIC KEYWORDS
  +-----------+----------------------+----------------+-------------------+
  |  COMMAND  |     ABBREVIATION     |     SCREEN     |   FUNCTION TYPE   |
  +-----------+----------------------+----------------+-------------------+
  |           |                      |                |                   |
  |    ABS    |     A <SHIFT+B>      |                |     NUMERIC       |
  |           |                      |                |                   |
  |    AND    |     A <SHIFT+N>      |                |                   |
  |           |                      |                |                   |
  |    ASC    |     A <SHIFT+S>      |                |     NUMERIC       |
  |           |                      |                |                   |
  |    ATN    |     A <SHIFT+T>      |                |     NUMERIC       |
  |           |                      |                |                   |
  |    CHR$   |     C <SHIFT+H>      |                |     STRING        |
  |           |                      |                |                   |
  |    CLOSE  |     CL <SHIFT+O>     |                |                   |
  |           |                      |                |                   |
  |    CLR    |     C <SHIFT+L>      |                |                   |
  |           |                      |                |                   |
  |    CMD    |     C <SHIFT+M>      |                |                   |
  |           |                      |                |                   |
  |    CONT   |     C <SHIFT+O>      |                |                   |
  |           |                      |                |                   |
  |    COS    |        none          |      COS       |     NUMERIC       |
  |           |                      |                |                   |
  |    DATA   |     D <SHIFT+A>      |                |                   |
  |           |                      |                |                   |
  |    DEF    |     D <SHIFT+E>      |                |                   |
  |           |                      |                |                   |
  |    DIM    |     D <SHIFT+I>      |                |                   |

					     BASIC LANGUAGE VOCABULARY   31

  +-----------+----------------------+----------------+-------------------+
  |  COMMAND  |     ABBREVIATION     |     SCREEN     |   FUNCTION TYPE   |
  +-----------+----------------------+----------------+-------------------+
  |           |                      |                |                   |
  |    END    |     E <SHIFT+N>      |                |                   |
  |           |                      |                |                   |
  |    EXP    |     E <SHIFT+X>      |                |     NUMERIC       |
  |           |                      |                |                   |
  |    FN     |        none          |       FN       |                   |
  |           |                      |                |                   |
  |    FOR    |     F <SHIFT+O>      |                |                   |
  |           |                      |                |                   |
  |    FRE    |     F <SHIFT+R>      |                |     NUMERIC       |
  |           |                      |                |                   |
  |    GET#   |        none          |      GET#      |                   |
  |           |                      |                |                   |
  |    GOSUB  |     GO <SHIFT+S>     |                |                   |
  |           |                      |                |                   |
  |    GOTO   |     G <SHIFT+O>      |                |                   |
  |           |                      |                |                   |
  |    IF     |        none          |       IF       |                   |
  |           |                      |                |                   |
  |    INPUT  |        none          |     INPUT      |                   |
  |           |                      |                |                   |
  |    INPUT# |     I <SHIFT+N>      |                |                   |
  |           |                      |                |                   |
  |    INT    |        none          |      INT       |     NUMERIC       |
  |           |                      |                |                   |
  |    LEFT$  |     LE <SHIFT+F>     |                |     STRING        |
  |           |                      |                |                   |
  |    LEN    |        none          |      LEN       |     NUMERIC       |
  |           |                      |                |                   |
  |    LET    |     L <SHIFT+E>      |                |                   |
  |           |                      |                |                   |
  |    LIST   |     L <SHIFT+I>      |                |                   |
  |           |                      |                |                   |
  |    LOAD   |     L <SHIFT+O>      |                |                   |
  |           |                      |                |                   |
  |    LOG    |        none          |      LOG       |     NUMERIC       |

  32   BASIC LANGUAGE VOCABULARY

  +-----------+----------------------+----------------+-------------------+
  |  COMMAND  |     ABBREVIATION     |     SCREEN     |   FUNCTION TYPE   |
  +-----------+----------------------+----------------+-------------------+
  |           |                      |                |                   |
  |    MID$   |     M <SHIFT+I>      |                |     STRING        |
  |           |                      |                |                   |
  |    NEW    |        none          |      NEW       |                   |
  |           |                      |                |                   |
  |    NEXT   |     N <SHIFT+E>      |                |                   |
  |           |                      |                |                   |
  |    NOT    |     N <SHIFT+O>      |                |                   |
  |           |                      |                |                   |
  |    ON     |        none          |       ON       |                   |
  |           |                      |                |                   |
  |    OPEN   |     O <SHIFT+P>      |                |                   |
  |           |                      |                |                   |
  |    OR     |        none          |       OR       |                   |
  |           |                      |                |                   |
  |    PEEK   |     P <SHIFT+E>      |                |     NUMERIC       |
  |           |                      |                |                   |
  |    POKE   |     P <SHIFT+O>      |                |                   |
  |           |                      |                |                   |
  |    POS    |        none          |      POS       |     NUMERIC       |
  |           |                      |                |                   |
  |    PRINT  |          ?           |       ?        |                   |
  |           |                      |                |                   |
  |    PRINT# |     P <SHIFT+R>      |                |                   |
  |           |                      |                |                   |
  |    READ   |     R <SHIFT+E>      |                |                   |
  |           |                      |                |                   |
  |    REM    |        none          |      REM       |                   |
  |           |                      |                |                   |
  |    RESTORE|     RE <SHIFT+S>     |                |                   |
  |           |                      |                |                   |
  |    RETURN |     RE <SHIFT+T>     |                |                   |
  |           |                      |                |                   |
  |    RIGHT$ |     R <SHIFT+I>      |                |     STRING        |
  |           |                      |                |                   |
  |    RND    |     R <SHIFT+N>      |                |     NUMERIC       |
  |           |                      |                |                   |
  |    RUN    |     R <SHIFT+U>      |                |                   |

                                             BASIC LANGUAGE VOCABULARY   33

  |           |                      |                |                   |
  |    SAVE   |     S <SHIFT+A>      |                |                   |
  |           |                      |                |                   |
  |    SGN    |     S <SHIFT+G>      |                |     NUMERIC       |
  |           |                      |                |                   |
  |    SIN    |     S <SHIFT+I>      |                |     NUMERIC       |
  |           |                      |                |                   |
  |    SPC(   |     S <SHIFT+P>      |                |     SPECIAL       |
  |           |                      |                |                   |
  |    SQR    |     S <SHIFT+Q>      |                |     NUMERIC       |
  |           |                      |                |                   |
  |    STATUS |          ST          |       ST       |     NUMERIC       |
  |           |                      |                |                   |
  |    STEP   |     ST <SHIFT+E>     |                |                   |
  |           |                      |                |                   |
  |    STOP   |     S <SHIFT+T>      |                |                   |
  |           |                      |                |                   |
  |    STR$   |     ST <SHIFT+R>     |                |     STRING        |
  |           |                      |                |                   |
  |    SYS    |     S <SHIFT+Y>      |                |                   |
  |           |                      |                |                   |
  |    TAB(   |     T <SHIFT+A>      |                |     SPECIAL       |
  |           |                      |                |                   |
  |    TAN    |        none          |      TAN       |     NUMERIC       |
  |           |                      |                |                   |
  |    THEN   |     T <SHIFT+H>      |                |                   |
  |           |                      |                |                   |
  |    TIME   |         TI           |       TI       |     NUMERIC       |
  |           |                      |                |                   |
  |    TIME$  |         TI$          |      TI$       |     STRING        |
  |           |                      |                |                   |
  |    TO     |        none          |       TO       |                   |
  |           |                      |                |                   |
  |    USR    |     U <SHIFT+S>      |                |     NUMERIC       |
  |           |                      |                |                   |
  |    VAL    |     V <SHIFT+A>      |                |     NUMERIC       |
  |           |                      |                |                   |
  |    VERIFY |     V <SHIFT+E>      |                |                   |
  |           |                      |                |                   |
  |    WAIT   |     W <SHIFT+A>      |                |                   |
  +-----------+----------------------+----------------+-------------------+

  34   BASIC LANGUAGE VOCABULARY

  DESCRIPTION OF BASIC KEYWORDS

  ABS

  TYPE: Function-Numeric
  FORMAT: ABS(<expression>)

    Action: Returns the absolute value of the number, which is its value
  without any signs. The absolute value of a negative number is that
  number multiplied by -1.

  EXAMPLES of ABS Function:

    10 X = ABS (Y)
    10 PRINT ABS (X*J)
    10 IF X = ABS (X) THEN PRINT"POSITIVE"

  AND

  TYPE: Operator
  FORMAT: <expression> AND <expression>

    Action: AND is used in Boolean operations to test bits. it is also used
  in operations to check the truth of both operands.
    In Boolean algebra, the result of an AND operation is 1 only if both
  numbers being ANDed are 1. The result is 0 if either or both is 0
  (false).

  EXAMPLES of 1-Bit AND operation:

            0         1         0         1
        AND 0     AND 0     AND 1     AND 1
       ------     -----     -----     -----
            0         0         0         1

    The Commodore 64 performs the AND operation on numbers in the range
  from -32768 to +32767. Any fractional values are not used, and numbers
  beyond the range will cause an ?ILLEGAL QUANTITY error message. When

                                             BASIC LANGUAGE VOCABULARY   35

  converted to binary format, the range allowed yields 16 bits for each
  number. Corresponding bits are ANDed together, forming a 16-bit result
  in the same range.

  EXAMPLES of 16-Bit AND Operation:

                                         17
                                    AND 194
                                   --------
                           0000000000010001
                       AND 0000000011000010
                 --------------------------
                  (BINARY) 0000000000000000
                 --------------------------
                 (DECIMAL)                0

                                      32007
                                  AND 28761
                                 ----------
                           0111110100000111
                       AND 0111000001011001
                 --------------------------
                  (BINARY) 0111000000000001
                 --------------------------
                 (DECIMAL)            28673

                                       -241
                                  AND 15359
                                 ----------
                           1111111100001111
                       AND 0011101111111111
                 --------------------------
                  (BINARY) 0011101100001111
                 --------------------------
                 (DECIMAL)            15119

  36   BASIC LANGUAGE VOCABULARY

    When evaluating a number for truth or falsehood, the computer assumes
  the number is true as long as its value isn't 0. When evaluating a
  comparison, it assigns a value of -I if the result is true, while false
  has a value of 0. In binary format, -1 is all 1's and 0 is all 0's.
  Therefore, when ANDing true/false evaluations, the result will be true if
  any bits in the result are true.

  EXAMPLES of Using AND with True/False Evaluations:

    50 IF X=7 AND W=3 THEN GOTO 10: REM ONLY TRUE IF BOTH X=7
       AND W=3 ARE TRUE
    60 IF A AND Q=7 THEN GOTO 10: REM TRUE IF A IS NON-ZERO
       AND Q=7 IS TRUE

   ASC

  TYPE: Function-Numeric
  FORMAT: ASC(<string>)

    Action: ASC will return a number from 0 to 255 which corresponds to
  the Commodore ASCII value of the first character in the string. The table
  of Commodore ASCII values is shown in Appendix C.

  EXAMPLES OF ASC Function:

    10 PRINT ASC("Z")
    20 X = ASC("ZEBRA")
    30 J = ASC(J$)

    If there are no characters in the string, an ?ILLEGAL QUANTITY error
  results. In the third example above, if J$="", the ASC function will not
  work. The GET and GET# statement read a CHR$(0) as a null string. To
  eliminate this problem, you should add a CHR$(0) to the end of the
  string as shown below.

  EXAMPLE of ASC Function Avoiding ILLEGAL QUANTITY ERROR:

    30 J = ASC(J$ + CHR$(0))

                                             BASIC LANGUAGE VOCABULARY   37

  ATN

  TYPE: Function-Numeric
  FORMAT: ATN(<number>)

    Action: This mathematical function returns the arctangent of the
  number. The result is the angle (in radians) whose tangent is the number
  given. The result is always in the range -pi/2 to +pi/2.

  EXAMPLES of ATN Function:

    10 PRINT ATN(0)
    20 X = ATN(J)*180/ {pi} : REM CONVERT TO DEGREES

  CHR$

  TYPE: Function-String
  FORMAT: CHR$ (<number>)

    Action: This function converts a Commodore ASCII code to its character
  equivalent. See Appendix C for a list of characters and their codes. The
  number must have a value between 0 and 255, or an ?ILLEGAL QUANTITY error
  message results.

  EXAMPLES of CHR$ Function:

    10 PRINT CHR$(65) : REM 65 = UPPER CASE A
    20 A$=CHR$(13) : REM 13 = RETURN KEY
    50 A=ASC(A$) : A$ = CHR$(A) : REM CONVERTS TO C64 ASCII CODE AND BACK

  38   BASIC LANGUAGE VOCABULARY

  CLOSE

  TYPE: I/O Statement
  FORMAT: CLOSE <file number>

    Action: This statement shuts off any data file or channel to a device.
  The file number is the same as when the file or device was OPENed (see
  OPEN statement and the section on INPUT/OUTPUT programming).
    When working with storage devices like cassette tape and disks, the
  CLOSE operation stores any incomplete buffers to the device. When this
  is not performed, the file will be incomplete on the tape and unreadable
  on the disk. The CLOSE operation isn't as necessary with other devices,
  but it does free up memory for other files. See your external device
  manual for more details.

  EXAMPLES of CLOSE Statement:

    10 CLOSE 1
    20 CLOSE X
    30 CLOSE 9*(1+J)

  CLR

  TYPE: Statement
  FORMAT: CLR

    Action: This statement makes available RAM memory that had been used
  but is no longer needed. Any BASIC program in memory is untouched, but
  all variables, arrays, GOSUB addresses, FOR...NEXT loops, user-defined
  functions, and files are erased from memory, and their space is mode
  available to new variables, etc.

                                             BASIC LANGUAGE VOCABULARY   39

    In the case of files to the disk and cassette tape, they are not
  properly CLOSED by the CLR statement. The information about the files is
  lost to the computer, including any incomplete buffers. The disk drive
  will still think the file is OPEN. See the CLOSE statement for more
  information on this.

  EXAMPLE of CLR Statement:

    10 X=25
    20 CLR
    30 PRINT X

    RUN
    0

    READY

  CMD

  TYPE: I/O Statement
  FORMAT: <file number> [,string]

    Action: This statement switches the primary- output device from the TV
  screen to the file specified. This file could be on disk, tape, printer,
  or an I/O device like the modem. The file number must be specified in a
  prior OPEN statement. The string, when specified, is sent to the file.
  This is handy for titling printouts, etc.
    When this command is in effect, any PRINT statements and LIST commands
  will not display on the screen, but will send the text in the same
  format to the file.
    To re-direct the output back to the screen, the PRINT# command should
  send a blank line to the CMD device before CLOSEing, so it will
  stop expecting data (called "un-listening" the device).

  40   BASIC LANGUAGE VOCABULARY

    Any system error (like ?SYNTAX ERROR) will cause output to return to
  the screen. Devices aren't un-listened by this, so you should send a
  blank line after an error condition. (See your printer or disk manual for
  more details.)

  EXAMPLES of CMD Statement:

    OPEN 4,4: CMD 4,"TITLE" : LIST: REM LISTS PROGRAM ON PRINTER
    PRINT#4: CLOSE 4: REM UN-LISTENS AND CLOSES PRINTER

    10 OPEN 1,1,1,"TEST" : REM CREATE SEQ FILE
    20 CMD 1 : REM OUTPUT TO TAPE FILE, NOT SCREEN
    30 FOR L = 1 TO 100
    40 PRINT L: REM PUTS NUMBER IN TAPE BUFFER
    50 NEXT
    60 PRINT#1 : REM UNLISTEN
    70 CLOSE 1 : REM WRITE UNFINISHED BUFFER, PROPERLY FINISH

  CONT

  TYPE: Command
  FORMAT: CONT

    Action: This command re-starts the execution of a program which was
  halted by a STOP or END statement or the <RUN/STOP> key being pressed.
  The program will re-start at the exact place from which it left off.
    While the program is stopped, the user can inspect or change any
  variables or look at the program. When debugging or examining a program,
  STOP statements can be placed at strategic locations to allow examination
  of variables and to check the flow of the program.
    The error message CAN'T CONTINUE will result from editing the program
  (even just hitting <RETURN> with the cursor on an unchanged line), or if
  the program halted due to an error, or if you caused an error before
  typing CONT to re-start the program.

  EXAMPLE of CONT Command:

    10 PI=0:C=1
    20 PI=PI+4/C-4/(C+2)
    30 PRINT PI
    40 C=C+4:GOTO 20

                                             BASIC LANGUAGE VOCABULARY   41

    This program calculates the value of PI. RUN this program, and after
  a short while hit the <RUN/STOP> key. You will see the display:

                 +----------------------------------+
    BREAK IN 20  | NOTE: Might be different number. |
                 +----------------------------------+

    Type the command PRINT C to see how far the Commodore 64 has gotten.
  Then use CONT to resume from where the Commodore 64 left off.

  COS

  TYPE: Function
  FORMAT: COS (<number>)

    Action: This mathematical function calculates the cosine of the number,
  where the number is an angle in radians.

  EXAMPLES of COS Function:

    10 PRINT COS(0)
    20 X = COS(Y* {pi} /180) : REM CONVERT DEGREES TO RADIANS

  DATA

  TYPE: Statement
  FORMAT: DATA <list of constants>

    Action: DATA statements store information within a program. The program
  uses the information by means of the READ statement, which pulls
  successive constants from the DATA statements.
    The DATA statements don't have to be executed by the program, they
  only have to be present. Therefore, they are usually placed at the end of
  the program.
    All data statements in a program are treated as a continuous list. Data
  is READ from left to right, from the lowest numbered line to the highest.
  If the READ statement encounters data that doesn't fit the type requested
  (if it needs a number and finds a string) an error message occurs.

  42   BASIC LANGUAGE VOCABULARY

    Any characters can be included as data, but if certain ones are used
  the data item must be enclosed by quote marks (" "). These include
  punctuation like comma (,), colon (:), blank spaces, and shifted letters,
  graphics, and cursor control characters.

  EXAMPLES of DATA Statement:

    10 DATA 1,10,5,8
    20 DATA JOHN,PAUL,GEORGE,RINGO
    30 DATA "DEAR MARY, HOW ARE YOU, LOVE, BILL"
    40 DATA -1.7E-9, 3.33

  DEF FN

  TYPE: Statement
  FORMAT: DEF FN <name> ( <variable> ) = <expression>

    Action: This sets up a user-defined function that can be used later in
  the program. The function can consist of any mathematical formula. User-
  defined functions save space in programs where a long formula is used in
  several places. The formula need only be specified once, in the
  definition statement, and then it is abbreviated as a function name. It
  must be executed once, but any subsequent executions are ignored.
    The function name is the letters FN followed by any variable name. This
  can be 1 or 2 characters, the first being a letter and the second a
  letter or digit.

  EXAMPLES of DEF FN Statement:

    10 DEF FN A(X)=X+7
    20 DEF FN AA(X)=Y*Z
    30 DEF FN A9(Q) = INT(RND(1)*Q+1)

    The function is called later in the program by using the function name
  with a variable in parentheses. This function name is used like any other
  variable, and its value is automatically calculated,

                                             BASIC LANGUAGE VOCABULARY   43

  EXAMPLES of FN Use:

    40 PRINT FN A(9)
    50 R=FN AA(9)
    60 G=G+FN A9(10)

    In line 50 above, the number 9 inside the parentheses does not affect
  the outcome of the function, because the function definition in line 20
  doesn't use the variable in the parentheses. The result is Y times Z,
  regardless of the value of X. In the other two functions, the value in
  parentheses does affect the result.

  DIM

  TYPE: Statement
  FORMAT: DIM <variable> ( <subscripts> )[
          <variable> ( <subscripts> )...]

    Action: This statement defines an array or matrix of variables. This
  allows you to use the variable name with a subscript. The subscript
  points to the element being used. The lowest element number in an array
  is zero, and the highest is the number given in the DIM statement, which
  has a maximum of 32767.
    The DIM statement must be executed once and only once for each array.
  A REDIM'D ARRAY error occurs if this line is re-executed. Therefore,
  most programs perform all DIM operations at the very beginning.
    There may be any number of dimensions and 255 subscripts in an array,
  limited only by the amount of RAM memory which is available to hold the
  variables. The array may be mode up of normal numeric variables, as shown
  above, or of strings or integer numbers. If the variables are other than
  normal numeric, use the $ or % signs after the variable name to indicate
  string or integer variables,

  44   BASIC LANGUAGE VOCABULARY

    If an array referenced in a program was never DiMensioned, it is
  automatically dimensioned to 11 elements in each dimension used in the
  first reference.

  EXAMPLES of DIM Statement:

    10 DIM A(100)
    20 DIM Z (5,7), Y(3,4,5)
    30 DIM Y7%(Q)
    40 DIM PH$(1000)
    50 F(4)=9 : REM AUTOMATICALLY PERFORMS DIM F(10)

  EXAMPLE of FOOTBALL SCORE-KEEPING Using DIM:

    10 DIM S(1,5), T$(1)
    20 INPUT"TEAM NAMES"; T$(0), T$(1)
    30 FOR Q=1 TO 5: FOR T=0 TO 1
    40 PRINT T$(T),"SCORE IN QUARTER" Q
    50 INPUT S(T,Q): S(T,0)= S(T,0)+ S(T,Q)
    60 NEXT T,Q
    70 PRINT CHR$(147) "SCOREBOARD"
    80 PRINT "QUARTER"
    90 FOR Q= 1 TO 5
   100 PRINT TAB(Q*2+9) Q;
   110 NEXT: PRINT TAB(15) "TOTAL"
   120 FOR T=0 TO 1: PRINT T$(T);
   130 FOR Q= 1 TO 5
   140 PRINT TAB(Q*2+9) S(T,Q);
   150 NEXT: PRINT TAB(15) S(T,0)
   160 NEXT

  CALCULATING MEMORY USED BY DIM:

    5 bytes for the array name
    2 bytes for each dimension
    2 bytes/element for integer variables
    5 bytes/element for normal numeric variables
    3 bytes/element for string variables
    1 byte for each character in each string element

                                             BASIC LANGUAGE VOCABULARY   45

  END

  TYPE: Statement
  FORMAT: END

    Action: This finishes a program's execution and displays the READY
  message, returning control to the person operating the computer. There
  may be any number of END statements within a program. While it is not
  necessary to include any END statements at all, it is recommended that
  a program does conclude with one, rather than just running out of lines.
    The END statement is similar to the STOP statement. The only difference
  is that STOP causes the computer to display the message BREAK IN LINE XX
  and END just displays READY. Both statements allow the computer to resume
  execution by typing the CONT command.

  EXAMPLES of END Statement:

    10 PRINT"DO YOU REALLY WANT TO RUN THIS PROGRAM"
    20 INPUT A$
    30 IF A$ = "NO" THEN END
    40 REM REST OF PROGRAM . . .
    999 END

  EXP

  TYPE: Function-Numeric
  FORMAT: EXP ( <number> )

    Action: This mathematical function calculates the constant e
  (2.71828183) raised to the power of the number given. A value greater
  than 88.0296919 causes an ?OVERFLOW error to occur.

  EXAMPLES of EXP Function:

    10 PRINT EXP (1)
    20 X = Y*EXP (Z*Q)

  46   BASIC LANGUAGE VOCABULARY

  FN

  TYPE: Function-Numeric
  FORMAT: FN <name> ( <number> )

    Action: This function references the previously DEFined formula spec-
  ified by name. The number is substituted into its place (if any) and the
  formula is calculated. The result will be a numeric value.
    This function can be used in direct mode, as long as the statement
  DEFining it has been executed.
    If an FN is executed before the DEF statement which defines it, an
  UNDEF'D FUNCTION error occurs.

  EXAMPLES of FN (User-Defined) Function:

    PRINT FN A(Q)
    1100 J = FN J(7)+ FN J(9)
    9990 IF FN B7 (1+1)= 6 THEN END

  FOR ... TO ... [STEP ...

  TYPE: Statement
  FORMAT: FOR <variable> = <start> TO <limit> [ STEP <increment> ]

    Action: This is a special BASIC statement that lets you easily use a
  variable as a counter. You must specify certain parameters: the
  floating-point variable name, its starting value, the limit of the count,
  and how much to add during each cycle.

    Here is a simple BASIC program that counts from 1 to 10, PRINTing
  each number and ENDing when complete, and using no FOR statements:

    100 L = 1
    110 PRINT L
    120 L = 1 + 1
    130 IF L <= 10 THEN 110
    140 END

                                             BASIC LANGUAGE VOCABULARY   47

  Using the FOR statement, here is the same program:

    100 FOR L = 1 TO 10
    110 PRINT L
    120 NEXT L
    130 END

    As you can see, the program is shorter and easier to understand using
  the FOR statement.
    When the FOR statement is executed, several operations take place.
  The <start> value is placed in the <variable> being used in the
  counter. In the example above, a I is placed in L.
    When the NEXT statement is reached, the <increment> value is added to
  the <variable>. If a STEP was not included, the <increment> is set to
  + 1. The first time the program above hits line 120, 1 is added to L,
  so the new value of L is 2.
    Now the value in the <variable> is compared to the <limit>. If the
  <limit> has not been reached yet, the program G0es TO the line after
  the original FOR statement. In this case, the value of 2 in L is less
  than the limit of 10, so it GOes TO line 110.
    Eventually, the value of <limit> is exceeded by the <variable>. At
  that time, the loop is concluded and the program continues with the line
  following the NEXT statement. In our example, the value of L reaches
  11, which exceeds the limit of 10, and the program goes on with line
  130.
    When the value of <increment> is positive, the <variable> must
  exceed the <limit>, and when it is negative it must become less than
  the <limit>.

  +---------------------------------------------+
  | NOTE: A loop always executes at least once. |
  +---------------------------------------------+

  EXAMPLES of FOR...TO...STEP...Statement:

    100 FOR L = 100 TO 0 STEP -1
    100 FOR L = PI TO 6* {pi} STEP .01
    100 FOR AA = 3 TO 3

  48   BASIC LANGUAGE VOCABULARY

  FRE

  TYPE: Function
  FORMAT: FRE ( <variable> )

  Action: This function tells you how much RAM is available for your
  program and its variables. If a program tries to use more space than is
  available, the OUT OF MEMORY error results.
    The number in parentheses can have any value, and it is not used in
  the calculation.

  +-----------------------------------------------------------------------+
  | NOTE: If the result of FRE is negative, add 65536 to the FRE number   |
  | get the number of bytes available in memory.                          |
  +-----------------------------------------------------------------------+

  EXAMPLES of FRE Function:

    PRINT FRE(0)
    10 X = (FRE(K)-1000)/7
    950 IF FRE(0)< 100 THEN PRINT "NOT ENOUGH ROOM"

  +-----------------------------------------------------------------------+
  | NOTE: The following always tells you the current available RAM:       |
  | PRINT FRE(0) - (FRE(0) < 0)* 65536                                    |
  +-----------------------------------------------------------------------+

  GET

  TYPE: Statement
  FORMAT: GET <variable list>

    Action: This statement reads each key typed by the user. As the user is
  typing, the characters are stored in the Commodore 64's keyboard buffer.
  Up to 10 characters are stored here, and any keys struck after the 10th
  are lost. Reading one of the characters with the GET statement makes room
  for another character.
    If the GET statement specifies numeric data, and the user types a key
  other than a number, the message ?SYNTAX ERROR appears. To be safe, read
  the keys as strings and convert them to numbers later.

                                             BASIC LANGUAGE VOCABULARY   49

    The GET statement can be used to avoid some of the limitations of the
  INPUT statement. For more on this, see the section on Using the GET
  Statement in the Programming Techniques section.

  EXAMPLES of GET Statement:

    10 GET A$: IF A$ ="" THEN 10: REM LOOPS IN 10 UNTIL ANY KEY HIT
    20 GET A$, B$, C$, D$, E$: REM READS 5 KEYS
    30 GET A, A$

  GET#

  TYPE: I/O Statement
  FORMAT: GET# <file number>, <variable list>

    Action: This statement reads characters one-at-a-time from the device
  or file specified. It works the same as the GET statement, except that
  the data comes from a different place than the keyboard. If no character
  is received, the variable is set to an empty string (equal to "") or to 0
  for numeric variables. Characters used to separate data in files, like
  the comma (,) or <RETURN> key code (ASC code of 13), are received like
  any other character.
    When used with device #3 (TV screen), this statement will read char-
  acters one by one from the screen. Each use of GET# moves the cursor 1
  position to the right. The character at the end of the logical line is
  changed to a CHR$ (13), the <RETURN> key code.

  EXAMPLES of GET# Statement:

    5 GET#1, A$
    10 OPEN 1,3: GET#1, Z7$
    20 GET#1, A, B, C$, D$

  50   BASIC LANGUAGE VOCABULARY

  GOSUB

  TYPE: Statement
  FORMAT: GOSUB <line number>

    Action: This is a specialized form of the GOTO statement, with one
  important difference: GOSUB remembers where it came from. When the
  RETURN statement (different from the <RETURN> key on the keyboard)
  is reached in the program, the program jumps back to the statement
  immediately following the original GOSUB statement.
    The major use of a subroutine (GOSUB really means GO to a SUBroutine)
  is when a small section of program is used by different sections of the
  program. By using subroutines rather than repeating the same lines over
  and over at different places in the program, you can save lots of program
  space. In this way, GOSUB is similar to DEF FN. DEF FN lets you save
  space when using a formula, while GOSUB saves space when using a several-
  line routine. Here is an inefficient program that doesn't use GOSUB:

    100 PRINT "THIS PROGRAM PRINTS"
    110 FOR L = 1 TO 500:NEXT
    120 PRINT "SLOWLY ON THE SCREEN"
    130 FOR L = 1 TO 500:NEXT
    140 PRINT "USING A SIMPLE LOOP"
    150 FOR L = 1 TO 500:NEXT
    160 PRINT "AS A TIME DELAY."
    170 FOR L = 1 TO 500:NEXT

  Here is the same program using GOSUB:

    100 PRINT "THIS PROGRAM PRINTS"
    110 GOSUB 200
    120 PRINT "SLOWLY ON THE SCREEN"
    130 GOSUB 200
    140 PRINT "USING A SIMPLE LOOP"
    150 GOSUB 200
    160 PRINT "AS A TIME DELAY."
    170 GOSUB 200
    180 END
    200 FOR L = 1 TO 500 NEXT
    210 RETURN

                                             BASIC LANGUAGE VOCABULARY   51

    Each time the program executes a GOSUB, the line number and position
  in the program line are saved in a special area called the "stack,"
  which takes up 256 bytes of your memory. This limits the amount of data
  that can be stored in the stack. Therefore, the number of subroutine
  return addresses that can be stored is limited, and care should be taken
  to make sure every GOSUB hits the corresponding RETURN, or else you'll
  run out of memory even though you have plenty of bytes free.

  GOTO

  TYPE: Statement
  FORMAT :GOTO <line number>
	  or GO TO <line number>

    Action: This statement allows the BASIC program to execute lines out
  of numerical order. The word GOTO followed by a number will make the
  program jump to the line with that number. GOTO NOT followed by a number
  equals GOTO 0. It must have the line number after the word GOTO.
    It is possible to create loops with GOTO that will never end. The
  simplest example of this is a line that GOes TO itself, like 10 GOTO 10.
  These loops can be stopped using the <RUN/STOP> key on the keyboard.

  EXAMPLES of GOTO Statement:

    GOTO 100
    10 GO TO 50
    20 GOTO 999

  IF...THEN...

  TYPE: Statement
  FORMAT: IF <expression> THEN <line number>
	  IF <expression> GOTO <line number>
	  IF <expression> THEN <statements>

    Action: This is the statement that gives BASIC most of its "intelli-
  gence," the ability to evaluate conditions and take different actions de-
  pending on the outcome.

  52   BASIC LANGUAGE VOCABULARY

    The word IF is followed by an expression, which can include variables,
  strings, numbers, comparisons, and logical operators. The word THEN
  appears on the same line and is followed by either a line number or one
  or more BASIC statements. When the expression is false, everything after
  the word THEN on that line is ignored, and execution continues with the
  next line number in the program. A true result makes the program either
  branch to the line number after the word THEN or execute whatever other
  BASIC statements are found on that line.

  EXAMPLE of IF...GOTO...Statement:

    100 INPUT "TYPE A NUMBER"; N
    110 IF N <= 0 GOTO 200
    120 PRINT "SQUARE ROOT=" SQR(N)
    130 GOTO 100
    200 PRINT "NUMBER MUST BE >0"
    210 GOTO 100

    This program prints out the square root of any positive number. The IF
  statement here is used to validate the result of the INPUT. When the
  result of N <= 0 is true, the program skips to line 200, and when the
  result is false the next line to be executed is 120. Note that THEN GOTO
  is not needed with IF...THEN, as in line 110 where GOTO 200 actually
  means THEN GOTO 200.

  EXAMPLE OF IF...THEN...Statement:

    100 FOR L = 1 TO 100
    110 IF RND(1) < .5 THEN X=X+1: GOTO 130
    120 Y=Y+1
    130 NEXT L
    140 PRINT "HEADS=" X
    150 PRINT "TAILS= " Y

  The IF in line 110 tests a random number to see if it is less than .5.
  When the result is true, the whole series of statements following the
  word THEN are executed: first X is incremented by 1, then the program
  skips to line 130. When the result is false, the program drops to the
  next statement, line 120.

                                             BASIC LANGUAGE VOCABULARY   53

  INPUT

  TYPE: Statement
  FORMAT: INPUT [ "<prompt>" ; ] <variable list>

    Action: This is a statement that lets the person RUNning the program
  "feed" information into the computer. When executed, this statement
  PRINTs a question mark (?) on the screen, and positions the cursor 1
  space to the right of the question mark. Now the computer waits, cursor
  blinking, for the operator to type in the answer and press the <RETURN>
  key.
    The word INPUT may be followed by any text contained in quote marks
  (""). This text is PRINTed on the screen, followed by the question mark.
    After the text comes a semicolon (;) and the name of one or more
  variables separated by commas. This variable is where the computer
  stores the information that the operator types. The variable can be any
  legal variable name, and you can have several different variable
  names, each for a different input.

  EXAMPLES of INPUT Statement:

    100 INPUT A
    110 INPUT B, C, D
    120 INPUT "PROMPT"; E

    When this program RUNs, the question mark appears to prompt the
  operator that the Commodore 64 is expecting an input for line 100. Any
  number typed in goes into A, for later use in the program. If the answer
  typed was not a number, the ?REDO FROM START message appears, which means
  that a string was received when a number was expected.
    If the operator just hits <RETURN> without typing anything, the vari-
  able's value doesn't change.
    Now the next question mark, for line 110, appears. If we type only
  one number and hit the <RETURN>, Commodore 64 will now display 2
  question marks (??), which means that more input is required. You can

  54   BASIC LANGUAGE VOCABULARY

  just type as many inputs as you need separated by commas, which prevents
  the double question mark from appearing. If you type more data than the
  INPUT statement requested, the ?EXTRA IGNORED message appears, which
  means that the extra items you typed were not put into any variables.
    Line 120 displays the word PROMPT before the question mark appears. The
  semicolon is required between the prompt and any list of variables.
    The INPUT statement can never be used outside a program. The Commodore
  64 needs space for a buffer for the INPUT variables, the same space that
  is used for commands.

  INPUT#

  TYPE: I/O Statement
  FORMAT: INPUT# <file number> , <variable list>

    Action: This is usually the fastest and easiest way to retrieve data
  stored in a file on disk or tape. The data is in the form of whole vari-
  ables of up to 80 characters in length, as opposed to the one-at-a-time
  method of GET#. First, the file must have been OPENed, then INPUT# can
  fill the variables.
    The INPUT# command assumes a variable is finished when it reads a
  RETURN code (CHR$ (13)), a comma (,), semicolon (;), or colon (:).
  Quote marks can be used to enclose these characters when writing if
  they are needed (see PRINT# statement).
    If the variable type used is numeric, and non-numeric characters are
  received, a BAD DATA error results. INPUT# can read strings up to 80
  characters long, beyond which a STRING TOO LONG error results.
    When used with device #3 (the screen), this statement will read an
  entire logical line and move the cursor down to the next line.

  EXAMPLES of INPUT# Statement:

  10 INPUT#1,A
  20 INPUT#2,A$,B$

                                             BASIC LANGUAGE VOCABULARY   55

  INT

  TYPE: Integer Function
  FORMAT: INT (<numeric>)

    Action: Returns the integer value of the expression. If the expression
  is positive, the fractional part is left off. If the expression is
  negative, any fraction causes the next lower integer to be returned.

  EXAMPLES of INT Function:

    120 PRINT INT(99.4343), INT(-12.34)

     99       -13

  LEFT$

  TYPE: String Function
  FORMAT: LEFT$ (<string>, <integer>)

    Action: Returns a string comprised of the leftmost <integer> char-
  acters of the <string>. The integer argument value must be in the range
  0 to 255. If the integer is greater than the length of the string, the
  entire string will be returned. If an <integer> value of zero is used,
  then a null string (of zero length) is returned.

  EXAMPLES of LEFT$ Function:

    10 A$ = "COMMODORE COMPUTERS"
    20 B$ = LEFT$(A$,9): PRINT B$
    RUN

    COMMODORE

  56   BASIC LANGUAGE VOCABULARY

  LEN

  TYPE: Integer Function
  Format: LEN (<string>)

    Action: Returns the number of characters in the string expression.
  Non-printed characters and blanks are counted.

  EXAMPLE of LEN Function:

    CC$ = "COMMODORE COMPUTER": PRINT LEN(CC$)

     18

  LET

  TYPE: Statement
  FORMAT: [LET] <variable> = <expression>

    Action: The LET statement can be used to assign a value to a variable.
  But the word LET is optional and therefore most advanced programmers
  leave LET out because it's always understood and wastes valuable memory.
  The equal sign (=) alone is sufficient when assigning the value of an
  expression to a variable name.

  EXAMPLES of LET Statement:

    10 LET D= 12              (This is the same as D = 12)
    20 LET E$ = "ABC"
    30 F$ = "WORDS"
    40 SUM$= E$ + F$          (SUM$ would equal ABCWORDS)

                                             BASIC LANGUAGE VOCABULARY   57

  LIST

  TYPE: Command
  FORMAT: LIST [[<first-line>]-[<last-line>]]

    Action: The LIST command allows you to look at lines of the BASIC
  program currently in the memory of your Commodore 64. This lets you use
  your computer's powerful screen editor, to edit programs which you've
  LISTed both quickly and easily.
    The LIST system command displays all or part of the program that is
  currently in memory on the default output device. The LIST will normally
  be directed to the screen and the CMD statement can be used to switch
  output to an external device such as a printer or a disk. The LIST com-
  mand can appear in a program, but BASIC always returns to the system
  READY message after a LIST is executed.
    When you bring the program LIST onto the screen, the "scrolling" of
  the display from the bottom of the screen to the top can be slowed by
  holding down the ConTRoL <CTRL> key. LIST is aborted by typing the
  <RUN/STOP> key.
    If no line-numbers are given the entire program is listed. If only the
  first-line number is specified, and followed by a hyphen (-), that line
  and all higher-numbered lines are listed. If only the last line-number is
  specified, and it is preceded by a hyphen, then all lines from the
  beginning of the program through that line are listed. If both numbers
  are specified, the entire range, including the line-numbers LISTed, is
  displayed.

  EXAMPLES of LIST Command:

    LIST            (Lists the program currently in memory.)

    LIST 500        (Lists line 500 only.)

    LIST 150-       (Lists all lines from 150 to the end.)

    LIST -1000      (Lists all lines from the lowest through 1000.)

    LIST 150-1000   (Lists lines 150 through 1000, inclusive.)

    10 PRINT "THIS  IS LINE 10"
    20 LIST                             (LIST used in Program Mode)
    30 PRINT "THIS  IS LINE 30"

  58   BASIC LANGUAGE VOCABULARY

  LOAD

  TYPE: Command

  FORMAT: LOAD["<file-name>"][,<device>][,<address>]

    Action: The LOAD statement reads the contents of a program file from
  tape or disk into memory. That way you can use the information LOADed
  or change the information in some way. The device number is optional,
  but when it is left out the computer will automatically default to 1, the
  cassette unit. The disk unit is normally device number 8. The LOAD closes
  all open files and, if it is used in direct mode, it performs a CLR
  (clear) before reading the program. If LOAD is executed from within a
  program, the program is RUN. This means that you can use LOAD to "chain"
  several programs together. None of the variables are cleared during a
  chain operation.
    If you are using file-name pattern matching, the first file which
  matches the pattern is loaded. The asterisk in quotes by itself ("*")
  causes the first file-name in the disk directory to be loaded. if the
  filename used does not exist or if it is not a program file, the BASIC
  error message ?FILE NOT FOUND occurs.
    When LOADing programs from tape, the <file-name> can be left out, and
  the next program file on the tape will be read. The Commodore 64 will
  blank the screen to the border color after the PLAY key is pressed. When
  the program is found, the screen clears to the background color and the
  "FOUND" message is displayed. When the <C=> key, <CTRL> key, <ARROW LEFT>
  key, or <SPACE BAR> is pressed, the file will be loaded. Programs will
  LOAD starting at memory location 2048 unless a secondary <address> of 1
  is used. If you use the secondary address of 1 this will cause the
  program to LOAD to the memory location from which it was saved.

                                             BASIC LANGUAGE VOCABULARY   59

  EXAMPLES of LOAD Command:

    LOAD                         (Reads the next program on tape)

    LOAD A$                      (Uses the name in A$ to search)

    LOAD"*",8                    (LOADs first program from disk)

    LOAD"",1,1                   (Looks for the first program on
                                  tape, and LOADs it into the same
                                  part of memory that it came from)

    LOAD"STAR TREK"              (LOAD a file from tape)
    PRESS PLAY ON TAPE
    FOUND STAR TREK
    LOADING
    READY.

    LOAD"FUN",8                  (LOAD a file from disk)
    SEARCHING FOR FUN
    LOADING
    READY.

    LOAD"GAME ONE",8,1           (LOAD a file to the specific
    SEARCHING FOR GAME ONE        memory location from which the
    LOADING                       program was saved on the disk)
    READY.

  60   BASIC LANGUAGE VOCABULARY

  LOG

  TYPE: Floating-Point Function
  FORMAT: LOG(<numeric>)

    Action: Returns the natural logarithm (log to the base of e) of the
  argument. If the value of the argument is zero or negative the BASIC
  error message ?ILLEGAL QUANTITY will occur.

  EXAMPLES of LOG Function:

    25 PRINT LOG(45/7)
     1.86075234

    10 NUM=LOG(ARG)/LOG(10)  (Calculates the LOG of ARG to the base 10)

  MID$

  TYPE: String Function
  FORMAT: MID$(<string>,<numeric-1>[,<numeric-2>])

    Action: The MID$ function returns a sub-string which is taken from
  within a larger <string> argument. The starting position of the sub-
  string is defined by the <numeric-1> argument and the length of the
  sub-string by the <numeric-2> argument. Both of the numeric arguments
  can have values ranging from 0 to 255.
    If the <numeric-1> value is greater than the length of the <string>,
  or if the <numeric-2> value is zero, then MID$ gives a null string value.
  If the <numeric-2> argument is left out, then the computer will assume
  that a length of the rest of the string is to be used. And if the source
  string has fewer characters than <numeric-2>, from the starting position
  to the end of the string argument, then the whole rest of the string is
  used.

  EXAMPLE of MID$ Function:

    10 A$="GOOD"
    20 B$="MORNING EVENING AFTERNOON"
    30 PRINT A$ + MID$(B$,8,8)

    GOOD EVENING

                                             BASIC LANGUAGE VOCABULARY   61

  NEW

  TYPE: Command
  FORMAT: NEW

    Action: The NEW command is used to delete the program currently in
  memory and clear all variables. Before typing in a new program, NEW
  should be used in direct mode to clear memory. NEW can also be used in
  a program, but you should be aware of the fact that it will erase
  everything that has gone before and is still in the computer's memory.
  This can be particularly troublesome when you're trying to debug your
  program.

  +-----------------------------------------------------------------------+
  | BE CAREFUL: Not clearing out an old program before typing a new one   |
  | can result in a confusing mix of the two programs.                    |
  +-----------------------------------------------------------------------+

  EXAMPLES of NEW Command:

    NEW             (Clears the program and all variables)
    10 NEW          (Performs a NEW operation and STOPs the program.)

  NEXT

  TYPE: Statement
  FORMAT: NEXT[<counter>][,<counter>]...

    Action: The NEXT statement is used with FOR to establish the end of a
  FOR...NEXT loop. The NEXT need not be physically the last statement
  in the loop, but it is always the last statement executed in a loop. The
  <counter> is the loop index's variable name used with FOR to start the
  loop. A single NEXT can stop several nested loops when it is followed by
  each FOR's <counter> variable name(s). To do this each name must appear
  in the order of inner-most nested loop first, to outer-most nested loop
  last. When using a single NEXT to increment and stop several variable
  names, each variable name must be separated by commas. Loops can be
  nested to 9 levels. If the counter variable(s) are omitted, the counter
  associated with the FOR of the current level (of the nested loops) is
  incremented.

  62   BASIC LANGUAGE VOCABULARY

    When the NEXT is reached, the counter value is incremented by 1 or by
  an optional STEP value. It is then tested against an end-value to see if
  it's time to stop the loop. A loop will be stopped when a NEXT is found
  which has its counter value greater than the end-value.

  EXAMPLES of NEXT Statement:

    10 FOR J=1 TO 5: FOR K=10 TO 20: FOR N=5 TO -5 STEP - 1

    20 NEXT N,K,J            (Stopping Nested Loops)

    10 FOR L=1 TO 100
    20 FOR M=1 TO 10
    30 NEXT M
    400 NEXT L               (Note how the loops do NOT cross each other)

    10 FOR A=1 TO 10
    20 FOR B=1 TO 20
    30 NEXT
    40 NEXT                  (Notice that no variable names are needed)

  NOT

  TYPE: Logical Operator
  FORMAT: NOT <expression>

    Action: The NOT logical operator "complements" the value of each bit
  in its single operand, producing an integer "twos-complement" result. In
  other words, the NOT is really saying, "if it isn't. When working with a
  floating-point number, the operands are converted to integers and any
  fractions are lost. The NOT operator can also be used in a comparison to
  reverse the true/false value which was the result of a relationship test
  and therefore it will reverse the meaning of the comparison. In the first
  example below, if the "twos-complement" of "AA" is equal to "BB" and if
  "BB" is NOT equal to "CC" then the expression is true.

                                             BASIC LANGUAGE VOCABULARY   63

  EXAMPLES of NOT Operator:

    10 IF NOT AA = BB AND NOT(BB = CC) THEN...

    NN% = NOT 96: PRINT NN%
    -97

  +-----------------------------------------------------------------------+
  | NOTE: TO find the value of NOT use the expression X=(-(X+1)). (The    |
  | two's complement of any integer is the bit complement plus one.)      |
  +-----------------------------------------------------------------------+

  ON

  TYPE: Statement
  FORMAT: ON <variable> GOTO / GOSUB <line-number>[,<line-number>]...

    Action: The ON statement is used to GOTO one of several given line-
  numbers, depending upon the value of a variable. The value of the
  variables can range from zero through the number of lines given. if the
  value is a non-integer, the fractional portion is left off. For example,
  if the variable value is 3, ON will GOTO the third line-number in the
  list.
    If the value of the variable is negative, the BASIC error message
  ?ILLEGAL QUANTITY occurs. If the number is zero, or greater than the
  number of items in the list, the program just "ignores" the statement and
  continues with the statement following the ON statement.
    ON is really an underused variant of the IF...THEN...statement. Instead
  of using a whole lot of IF statements each of which sends the program to
  1 specific line, 1 ON statement can replace a list of IF statements. When
  you look at the first example you should notice that the 1 ON statement
  replaces 4 IF...THEN... statements.

    EXAMPLES of ON Statement:

  ON -(A=7)-2*(A=3)-3*(A<3)-4*(A>7)GOTO 400,900,1000,100
  ON X GOTO 100,130,180,220
  ON X+3 GOSUB 9000,20,9000
  100 ON NUM GOTO 150,300,320,390
  500 ON SUM/2 + 1 GOSUB 50,80,20

  64   BASIC LANGUAGE VOCABULARY

  OPEN

  TYPE: I/O Statement
  FORMAT: OPEN <file-num>,[<device>][,<address>]
           [,"<File-name> [,<type>] [,<mode>]"]

    Action: This statement OPENs a channel for input and/or output to a
  peripheral device. However, you may NOT need all those parts for every
  OPEN statement. Some OPEN statements require only 2 codes:

    1) LOGICAL FILE NUMBER
    2) DEVICE NUMBER

    The <file-num> is the logical file number, which relates the OPEN,
  CLOSE, CMD, GET#, INPUT#, and PRINT# statements to each other and
  associates them with the file-name and the piece of equipment being used.
  The logical file number can range from 1 to 255 and you can assign it any
  number you want in that range.

  +-----------------------------------------------------------------------+
  | NOTE: File numbers over 128 were really designed for other uses so    |
  | it's good practice to use only numbers below 127 for file numbers.    |
  +-----------------------------------------------------------------------+

    Each peripheral device (printer, disk drive, cassette) in the system
  has its own number which it answers to. The <device> number is used with
  OPEN to specify on which device the data file exists. Peripherals like
  cassette decks, disk drives or printers also answer to several secondary
  addresses. Think of these as codes which tell each device what operation
  to perform. The device logical file number is used with every GET#,
  INPUT#, and PRINT#.
    If the <device> number is left out the computer will automatically
  assume that you want your information to be sent to and received from
  the Datassette(TM), which is device number 1. The file-name can also be
  left out, but later on in your program, you can NOT call the file by name
  if you have not already given it one. When you are storing files on cas-
  sette tape, the computer will assume that the secondary <address> is
  zero (0) if you omit the secondary address (a READ operation).

                                             BASIC LANGUAGE VOCABULARY   65

    A secondary address value of one (1) OPENs cassette tape files for
  writing. A secondary address value of two (2) causes an end-of-tape
  marker to be written when the file is later closed. The end-of-tape
  marker prevents accidentally reading past the end of data which results
  in the BASIC error message ?DEVICE NOT PRESENT.
    For disk files, the secondary addresses 2 thru 14 are available for
  data-files, but other numbers have special meanings in DOS commands.
  You must use a secondary address when using your disk drive(s). (See
  your disk drive manual for DOS command details.)
    The <file-name> is a string of 1-16 characters and is optional for
  cassette or printer files. If the file <type> is left out the type of
  file will automatically default to the Program file unless the <mode> is
  given.
  Sequential files are OPENed for reading <mode>=R unless you specify that
  files should be OPENed for writing <mode> =W is specified. A file <type>
  can be used to OPEN an existing Relative file. Use REL for <type> with
  Relative files. Relative and Sequential files are for disk only.
    If you try to access a file before it is OPENed the BASIC error message
  ?FILE NOT OPEN will occur. If you try to OPEN a file for reading which
  does not exist the BASIC error message ?FILE NOT FOUND will occur. If
  a file is OPENed to disk for writing and the file-name already exists,
  the DOS error message FILE EXISTS occurs. There is no check of this type
  available for tape files, so be sure that the tape is properly positioned
  or you might accidentally write over some data that had previously been
  SAVED. If a file is OPENed that is already OPEN, the BASIC error message
  FILE OPEN occurs. (See Printer Manual for further details.)

  66   BASIC LANGUAGE VOCABULARY

  EXAMPLES of OPEN Statements:

    10 OPEN 2,8,4,"DISK-OUTPUT,SEQ,W"  (Opens sequential file on disk)

    10 OPEN 1,1,2,"TAPE-WRITE"         (Write End-of-File on Close)

    10 OPEN 50,0                       (Keyboard input)

    10 OPEN 12,3                       (Screen output)

    10 OPEN 130,4                      (Printer output)

    10 OPEN 1,1,0,"NAME"               (Read from cassette)

    10 OPEN 1,1,1,"NAME"               (Write to cassette)

    10 OPEN 1,2,0,CHR$(10)             (open channel to RS-232 device)

    10 OPEN 1,4,0,"STRING"             (Send upper case/graphics to
                                        the printer)

    10 OPEN 1,4,7,"STRING"             (Send upper/lower case to
                                        printer)

    10 OPEN 1,5,7,"STRING"             (Send upper/lower case to
                                        printer with device # 5)

    10 OPEN 1,8,15,"COMMAND"           (Send a command to disk)

                                             BASIC LANGUAGE VOCABULARY   67

  OR

  TYPE: Logical Operator
  FORMAT: <operand> OR <operand>

  Action: Just as the relational operators can be used to make decisions
  regarding program flow, logical operators can connect two or more re-
  lations and return a true or false value which can then be used in a
  decision. When used in calculations, the logical OR gives you a bit
  result of I if the corresponding bit of either or both operands is 1.
  This will produce an integer as a result depending on the values of the
  operands. When used in comparisons the logical OR operator is also used
  to link two expressions into a single compound expression. If either of
  the expressions are true, the combined expression value is true (-1). In
  the first example below if AA is equal to BB OR if XX is 20, the
  expression is true.
    Logical operators work by converting their operands to 16-bit, signed,
  two's complement integers in the range of -32768 to +32767. If the
  operands are not in the range an error message results. Each bit of the
  result is determined by the corresponding bits in the two operands.

  EXAMPLES of OR Operator:

    100 IF (AA=BB) OR (XX=20) THEN...

    230 KK%=64 OR 32: PRINT KK%         (You typed this with a bit
                                         value of 1000000 for 64
                                         and 100000 for 32)

    96                                  (The computer responded with
                                         bit value 1100000.
                                         1100000=96.)

  68   BASIC LANGUAGE VOCABULARY

  PEEK

  TYPE: Integer Function
  FORMAT: PEEK(<numeric>)

    Action: Returns an integer in the range of 0 to 255, which is read
  from a memory location. The <numeric> expression is a memory location
  which must be in the range of 0 to 65535. If it isn't then the BASIC
  error message ?ILLEGAL QUANTITY occurs.

  EXAMPLES of PEEK Function:

    10 PRINT PEEK(53280) AND 15   (Returns value of screen border color)

    5 A%=PEEK(45)+PEEK(46)*256    (Returns address of BASIC variable table)

  POKE

  TYPE: Statement
  FORMAT: POKE <location>,<value>

  Action: The POKE statement is used to write a one-byte (8-bits) binary
  value into a given memory location or input/output register. The
  <location> is an arithmetic expression which must equal a value in the
  range of 0 to 65535. The <value> is an expression which can be reduced to
  an integer value of 0 to 255. If either value is out of its respective
  range, the BASIC error message ?ILLEGAL QUANTITY occurs.
    The POKE statement and PEEK statement (which is a built-in function
  that looks at a memory location) are useful for data storage, controlling
  graphics displays or sound generation, loading assembly language sub-
  routines, and passing arguments and results to and from assembly language
  subroutines. In addition, Operating System parameters can be examined
  using PEEK statements or changed and manipulated using POKE statements.
  A complete memory map of useful locations is given in Appendix G.

                                             BASIC LANGUAGE VOCABULARY   69

  EXAMPLES of POKE Statement:

    POKE 1024, 1         (Puts an "A" at position 1 on the screen)
    POKE 2040, PTR       (Updates Sprite #0 data pointer)
    10 POKE RED,32
    20 POKE 36879,8
    2050 POKE A,B

  POS

  TYPE: Integer Function
  FORMAT: POS (<dummy>)

    Action: Tells you the current cursor position which, of course, is in
  the range of 0 (leftmost character) though position 79 on an 80-character
  logical screen line. Since the Commodore 64 has a 40-column screen, any
  position from 40 through 79 will refer to the second screen line. The
  dummy argument is ignored.

  EXAMPLE of POS Function:

    1000 IF POS(0)>38 THEN PRINT CHR$(13)

  PRINT

  TYPE: Statement
  FORMAT: PRINT [<variable>][<,/;><variable>]...

    Action: The PRINT statement is normally used to write data items to
  the screen. However, the CMD statement may be used to re-direct that
  output to any other device in the system. The <variable(s)> in the
  output-list are expressions of any type. If no output-list is present, a
  blank line is printed. The position of each printed item is determined by
  the punctuation used to separate items in the output-list.
    The punctuation characters that you can use are blanks, commas, or
  semicolons. The 80-character logical screen line is divided into 8 print
  zones of 10 spaces each. In the list of expressions, a comma causes the
  next value to be printed at the beginning of the next zone. A semicolon
  causes the next value to be printed immediately following the previous
  value. However, there are two exceptions to this rule:

  70   BASIC LANGUAGE VOCABULARY

    1) Numeric items are followed by an added space.
    2) Positive numbers have a space preceding them.

    When you use blanks or no punctuation between string constants or
  variable names it has the same effect as a semicolon. However, blanks
  between a string and a numeric item or between two numeric items will
  stop output without printing the second item.
    If a comma or a semicolon is at the end of the output-list, the next
  PRINT statement begins printing on the same line, and spaced accord-
  ingly. If no punctuation finishes the list, a carriage-return and a line-
  feed are printed at the end of the data. The next PRINT statement will
  begin on the next line. If your output is directed to the screen and the
  data printed is longer than 40 columns, the output is continued on the
  next screen line.
    There is no statement in BASIC with more variety than the PRINT
  statement. There are so many symbols, functions, and parameters
  associated with this statement that it might almost be considered as a
  language of its own within BASIC; a language specially designed for
  writing on the screen.

  EXAMPLES of PRINT Statement:

  1)
     5 X = 5
    10 PRINT -5*X,X-5,X+5,X^5

    -25     0     10     3125

  2)
     5 X=9
    10 PRINT X;"SQUARED IS";X*X;"AND";
    20 PRINT X "CUBED IS" X^3

    9 SQUARED IS 81 AND 9 CUBED IS 729

  3)
     90 AA$="ALPHA":BB$="BAKER":CC$="CHARLIE":DD$="DOG":EE$="ECHO"
    100 PRINT AA$BB$;CC$ DD$,EE$

    ALPHABAKERCHARLIEDOG     ECHO

                                             BASIC LANGUAGE VOCABULARY   71

  Quote Mode

    Once the quote mark <SHIFT+2> is typed, the cursor controls stop
  operating and start displaying reversed characters which actually stand
  for the cursor control you are hitting. This allows you to program these
  cursor controls, because once the text inside the quotes is PRINTed they
  perform their functions. The <INST/DEL> key is the only cursor control
  not affected by "quote mode."

  1. Cursor Movement

    The cursor controls which can be "programmed" in quote mode are:

          KEY                             APPEARS AS

        <CLR/HOME>
        <SHIFT+CLR/HOME>
        <CRSR UP/DOWN>
        <SHIFT+CRSR UP/DOWN>
        <CRSR LEFT/RIGHT>
        <SHIFT+CRSR LEFT/RIGHT>

    If you wanted the word HELLO to PRINT diagonally from the upper left
  corner of the screen, you would type:

  PRINT"<HOME>H<DOWN>E<DOWN>L<DOWN>L<DOWN>O"

  2. Reverse Characters

    Holding down the <CTRL> key and hitting <9> will cause <R> to appear
  inside the quotes. This will make all characters start printing in
  reverse video (like a negative of a picture). To end the reverse printing
  hit <CTRL+0>, or else PRINT a <RETURN> (CHR$(13)). (Just ending the PRINT
  statement without a semicolon or comma will take care of this.)

  3.Color Controls

    Holding down the <CTRL> key or <C=> key with any of the 8 color keys
  will make a special reversed character appear in the quotes. When the
  character is PRINTed, then the color change will occur.

  72   BASIC LANGUAGE VOCABULARY

      KEY           COLOR                APPEARS AS

   <CTRL+1>         Black
   <CTRL+2>         White
   <CTRL+3>         Red
   <CTRL+4>         Cyan
   <CTRL+5>         Purple
   <CTRL+6>         Green
   <CTRL+7>         Blue
   <CTRL+8>         Yellow
   <C=+1>           Orange
   <C=+2>           Brown
   <C=+3>           Light Red
   <C=+4>           Grey 1
   <C=+5>           Grey 2
   <C=+6>           Light Green
   <C=+7>           Light Blue
   <C=+8>           Grey 3

    If you wanted to PRINT the word HELLO in cyan and the word THERE
  in white, type:

    PRINT "<CTRL+4>HELLO <CTRL+2>THERE"

  4. Insert Mode

    The spaces created by using the <INST/DEL> key have some of the same
  characteristics as quote mode. The cursor controls and color controls
  show up as reversed characters. The only difference is in the <INST> and
  <DEL>, which performs its normal function even in quote mode, now

                                             BASIC LANGUAGE VOCABULARY   73

  creates the <T>. And <INST>, which created a special character in quote
  mode, inserts spaces normally.
    Because of this, it is possible to create a PRINT statement containing
  DELetes, which cannot be PRINTed in quote mode. Here is an example
  of how this is done:

    10 PRINT"HELLO"<DEL><INST><INST><DEL><DEL>P"

    When the above line is RUN, the word displayed will be HELP, because
  the last two letters are deleted and the P is put in their place.

  +-----------------------------------------------------------------------+
  | WARNING: The DELetes will work when LISTing as well as PRINTing, so   |
  | editing a line with these characters will be difficult.               |
  +-----------------------------------------------------------------------+

    The "insert mode" condition is ended when the <RETURN> (or
  <SHIFT+RETURN>) key is hit, or when as many characters have been typed as
  spaces were inserted.

  5. Other Special Characters

    There are some other characters that can be PRINTed for special
  functions, although they are not easily available from the keyboard. In
  order to get these into quotes, you must leave empty spaces for them in
  the line, hit <RETURN> or <SHIFT+RETURN>, and go back to the spaces with
  the cursor controls. Now you must hit <RVS ON>, to start typing reversed
  characters, and type the keys shown below:

          Function                    Type               Appears As

    <SHIFT+RETURN>                    <SHIFT+M>
    switch to lower case              <N>
    switch to upper case              <SHIFT+N>
    disable case-switching keys       <H>
    enable case-switching keys        <I>

  74   BASIC LANGUAGE VOCABULARY

    The <SHIFT+RETURN> will work in the LISTing as well as PRINTing, so
  editing will be almost impossible if this character is used. The LISTing
  will also look very strange.

  PRINT#

  TYPE: I/O Statement
  FORMAT: PRINT#<file-number>[<variable>][<,/;><variable>]...

    Actions: The PRINT# statement is used to write data items to a logical
  file. It must use the same number used to OPEN the file. Output goes to
  the device-number used in the OPEN statement. The <variable> expressions
  in the output-list can be of any type. The punctuation characters between
  items are the same as with the PRINT statement and they can be used in
  the same ways. The effects of punctuation are different in two
  significant respects.
    When PRINT# is used with tape files, the comma, instead of spacing
  by print zones, has the same effect as a semicolon. Therefore, whether
  blanks, commas, semicolons or no punctuation characters are used between
  data items, the effect on spacing is the same. The data items are written
  as a continuous stream of characters. Numeric items are followed by a
  space and, if positive, are preceded by a space.
    If no punctuation finishes the list, a carriage-return and a line-feed
  are written at the end of the data. If a comma or semicolon terminates
  the output-list, the carriage-return and line-feed are suppressed. Re-
  gardless of the punctuation, the next PRINT# statement begins output in
  the next available character position. The line-feed will act as a stop
  when using the INPUT# statement, leaving an empty variable when the next
  INPUT# is executed. The line-feed can be suppressed or compensated for as
  shown in the examples below.
    The easiest way to write more than one variable to a file on tape or
  disk is to set a string variable to CHR$(13), and use that string in be-
  tween all the other variables when writing the file.

                                             BASIC LANGUAGE VOCABULARY   75

  EXAMPLES of PRINT# Statement:

  1)

    10 OPEN 1,1,1,"TAPE FILE"
    20 R$=CHR$(13)                      (By Changing the CHR$(13) to
    30 PRINT#1,1;R$;2;R$;3;R$;4;R$;5     CHR$(44) you put a "," between
    40 PRINT#1,6                         each variable. CHR$(59) would
    50 PRINT# 1,7                        put a ";" between each variable.)

  2)

    10 CO$=CHR$(44):CR$=CHR$(13)
    20 PRINT#1,"AAA"CO$"BBB",           AAA,BBB     CCCDDDEEE
       "CCC";"DDD";"EEE"CR$             (carriage return)
       "FFF"CR$;                        FFF(carriage return)
    30 INPUT#1,A$,BCDE$,F$

  3)

     5 CR$=CHR$(13)
    10 PRINT#2,"AAA";CR$;"BBB"          (10 blanks) AAA
    20 PRINT#2,"CCC";                   BBB
                                        (10 blanks)CCC
    30 INPUT#2,A$,B$,DUMMY$,C$

  READ

  TYPE: Statement
  FORMAT: READ <variable>[,<variable>]...

    Action: The READ statement is used to fill variable names from con-
  stants in DATA statements. The data actually read must agree with the
  variable types specified or the BASIC error message ?SYNTAX ERROR will
  result.(*) Variables in the DATA input-list must be separated by commas.
    A single READ statement can access one or more DATA statements,
  which will be accessed in order (see DATA), or several READ statements
  can access the same DATA statement. If more READ statements are executed
  than the number of elements in DATA statements(s) in the program, the

  76   BASIC LANGUAGE VOCABULARY

  BASIC error message ?OUT OF DATA is printed. If the number of variables
  specified is fewer than the number of elements in the DATA statement(s),
  subsequent READ statements will continue reading at the next data
  element. (See RESTORE.)

  +-----------------------------------------------------------------------+
  | *NOTE: The ?SYNTAX ERROR will appear with the line number from the    |
  | DATA statement, NOT the READ statement.                               |
  +-----------------------------------------------------------------------+

  EXAMPLES of READ Statement:

    110 READ A,B,C$
    120 DATA 1,2,HELLO

    100 FOR X=1 TO 10: READ A(X):NEXT

    200 DATA 3.08, 5.19, 3.12, 3.98, 4.24
    210 DATA 5.08, 5.55, 4.00, 3.16, 3.37

    (Fills array items (line 1) in order of constants shown (line 5))

    1 READ CITY$,STATE$,ZIP
    5 DATA DENVER,COLORADO, 80211

  REM

  TYPE: Statement
  FORMAT: REM [<remark>]

    Action:The REM statement makes your programs more easily understood
  when LISTed. It's a reminder to yourself to tell you what you had in
  mind when you were writing each section of the program. For instance,
  you might want to remember what a variable is used for, or some other
  useful information. The REMark can be any text, word, or character
  including the colon (:) or BASIC keywords.
    The REM statement and anything following it on the same line-number
  are ignored by BASIC, but REMarks are printed exactly as entered when
  the program is listed. A REM statement can be referred to by a GOTO or
  GOSUB statement, and the execution of the program will continue with
  the next higher program line having executable statements.

                                             BASIC LANGUAGE VOCABULARY   77

  EXAMPLES of REM Statement:

    10 REM CALCULATE AVERAGE VELOCITY
    20 FOR X= 1 TO 20 :REM LOOP FOR TWENTY VALUES
    30 SUM=SUM + VEL(X): NEXT
    40 AVG=SUM/20

  RESTORE

  TYPE: Statement
  FORMAT: RESTORE

    Action: BASIC maintains an internal pointer to the next DATA constant
  to be READ. This pointer can be reset to the first DATA constant in a
  program using the RESTORE statement. The RESTORE statement can be
  used anywhere in the program to begin re-READing DATA.

  EXAMPLES of RESTORE Statement:

    100 FOR X=1 TO 10: READ A(X): NEXT
    200 RESTORE
    300 FOR Y=1 TO 10: READ B(Y): NEXT

    4000 DATA 3.08, 5.19, 3.12, 3.98, 4.24
    4100 DATA 5.08, 5.55, 4.00, 3.16, 3.37

    (Fills the two arrays with identical data)

    10 DATA 1,2,3,4
    20 DATA 5,6,7,8
    30 FOR L= 1 TO 8
    40 READ A: PRINT A
    50 NEXT
    60 RESTORE
    70 FOR L= 1 TO 8
    80 READ A: PRINT A
    90 NEXT

  78   BASIC LANGUAGE VOCABULARY

  RETURN

  TYPE: Statement
  FORMAT: RETURN

    Action: The RETURN statement is used to exit from a subroutine called
  for by a GOSUB statement. RETURN restarts the rest of your program at
  the next executable statement following the GOSUB. If you are nesting
  subroutines, each GOSUB must be paired with at least one RETURN
  statement. A subroutine can contain any number of RETURN statements,
  but the first one encountered will exit the subroutine.

  EXAMPLE of RETURN Statement:

    10 PRINT"THIS IS THE PROGRAM"
    20 GOSUB 1000
    30 PRINT"PROGRAM CONTINUES"
    40 GOSUB 1000
    50 PRINT"MORE PROGRAM"
    60 END
    1000 PRINT"THIS IS THE GOSUB":RETURN

  RIGHT$

  TYPE: String Function
  FORMAT: RIGHT$ (<string>,<numeric>)

    Action: The RIGHT$ function returns a sub-string taken from the right-
  most end of the <string> argument. The length of the sub-string is
  defined by the <numeric> argument which can be any integer in the range
  of 0 to 255. If the value of the numeric expression is zero, then a null
  string ("") is returned. If the value you give in the <numeric> argument
  is greater than the length of the <string> then the entire string is
  returned.

  EXAMPLE of RIGHT$ Function:

    10 MSG$="COMMODORE COMPUTERS"
    20 PRINT RIGHT$(MSG$,9)
    RUN

    COMPUTERS
                                             BASIC LANGUAGE VOCABULARY   79

  RND

  TYPE: Floating-Point Function
  FORMAT: RND (<numeric>)

    Action: RND creates a floating-point random from 0.0 to 1.0. The
  computer generates a sequence of random numbers by performing cal-
  culations on a starting number, which in computer jargon is called a
  seed. The RND function is seeded on system power-up. The <numeric>
  argument is a dummy, except for its sign (positive, zero, or negative).
    If the <numeric> argument is positive, the same "pseudorandom"
  sequence of numbers is returned, starting from a given seed value. Dif-
  ferent number sequences will result from different seeds, but any se-
  quence is repeatable by starting from the same seed number. Having a
  known sequence of "random" numbers is useful in testing programs.
    If you choose a <numeric> argument of zero, then RND generates a
  number directly from a free-running hardware clock (the system "jiffy
  clock"). Negative arguments cause the RND function to be re-seeded
  with each function call.

  EXAMPLES of RND Function:

    220 PRINT INT(RND(0)*50)               (Return random integers 0-49)

    100 X=INT(RND(1)*6)+INT(RND(1)*6)+2    (Simulates 2 dice)

    100 X=INT(RND(1)*1000)+1               (Random integers from 1-1000)

    100 X=INT(RND(1)*150)+100              (Random numbers from 100-249)

    100 X=RND(1)*(U-L)+L                   (Random numbers between
                                            upper (U) and lower (L) limits)

  80   BASIC LANGUAGE VOCABULARY

  RUN

  TYPE: Command
  FORMAT: RUN [<line-number>]

    Action: The system command RUN is used to start the program currently
  in memory. The RUN command causes an implied CLR operation to be
  performed before starting the program. You can avoid the CLeaRing
  operation by using CONT or GOTO to restart a program instead of RUN. If
  a <line-number> is specified, your program will start on that line.
  Otherwise, the RUN command starts at first line of the program. The RUN
  command can also be used within a program. If the <line-number> you
  specify doesn't exist, the BASIC error message UNDEF'D STATEMENT occurs.
    A RUNning program stops and BASIC returns to direct mode when an END or
  STOP statement is reached, when the last line of the program is finished,
  or when a BASIC error occurs during execution.

  EXAMPLES of RUN Command:

    RUN           (Starts at first line of program)

    RUN 500       (Starts at line-number 500)
    RUN X         (Starts at line X, or UNDEF'D STATEMENT ERROR
                   if there is no line X)

  SAVE

  TYPE: Command
  FORMAT: SAVE ["<file-name>"][,<device-number>][,<address>]

    Action: The SAVE command is used to store the program that is cur-
  rently in memory onto a tape or diskette file. The program being SAVED
  is only affected by the command while the SAVE is happening. The program
  remains in the current computer memory even after the SAVE operation is
  completed until you put something else there by using another command.
  The file type will be "prg" (program). If the <device-number> is left
  out, then the C64 will automatically assume that you want the program
  saved on cassette, device number 1. If the <device-number> is an <8>,
  then the program is written onto disk. The SAVE statement can be used

                                             BASIC LANGUAGE VOCABULARY   81

  be used in your programs and execution will continue with the next
  statement after the SAVE is completed.
    Programs on tape are automatically stored twice, so that your Com-
  modore 64 can check for errors when LOADing the program back in. When
  saving programs to tape, the <file-name> and secondary <address> are
  optional. But following a SAVE with a program name in quotes ("") or
  by a string variable (---$) helps your Commodore 64 find each program
  more easily. If the file-name is left out it can NOT be LOADed by name
  later on.
    A secondary address of I will tell the KERNAL to LOAD the tape at a
  later time, with the program currently in memory instead of the normal
  2048 location. A secondary address of 2 will cause an end-of-tape marker
  to follow the program. A secondary address of 3 combines both functions.
    When saving programs onto a disk, the <file-name> must be present.

  EXAMPLES of SAVE Command.

    SAVE               (Write to tape without a name)

    SAVE"ALPHA",1      (Store on tape as file-name "alpha")

    SAVE"ALPHA",1,2    (Store "alpha" with end-of-tape marker)

    SAVE"FUN.DISK",8   (SAVES on disk (device 8 is the disk))

    SAVE A$            (Store on tape with the name A$)

    10 SAVE"HI"        (SAVEs program and then move to next program line)

    SAVE"ME",1,3       (Stores at same memory location and puts an
                        end-of-tope marker on)

  82   BASIC LANGUAGE VOCABULARY

  SGN

  TYPE: Integer Function
  FORMAT: SGN (<numeric>)

    Action: SGN gives you an integer value depending upon the sign of the
  <numeric> argument. If the argument is positive the result is 1, if zero
  the result is also 0, if negative the result is -1.

  EXAMPLE of SGN Function:

    90 ON SGN(DV)+2 GOTO 100, 200, 300
    (jump to 100 if DV=negative, 200 if DV=0, 300 if DV=positive)

  SIN

  TYPE: Floating-Point Function
  FORMAT: SIN (<numeric>)

    Action: SIN gives you the sine of the <numeric> argument, in radians.
  The value of COS(X) is equal to SIN(x+3.14159265/2).

  EXAMPLE of SIN Function:

    235 AA=SIN(1.5):PRINT AA
     .997494987

  SPC

  TYPE: String Function
  FORMAT: SPC (<numeric>)

    Action: The SPC function is used to control the formatting of data, as
  either an output to the screen or into a logical file. The number of
  SPaCes given by the <numeric> argument are printed, starting at the first
  available position. For screen or tape files the value of the argument
  is in the range of 0 to 255 and for disk files up to 254. For printer
  files, an automatic carriage-return and line-feed will be performed by
  the printer if a SPaCe is printed in the last character position of a
  line. No SPaCes are printed on the following line.

                                             BASIC LANGUAGE VOCABULARY   83

  EXAMPLE of SPC Function:

    10 PRINT"RIGHT "; "HERE &";
    20 PRINT SPC(5)"OVER" SPC(14)"THERE"
    RUN

    RIGHT HERE &     OVER              THERE

  SQR

  TYPE: Floating-Point Function
  FORMAT: SQR (<numeric>)

    Action: SQR gives you the value of the SQuare Root of the <numeric>
  argument. The value of the argument must not be negative, or the BASIC
  error message ?ILLEGAL QUANTITY will happen.

  EXAMPLE of SQR Function:

    FOR J = 2 TO 5: PRINT J*S, SQR(J*5): NEXT

    10   3.16227766
    15   3.87298335
    20   4.47213595
    25   5

    READY

  STATUS

  TYPE: Integer Function
  FORMAT: STATUS

    Action: Returns a completion STATUS for the last input/output operation
  which was performed on an open file. The STATUS can be read from any
  peripheral device. The STATUS (or simply ST) keyword is a system defined

  84   BASIC LANGUAGE VOCABULARY

  variable-name into which the KERNAL puts the STATUS of I/O operations.
  A table of STATUS code values for tape, printer, disk and RS-232 file
  operations is shown below:

  +---------+------------+---------------+------------+-------------------+
  |  ST Bit | ST Numeric |    Cassette   |   Serial   |    Tape Verify    |
  | Position|    Value   |      Read     |  Bus R/W   |      + Load       |
  +---------+------------+---------------+------------+-------------------+
  |    0    |      1     |               |  time out  |                   |
  |         |            |               |  write     |                   |
  +---------+------------+---------------+------------+-------------------+
  |    1    |      2     |               |  time out  |                   |
  |         |            |               |    read    |                   |
  +---------+------------+---------------+------------+-------------------+
  |    2    |      4     |  short block  |            |    short block    |
  +---------+------------+---------------+------------+-------------------+
  |    3    |      8     |   long block  |            |    long block     |
  +---------+------------+---------------+------------+-------------------+
  |    4    |     16     | unrecoverable |            |   any mismatch    |
  |         |            |   read error  |            |                   |
  +---------+------------+---------------+------------+-------------------+
  |    5    |     32     |    checksum   |            |     checksum      |
  |         |            |     error     |            |       error       |
  +---------+------------+---------------+------------+-------------------+
  |    6    |     64     |  end of file  |     EOI    |                   |
  +---------+------------+---------------+------------+-------------------+
  |    7    |   -128     |  end of tape  | device not |    end of tape    |
  |         |            |               |   present  |                   |
  +---------+------------+---------------+------------+-------------------+

  EXAMPLES of STATUS Function:

    10 OPEN 1,4:OPEN 2,8,4,"MASTER FILE,SEQ,W"
    20 GOSUB 100:REM CHECK STATUS
    30 INPUT#2,A$,B,C
    40 IF STATUS AND 64 THEN 80:REM HANDLE END-OF-FILE
    50 GOSUB 100:REM CHECK STATUS
    60 PRINT#1,A$,B;C
    70 GOTO 20
    80 CLOSE1:CLOSE2
    90 GOSUB 100:END
    100 IF ST > 0 THEN 9000:REM HANDLE FILE I/O ERROR
    110 RETURN
                                             BASIC LANGUAGE VOCABULARY   85

  STEP

  TYPE: Statement
  FORMAT: [STEP <expression>]

    Action: The optional STEP keyword follows the <end-value> expression in
  a FOR statement. It defines an increment value for the loop counter
  variable. Any value can be used as the STEP increment. Of course, a STEP
  value of zero will loop forever. If the STEP keyword is left out, the
  increment value will be + 1. When the NEXT statement in a FOR loop is
  reached, the STEP increment happens. Then the counter is tested against
  the end-value to see if the loop is finished. (See FOR statement for more
  information.)
  +-----------------------------------------------------------------------+
  | NOTE: The STEP value can NOT be changed once it's in the loop.        |
  +-----------------------------------------------------------------------+
  EXAMPLES of STEP Statement:

    25 FOR XX=2 TO 20 STEP 2             (Loop repeats 10 times)
    35 FOR ZZ=0 TO -20 STEP -2           (Loop repeats 11 times)

  STOP

  TYPE: Statement
  FORMAT: STOP

    Action: The STOP statement is used to halt execution of the current
  program and return to direct mode. Typing the <RUN/STOP> key on the
  keyboard has the same effect as a STOP statement. The BASIC error message
  ?BREAK IN LINE nnnnn is displayed on the screen, followed by READY. The
  "nnnnn" is the line-number where the STOP occurs. Any open files remain
  open and all variables are preserved and can be examined. The program can
  be restarted by using CONT or GOTO statements.

  EXAMPLES of STOP Statement:

    10 INPUT#1,AA,BB,CC
    20 IF AA=BB AND BB=CC THEN STOP
    30 STOP
                    (If the variable AA is -1 and BB is equal to CC then:)
  BREAK IN LINE 20
  BREAK IN LINE 30        (For any other data values)

  86   BASIC LANGUAGE VOCABULARY

  STR$

  TYPE: String Function
  FORMAT: STR$ (<numeric>)

    Action: STR$ gives you the STRing representation of the numeric value
  of the argument. When the STR$ value is converted to each variable
  represented in the <numeric> argument, any number shown is followed by
  a space and, if it's positive, it is also preceded by a space.

  EXAMPLE of STR$ Function:

    100 FLT = 1.5E4: ALPHA$ = STR$(FLT)
    110 PRINT FLT, ALPHA$

    15000     15000

  SYS

  TYPE: Statement
  FORMAT: SYS <memory-location>

    Action: This is the most common way to mix a BASIC program with a
  machine language program. The machine language program begins at the
  location given in the SYS statement. The system command SYS is used in
  either direct or program mode to transfer control of the microprocessor
  to an existing machine language program in memory. The memory-location
  given is by numeric expression and can be anywhere in memory, RAM or ROM.
    When you're using the SYS statement you must end that section of
  machine language code with an RTS (ReTurn from Subroutine) instruction
  so that when the machine language program is finished, the BASIC
  execution will resume with the  statement following the SYS command.

  EXAMPLES of SYS Statement:

    SYS 64738                      (Jump to System Cold Start in ROM)

    10 POKE 4400,96:SYS 4400       (Goes to machine code location 4400
                                    and returns immediately)

                                             BASIC LANGUAGE VOCABULARY   87

  TAB

  TYPE: String Function
  FORMAT: TAB (<numeric>)

    Action: The TAB function moves the cursor to a relative SPC move
  position on the screen given by the <numeric> argument, starting with
  the left-most position of the current line. The value of the argument can
  range from 0 to 255. The TAB function should only be used with the PRINT
  statement, since it has no effect if used with PRINT# to a logical
  file.

  EXAMPLE of TAB Function:

    100 PRINT"NAME" TAB(25) "AMOUNT": PRINT
    110 INPUT#1, NAM$, AMT$
    120 PRINT NAM$ TAB(25) AMT$

    NAME                         AMOUNT

    G.T. JONES                   25.

  TAN

  TYPE: Floating-Point Function
  FORMAT: TAN (<numeric>)

    Action: Returns the tangent of the value of the <numeric> expression
  in radians. If the TAN function overflows, the BASIC error message
  ?DIVISION BY ZERO is displayed.

  EXAMPLE of TAN Function:

    10 XX=.785398163: YY=TAN(XX):PRINT YY

     1

  88   BASIC LANGUAGE VOCABULARY

  TIME

  TYPE: Numeric Function
  FORMAT: TI

    Action: The TI function reads the interval Timer. This type of "clock"
  is called a "jiffy clock." The "jiffy clock" value is set at zero
  (initialized) when you power-up the system. This 1/60 second interval
  timer is turned off during tape I/O.

  EXAMPLE of TI Function:

  10 PRINT TI/60 "SECONDS SINCE POWER UP"

  TIME$

  TYPE: String Function
  FORMAT: TI$

    Action: The TI$ timer looks and works like a real clock as long as your
  system is powered-on. The hardware interval timer (or jiffy clock) is
  read and used to update the value of TI$, which will give you a TIme
  $tring of six characters in hours, minutes and seconds. The TI$ timer can
  also be assigned an arbitrary starting point similar to the way you set
  your wristwatch. The value of TI$ is not accurate after tape I/O.

  EXAMPLE of TI$ Function:

    1 TI$ = "000000": FOR J=1 TO 10000: NEXT: PRINT TI$

    000011

                                             BASIC LANGUAGE VOCABULARY   89

  USR

  TYPE: Floating-Point Function
  FORMAT: USR (<numeric>)

    Action: The USR function jumps to a User callable machine language
  SubRoutine which has its starting address pointed to by the contents of
  memory locations 785-786. The starting address is established before
  calling the USR function by using POKE statements to set up locations
  785-786. Unless POKE statements are used, locations 785-786 will give
  you an ?ILLEGAL QUANTITY error message.
    The value of the <numeric> argument is stored in the floating-point
  accumulator starting at location 97, for access by the Assembler code,
  and the result of the USR function is the value which ends up there when
  the subroutine returns to BASIC.

  EXAMPLES of USR Function:

    10 B=T*SIN(Y)
    20 C=USR(B/2)
    30 D=USR(B/3)

  VAL

  TYPE: Numeric Function
  FORMAT: VAL (<string>)

    Action: Returns a numeric VALue representing the data in the <string>
  argument. If the first non-blank character of the string is not a plus
  sign (+), minus sign (-), or a digit the VALue returned is zero. String
  conversion is finished when the end of the string or any non-digit
  character is found (except decimal point or exponential e).

  EXAMPLE of VAL Function:

    10 INPUT#1, NAM$, ZIP$
    20 IF VAL(ZIP$) < 19400 OR VAL(ZIP$) > 96699
       THEN PRINT NAM$ TAB(25) "GREATER PHILADELPHIA"

  90   BASIC LANGUAGE VOCABULARY

  VERIFY

  TYPE: Command
  FORMAT: VERIFY ["<file-name>"][,<device>]

  Action: The VERIFY command is used, in direct or program mode, to compare
  the contents of a BASIC program file on tape or disk with the program
  currently in memory. VERIFY is normally used right after a SAVE, to make
  sure that the program was stored correctly on tape or disk.
    If the <device> number is left out, the program is assumed to be on
  the Datassette(TM) which is device number 1. For tape files, if the
  <file-name> is left out, the next program found on the tape will be com-
  pared. For disk files (device number 8), the file-name must be present.
  If any differences in program text are found, the BASIC error message
  ?VERIFY ERROR is displayed.
    A program name can be given either in quotes or as a string variable.
  VERIFY is also used to position a tape just past the last program, so
  that a new program can be added to the tape without accidentally writing
  over another program.

  EXAMPLES of VERIFY Command:

    VERIFY                      (Checks 1st program on tape)
    PRESS PLAY ON TAPE
    OK
    SEARCHING
    FOUND <FILENAME>
    VERIFYING

    9000 SAVE "ME",8:
    9010 VERIFY "ME",8          (Looks at device 8 for the program)

                                             BASIC LANGUAGE VOCABULARY   91

  WAIT

  TYPE: Statement
  FORMAT: WAIT <location>,<mask-1>[,<mask-2>]

    Action: The WAIT statement causes program execution to be suspended
  until a given memory address recognizes a specified bit pattern. In other
  words WAIT can be used to halt the program until some external event has
  occurred. This is done by monitoring the status of bits in the input/
  output registers, The data items used with WAIT can be any numeric
  expressions, but they will be converted to integer values. For most
  programmers, this statement should never be used. It causes the program
  to halt until a specific memory location's bits change in a specific way.
  This is used for certain I/O operations and almost nothing else.
    The WAIT statement takes the value in the memory location and performs
  a logical AND operation with the value in mask-1. If there is a mask-2 in
  the statement, the result of the first operation is exclusive-ORed with
  mask-2. In other words mask-1 "filters out" any bits that you don't want
  to test. Where the bit is 0 in mask-1, the corresponding bit in the
  result will always be 0. The mask-2 value flips any bits, so that you
  can test for an off condition as well as an on condition, Any bits being
  tested for a 0 should have a I in the corresponding position in mask-2.
    If corresponding bits of the <mask-1> and <mask-2> operands differ, the
  exclusive-OR operation gives a bit result of 1. If corresponding bits get
  the same result the bit is 0. It is possible to enter an infinite pause
  with the WAIT statement, in which case the <RUN/STOP> and <RESTORE> keys
  can be used to recover. Hold down the <RUN/STOP> key and then press
  <RESTORE>. The first example below WAITs until a key is pressed on the
  tape unit to continue with the program. The second example will WAIT
  until a sprite collides with the screen background.

  EXAMPLES of WAIT Statement:

    WAIT 1,32,32
    WAIT 53273,6,6
    WAIT 36868,144,16         (144 & 16 are masks. 144=10010000 in binary
                               and 16=10000 in binary. The WAIT statement
                               will halt the program until the 128 bit is
                               on or until the 16 bit is off)

  92   BASIC LANGUAGE VOCABULARY

  THE COMMODORE 64 KEYBOARD
  AND FEATURES

    The Operating System has a ton-character keyboard "buffer" that is used
  to hold incoming keystrokes until they can be processed. This buffer, or
  queue, holds keystrokes in the order in which they occur so that the
  first one put into the queue is the first one processed. For example, if
  a second keystroke occurs before the first can be processed, the second
  character Is stored in the buffer, while processing of the first
  character continues. After the program has finished with the first
  character, the keyboard buffer is examined for more data, and the second
  keystroke processed. Without this buffer, rapid keyboard input would
  occasionally drop characters.
    In other words, the keyboard buffer allows you to "type-ahead" of the
  system, which means it can anticipate responses to INPUT prompts or GET
  statements. As you type on the keys their character values are lined up,
  single-file (queued) into the buffer to wait for processing in the order
  the keys were struck. This type-ahead feature can give you an occasional
  problem where an accidental keystroke causes a program to fetch an
  incorrect character from the buffer.
    Normally, incorrect keystrokes present no problem, since they can be
  corrected by the CuRSoR-Left <CRSR LEFT> or DELete <INST/DEL> keys and
  then retyping the character, and the corrections will be processed before
  a following carriage-return. However, if you press the <RETURN> key, no
  corrective action is possible, since all characters in the buffer up to
  and including the carriage-return will be processed before any cor-
  rections. This situation can be avoided by using a loop to empty the
  keyboard buffer before reading an intended response:

    10 GET JUNK$: IF JUNK$ <>"" THEN 10: REM EMPTY THE KEYBOARD BUFFER

    In addition to GET and INPUT, the keyboard can also be read using
  PEEK to fetch from memory location 197 ($00C5) the integer value of the
  key currently being pressed. If no key Is being held when the PEEK is
  executed, a value of 64 is returned, The numeric keyboard values,
  keyboard symbols and character equivalents (CHR$) are shown in Ap-
  pendix C. The following example loops until a key is pressed then con-
  verts the integer to a character value.

    10 AA=PEEK(197): IF AA=64 THEN 10
    20 BB$=CHR$(AA)

                                             BASIC LANGUAGE VOCABULARY   93

    The keyboard is treated as a set of switches organized into a matrix
  of 8 columns by 8 rows. The keyboard matrix is scanned for key switch-
  closures by the KERNAL using the CIA #l 1/0 chip (MOS 6526 Complex
  Interface Adapter). Two CIA registers are used to perform the scan:
  register #0 at location 56320 ($DC00) for keyboard columns and
  register #l at location 56321 ($DC01) for keyboard rows.
    Bits 0-7 of memory location 56320 correspond to the columns 0-7. Bits
  0-7 of memory location 56321 correspond to rows 0-7. By writing column
  values in sequence, then reading row values, the KERNAL decodes the
  switch closures into the CHR$ (N) value of the key pressed.
    Eight columns by eight rows yields 64 possible values. However, if you
  first strike the <RVS ON>, <CTRL> or <C=> keys or hold down the <SHIFT>
  key and type a second character, additional values are generated. This is
  because the KERNAL decodes these keys separately and "remembers" when one
  of the control keys was pressed. The result of the keyboard scan is then
  placed in location 197.
    Characters can also be written directly to the keyboard buffer at lo-
  cations 631-640 using a POKE statement. These characters will be
  processed when the POKE is used to set a character count into location
  198. These facts can be used to cause a series of direct-mode commands to
  be executed automatically by printing the statements onto the screen,
  putting carriage-returns into the buffer, and then setting the character
  count. In the example below, the program will LIST itself to the printer
  and then resume execution.

    10 PRINT CHR$(147)"PRINT#1: CLOSE 1: GOTO 50"
    20 POKE 631119: POKE 632,13: POKE 633,13: POKE 198,3
    30 OPEN 114: CMD1: LIST
    40 END
    50 REM PROGRAM RE-STARTS HERE

  SCREEN EDITOR

    The SCREEN EDITOR provides you with powerful and convenient facilities
  for editing program text. Once a section of a program is listed to the
  screen, the cursor keys and other special keys are used to move around
  the screen so that you can make any appropriate changes. After making all
  the changes you want to a specific line-number of text, hitting the
  <RETURN> key anywhere on the line, causes the SCREEN EDITOR to read the
  entire 80-character logical screen line.

  94   BASIC LANGUAGE VOCABULARY

    The text is then passed to the Interpreter to be tokenized and stored
  in the program. The edited line replaces the old version of that line in
  memory. An additional copy of any line of text can be created simply by
  changing the line-number and pressing <RETURN>.
    If you use keyword abbreviations which cause a program line to exceed
  80 characters, the excess characters will be lost when that line is
  edited, because the EDITOR will read only two physical screen lines. This
  is also why using INPUT for more than a total of 80 characters is not
  possible. Thus, for all practical purposes, the length of a line of BASIC
  text is limited to 80 characters as displayed on the screen.
    Under certain conditions the SCREEN EDITOR treats the cursor control
  keys differently from their normal mode of handling. If the CuRSoR is
  positioned to the right of an odd number of double-quote marks (") the
  EDITOR operates in what is known as the QUOTE-MODE.
    In quote mode data characters are entered normally but the cursor
  controls no longer move the CuRSoR, instead reversed characters are
  displayed which actually stand for the cursor control being entered. The
  same is true of the color control keys. This allows you to include cursor
  and color controls inside string data items in programs. You will find
  that this is a very important and powerful feature. That's because when
  the text inside the quotes is printed to the screen it performs the
  cursor positioning and color control functions automatically as part of
  the string. An example of using cursor controls in strings is:

    You type -->         10 PRINT"A(R)(R)B(L)(L)(L)C(R)(R)D": REM(R)=CRSR
                            RIGHT, (L)=CRSR LEFT

    Computer prints -->  AC BD

     The <DEL> key is the only cursor control NOT affected by quote mode.
   Therefore, if an error is made while keying in quote mode, the
   <CRSR LEFT> key can't be used to back up and strike over the error -
   even the <INST> key produces a reverse video character. Instead, finish
   entering the line, and then, after hitting the <RETURN> key, you can
   edit the line normally. Another alternative, if no further cursor-
   controls are needed in the string, is to press the <RUN/STOP> and
   <RESTORE> keys which will cancel QUOTE MODE. The cursor control keys
   that you can use in strings are shown in Table 2-2.

                                             BASIC LANGUAGE VOCABULARY   95

             Table 2-2. Cursor Control Characters in QUOTE MODE
  -------------------------------------------------------------------------
                  Control Key                      Appearance
  -------------------------------------------------------------------------

              CRSR up
              CRSR down
              CRSR left
              CRSR right
              CLR
              HOME
              INST

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

    When you are NOT in quote mode, holding down the <SHIFT> key and then
  pressing the INSerT <INST> key shifts data to the right of the cursor to
  open up space between two characters for entering data between them. The
  Editor then begins operating in INSERT MODE until all of the space opened
  up is filled.
    The cursor controls and color controls again show as reversed char-
  acters in insert mode. The only difference occurs on the DELete and
  INSerT <INST/DEL> key. The <DEL> instead of operating normally as in
  the quote mode, now creates the reversed <T>. The <INST> key, which
  created a reverse character in quote mode, inserts spaces normally.
    This means that a PRINT statement can be created, containing DELetes,
  which can't be done in quote mode. The insert mode is cancelled by
  pressing the <RETURN>, <SHIFT> and <RETURN>, or <RUN/STOP> and <RESTORE>
  keys. Or you can cancel the insert mode by filling all the inserted
  spaces. An example of using DEL characters in strings is:

    10 PRINT"HELLO"<DEL><INST><INST><DEL><DEL>P"
   (Keystroke sequence shown above, appearance when listed below)
   10 PRINT"HELP"

    When the example is RUN, the word displayed will be HELP, because the
  letters LO are deleted before the P is printed. The DELete character in
  strings will work with LIST as well as PRINT. You can use this to "hide"
  part or all of a line of text using this technique. However, trying to
  edit a line with these characters will be difficult if not impossible.

  96   BASIC LANGUAGE VOCABULARY

    There are some other characters that can be printed for special func-
  tions, although they are not easily available from the keyboard. In order
  to get these into quotes, you must leave empty spaces for them in the
  line, press <RETURN>, and go back to edit the line. Now you hold down
  the <CTRL> (ConTRoL) key and type <RVS ON> (ReVerSe-ON) to start typing
  reversed characters. Type the keys as shown below:

    Key Function                Key Entered         Appearance

    Shifted RETURN              <SHIFT+M>
    Switch to upper/lower case  <N>
    Switch to upper/graphics    <SHIFT+N>

    Holding down the <SHIFT> key and hitting <RETURN> causes a carriage-
  return and line-feed on the screen but does not end the string. This
  works with LIST as well as PRINT, so editing will be almost impossible if
  this character is used. When output is switched to the printer via the
  CMD statement, the reverse "N" character shifts the printer into its
  upper-lower case character set and the <SHIFT> "N" shifts the printer
  into the upper-case/graphics character set.
    Reverse video characters can be included in strings by holding down
  the ConTRoL <CTRL> key and pressing ReVerSe <RVS>, causing a reversed R
  to appear inside the quotes. This will make all characters print in
  reverse video (like a negative of a photograph). To end the reverse
  printing, press <CTRL> and <RVS OFF> (ReVerSe OFF) by holding down the
  <CTRL> key and typing the <RVS OFF> key, which prints a reverse R.
  Numeric data can be printed in reverse video by first printing a
  CHR$(18). Printing a CHR$(146) or a carriage-return will cancel reverse
  video output.

                                             BASIC LANGUAGE VOCABULARY   97

                                                 CHAPTER 3

                                               PROGRAMMING
                                                  GRAPHICS
                                                    ON THE
                                              COMMODORE 64

                           o Graphics Overview
                           o Graphics Locations
                           o Standard Character Mode
                           o Programmable Characters
                           o Multi-Color Mode Graphics
                           o Extended Background Color Mode
                           o Bit Mapped Graphics
                           o Multi-Color Bit Map Mode
                           o Smooth Scrolling
                           o Sprites
                           o Other Graphics Features
                           o Programming Sprites -
                             Another Look

                                     99

  GRAPHICS OVERVIEW

  All of the graphics abilities of the Commodore 64 come from the 6567
  Video Interface Chip (also known as the VIC-II chip). This chip gives a
  variety of graphics modes, including a 40 column by 25 line text display,
  a 320 by 200 dot high resolution display, and SPRITES, small movable
  objects which make writing games simple. And if this weren't enough,
  many of the graphics modes can be mixed on the same screen. It is
  possible, for example, to define the top half of the screen to be in
  high resolution mode, while the bottom half is in text mode. And SPRITES
  will combine with anything! More on sprites later. First the other
  graphics modes.
    The VIC-II chip has the following graphics display modes:

  A) CHARACTER DISPLAY MODES

     1) Standard Character Mode
            a)ROM characters
            b)RAM programmable characters
     2) Multi-Color Character Mode
            a)ROM characters
            b)RAM programmable characters

     3) Extended Background Color Mode
            a)ROM characters
            b)RAM programmable characters

  B) BIT MAP MODES

     1) Standard Bit Map Mode
     2) Multi-Color Bit Map Mode

  C) SPRITES

     1) Standard Sprites
     2) Multi-Color Sprites

  100   PROGRAMMING GRAPHICS

  GRAPHICS LOCATIONS

    Some general information first. There are 1000 possible locations on
  the Commodore 64 screen. Normally, the screen starts at location 1024
  ($0400 in HEXadecimal notation) and goes to location 2023. Each of
  these locations is 8 bits wide. This means that it can hold any integer
  number from 0 to 255. Connected with screen memory is a group of 1000
  locations called COLOR MEMORY or COLOR RAM. These start at location 55296
  ($D800 in HEX) and go up to 56295. Each of the color RAM locations is 4
  bits wide, which means that it can hold any integer number from 0 to 15.
  Since there are 16 possible colors that the Commodore 64 can use, this
  works out well.
    In addition, there are 256 different characters that can be displayed
  at any time. For normal screen display, each of the 1000 locations in
  screen memory contains a code number which tells the VIC-II chip which
  character to display at that screen location.
    The various graphics modes are selected by the 47 CONTROL registers in
  the VIC-II chip. Many of the graphics functions can be controlled by
  POKEing the correct value into one of the registers. The VIC-II chip is
  located starting at 53248 ($D000 in HEX) through 53294 ($D02E in HEX).

  VIDEO BANK SELECTION

    The VIC-II chip can access ("see") 16K of memory at a time. Since there
  is 64K of memory in the Commodore 64, you want to be able to have the
  VIC-II chip see all of it. There is a way. There are 4 possible BANKS
  (or sections) of 16K of memory. All that is needed is some means of
  controlling which 16K bank the VIC-II chip looks at. In that way, the
  chip can "see" the entire 64K of memory. The BANK SELECT bits that allow
  you access to all the different sections of memory are located in the
  6526 COMPLEX INTERFACE ADAPTER CHIP #2 (CIA #2). The POKE and PEEK BASIC
  statements (or their machine language versions) are used to select a
  bank, by controlling bits 0 and 1 of PORT A of CIA#2 (location 56576 (or
  $DD00 HEX)). These 2 bits must be set to outputs by setting bits 0 and 1
  of location 56578 ($DD02,HEX) to change banks. The following example
  shows this:

    POKE 56578,PEEK(56578)OR 3: REM MAKE SURE BITS 0 AND 1 ARE OUTPUTS
    POKE 56576,(PEEK(56576)AND 252)OR A: REM CHANGE BANKS

    "A" should have one of the following values:

                                                 PROGRAMMING GRAPHICS   101

  +-------+------+-------+----------+-------------------------------------+
  | VALUE | BITS |  BANK | STARTING |  VIC-II CHIP RANGE                  |
  |  OF A |      |       | LOCATION |                                     |
  +-------+------+-------+----------+-------------------------------------+
  |   0   |  00  |   3   |   49152  | ($C000-$FFFF)*                      |
  |   1   |  01  |   2   |   32768  | ($8000-$BFFF)                       |
  |   2   |  10  |   1   |   16384  | ($4000-$7FFF)*                      |
  |   3   |  11  |   0   |       0  | ($0000-$3FFF) (DEFAULT VALUE)       |
  +-------+------+-------+----------+-------------------------------------+

    This 16K bank concept is part of everything that the VIC-II chip does.
  You should always be aware of which bank the VIC-II chip is pointing at,
  since this will affect where character data patterns come from, where the
  screen is, where sprites come from, etc. When you turn on the power of
  your Commodore 64, bits 0 and 1 of location 56576 are automatically set
  to BANK 0 ($0000-$3FFF) for all display information.

  +-----------------------------------------------------------------------+
  | *NOTE: The Commodore 64 character set is not available to the VIC-II  |
  | chip in BANKS 1 and 3. (See character memory section.)                |
  +-----------------------------------------------------------------------+

  SCREEN MEMORY

    The location of screen memory can be changed easily by a POKE to
  control register 53272 ($D018 HEX). However, this register is also used
  to control which character set is used, so be careful to avoid disturbing
  that part of the control register. The UPPER 4 bits control the location
  of screen memory. To move the screen, the following statement should be
  used:

  POKE53272,(PEEK(53272)AND15)OR A

  102   PROGRAMMING GRAPHICS

  Where "A" has one of the following values:
  +---------+------------+-----------------------------+
  |         |            |         LOCATION*           |
  |    A    |    BITS    +---------+-------------------+
  |         |            | DECIMAL |        HEX        |
  +---------+------------+---------+-------------------+
  |     0   |  0000XXXX  |      0  |  $0000            |
  |    16   |  0001XXXX  |   1024  |  $0400 (DEFAULT)  |
  |    32   |  0010XXXX  |   2048  |  $0800            |
  |    48   |  0011XXXX  |   3072  |  $0C00            |
  |    64   |  0100XXXX  |   4096  |  $1000            |
  |    80   |  0101XXXX  |   5120  |  $1400            |
  |    96   |  0110XXXX  |   6144  |  $1800            |
  |   112   |  0111XXXX  |   7168  |  $1C00            |
  |   128   |  1000XXXX  |   8192  |  $2000            |
  |   144   |  1001XXXX  |   9216  |  $2400            |
  |   160   |  1010XXXX  |  10240  |  $2800            |
  |   176   |  1011XXXX  |  11264  |  $2C00            |
  |   192   |  1100XXXX  |  12288  |  $3000            |
  |   208   |  1101XXXX  |  13312  |  $3400            |
  |   224   |  1110XXXX  |  14336  |  $3800            |
  |   240   |  1111XXXX  |  15360  |  $3C00            |
  +---------+------------+---------+-------------------+
  +-----------------------------------------------------------------------+
  | * Remember that the BANK ADDRESS of the VIC-II chip must be added in. |
  | You must also tell the KERNAL'S screen editor where the screen is as  |
  | follows: POKE 648, page (where page = address/256, e.g., 1024/256= 4, |
  | so POKE 648,4).                                                       |
  +-----------------------------------------------------------------------+

  COLOR MEMORY

    Color memory can NOT move. It is always located at locations 55296
  ($D800) through 56295 ($DBE7). Screen memory (the 1000 locations starting
  at 1024) and color memory are used differently in the different graphics
  modes. A picture created in one mode will often look completely different
  when displayed in another graphics mode.

  CHARACTER MEMORY

    Exactly where the VIC-II gets it character information is important to
  graphic programming. Normally, the chip gets the shapes of the characters

                                                 PROGRAMMING GRAPHICS   103

  you want to be displayed from the CHARACTER GENERATOR ROM. In this chip
  are stored the patterns which make up the various letters, numbers,
  punctuation symbols, and the other things that you see on the keyboard.
  One of the features of the Commodore 64 is the ability to use patterns
  located in RAM memory. These RAM patterns are created by you, and that
  means that you can have an almost infinite set of symbols for games,
  business applications, etc.
    A normal character set contains 256 characters in which each character
  is defined by 8 bytes of data. Since each character takes up 8 bytes this
  means that a full character set is 256*8=2K bytes of memory. Since the
  VIC-II chip looks at 16K of memory at a time, there are 8 possible
  locations for a complete character set. Naturally, you are free to use
  less than a full character set. However, it must still start at one of
  the 8 possible starting locations.
    The location of character memory is controlled by 3 bits of the VIC-II
  control register located at 53272 ($D018 in HEX notation). Bits 3,2, and
  1 control where the characters' set is located in 2K blocks. Bit 0 is ig-
  nored. Remember that this is the same register that determines where
  screen memory is located so avoid disturbing the screen memory bits. To
  change the location of character memory, the following BASIC statement
  can be used:

    POKE 53272,(PEEK(53272)AND240)OR A

  Where A is one of the following values:
  +-----+----------+------------------------------------------------------+
  |VALUE|          |            LOCATION OF CHARACTER MEMORY*             |
  | of A|   BITS   +-------+----------------------------------------------+
  |     |          |DECIMAL|         HEX                                  |
  +-----+----------+-------+----------------------------------------------+
  |   0 | XXXX000X |     0 | $0000-$07FF                                  |
  |   2 | XXXX001X |  2048 | $0800-$0FFF                                  |
  |   4 | XXXX010X |  4096 | $1000-$17FF ROM IMAGE in BANK 0 & 2 (default)|
  |   6 | XXXX011X |  6144 | $1800-$1FFF ROM IMAGE in BANK 0 & 2          |
  |   8 | XXXX100X |  8192 | $2000-$27FF                                  |
  |  10 | XXXX101X | 10240 | $2800-$2FFF                                  |
  |  12 | XXXX110X | 12288 | $3000-$37FF                                  |
  |  14 | XXXX111X | 14336 | $3800-$3FFF                                  |
  +-----+----------+-------+----------------------------------------------+
  +-----------------------------------------------------------------------+
  | * Remember to add in the BANK address.                                |
  +-----------------------------------------------------------------------+

  104   PROGRAMMING GRAPHICS

    The ROM IMAGE in the above table refers to the character generator ROM.
  It appears in place of RAM at the above locations in bank 0. it  also
  appears in the corresponding RAM at locations 36864-40959 ($9000-$9FFF)
  in bank 2. Since the VIC-II chip can only access 16K of memory at a time,
  the ROM character patterns appear in the 16K block of memory the VIC-II
  chip looks at. Therefore, the system was designed to make the VIC-II chip
  think that the ROM characters are at 4096-8191 ($1000-$1FFF) when your
  data is in bank 0, and 36864-40959 ($9000-$9FFF) when your data is in
  bank 2, even though the character ROM is actually at location 53248-57343
  ($D000-$DFFF). This imaging only applies to character data as seen by the
  VIC-II chip. It can be used for programs, other data, etc., just like any
  other RAM memory.

  +-----------------------------------------------------------------------+
  | NOTE: If these ROM images got in the way of your own graphics, then   |
  | set the BANK SELECT BITS to one of the BANKS without the images       |
  | (BANKS 1 or 3). The ROM patterns won't be there.                      |
  +-----------------------------------------------------------------------+

   The location and contents of the character set in ROM are as follows:

  +-----+-------------------+-----------+---------------------------------+
  |     |       ADDRESS     |   VIC-II  |                                 |
  |BLOCK+-------+-----------+   IMAGE   |            CONTENTS             |
  |     |DECIMAL|    HEX    |           |                                 |
  +-----+-------+-----------+-----------+---------------------------------+
  |  0  | 53248 | D000-D1FF | 1000-11FF | Upper case characters           |
  |     | 53760 | D200-D3FF | 1200-13FF | Graphics characters             |
  |     | 54272 | D400-D5FF | 1400-15FF | Reversed upper case characters  |
  |     | 54784 | D600-D7FF | 1600-17FF | Reversed graphics characters    |
  |     |       |           |           |                                 |
  |  1  | 55296 | D800-D9FF | 1800-19FF | Lower case characters           |
  |     | 55808 | DA00-DBFF | 1A00-1BFF | Upper case & graphics characters|
  |     | 56320 | DC00-DDFF | 1C00-1DFF | Reversed lower case characters  |
  |     | 56832 | DE00-DFFF | 1E00-1FFF | Reversed upper case &           |
  |     |       |           |           | graphics characters             |
  +-----+-------+-----------+-----------+---------------------------------+

    Sharp-eyed readers will have just noticed something. The locations
  occupied by the character ROM are the same as the ones occupied by the
  VIC-II chip control registers. This is possible because they don't occupy
  the same locations at the same time. When the VIC-II chip needs to access

                                                 PROGRAMMING GRAPHICS   105

  character data the ROM is switched in. It becomes an image in the 16K
  bank of memory that the VIC-II chip is looking at. Otherwise, the area is
  occupied by the I/O control registers, and the character ROM is only
  available to the VIC-II chip.
    However, you may need to get to the character ROM if you are going to
  use programmable characters and want to copy some of the character ROM
  for some of your character definitions. In this case you must switch out
  the I/O register, switch in the character ROM, and do your copying. When
  you're finished, you must switch the 1/0 registers back in again. During
  the copying process (when I/O is switched out) no interrupts can be
  allowed to take place. This is because the I/O registers are needed to
  service the interrupts. If you forget and perform an interrupt, really
  strange things happen. The keyboard should not be read during the copying
  process. To turn off the keyboard and other normal interrupts that occur
  with your Commodore 64, the following POKE should be used:

    POKE 56334,PEEK(56334)AND254   (TURNS INTERRUPTS OFF)

    After you are finished getting characters from the character ROM, and
  are ready to continue with your program, you must turn the keyboard scan
  back on by the following POKE:

    POKE 56334,PEEK(56334)OR1      (TURNS INTERRUPTS ON)

    The following POKE will switch out 1/0 and switch the CHARACTER ROM in:

    POKE 1,PEEK(1)AND251

    The character ROM is now in the locations from 53248-57343 ($D000-
  $DFFF).
    To switch I/O back into $D000 for normal operation use the following
  POKE:

    POKE 1,PEEK(1)OR 4

  106   PROGRAMMING GRAPHICS

  STANDARD CHARACTER MODE

    Standard character mode is the mode the Commodore 64 is in when you
  first turn it on. It is the mode you will generally program in.
    Characters can be taken from ROM or from RAM, but normally they are
  taken from ROM. When you want special graphics characters for a program,
  all you have to do is define the new character shapes in RAM, and tell
  the VIC-II chip to get its character information from there instead of
  the character ROM. This is covered in more detail in the next section.
    In order to display characters on the screen in color, the VIC-II chip
  accesses the screen memory to determine the character code for that
  location on the screen. At the same time, it accesses the color memory to
  determine what color you want for the character displayed. The character
  code is translated by the VIC-II into the starting address of the 8-byte
  block holding your character pattern. The 8-byte block is located in
  character memory.
    The translation isn't too complicated, but a number of items are com-
  bined to generate the desired address. First the character code you use
  to POKE screen memory is multiplied by 8. Next add the start of char-
  acter memory (see CHARACTER MEMORY section). Then the Bank Select Bits
  are taken into account by adding in the base address (see VIDEO BANK
  SELECTION section). Below is a simple formula to illustrate what happens:

  CHARACTER ADDRESS = SCREEN CODE*8+(CHARACTER SET*2048)+(BANK*16384)

  CHARACTER DEFINITIONS

    Each character is formed in an 8 by 8 grid of dots, where each dot may
  be either on or off. The Commodore 64 character images are stored in the
  Character Generator ROM chip. The characters are stored as a set of 8
  bytes for each character, with each byte representing the dot pattern of
  a row in the character, and each bit representing a dot. A zero bit means
  that dot is off, and a one bit means the dot is on.
    The character memory in ROM begins at location 53248 (when the I/O
  is switched off). The first 8 bytes from location 53248 ($D000) to 53255
  ($D007) contain the pattern for the @ sign, which has a character code
  value of zero in the screen memory. The next 8 bytes, from location

                                                 PROGRAMMING GRAPHICS   107

  53256 ($D008) to 53263 ($D00F), contain the information for forming the
  letter A.

       IMAGE     BINARY       PEEK

        **      00011000       24
       ****     00111100       60
      **  **    01100110      102
      ******    01111110      126
      **  **    01100110      102
      **  **    01100110      102
      **  **    01100110      102
		00000000	0

    Each complete character set takes up 2K (2048 bits) of memory, 8 bytes
  per character and 256 characters. Since there are two character sets, one
  for upper case and graphics and the other with upper and lower case, the
  character generator ROM takes up a total of 4K locations.

  PROGRAMMABLE CHARACTERS

    Since the characters are stored in ROM, it would seem that there is no
  way to change them for customizing characters. However, the memory
  location that tells the VIC-II chip where to find the characters is a
  programmable register which can be changed to point to many sections of
  memory. By changing the character memory pointer to point to RAM, the
  character set may be programmed for any need.
    If you want your character set to be located in RAM, there are a few
  VERY IMPORTANT things to take into account when you decide to actually
  program your own character sets. In addition, there are two other
  important points you must know to create your own special characters:

    1) It is an all or nothing process. Generally, if you use your own
       character set by telling the VIC-II chip to get the character
       information from the area you have prepared in RAM, the standard
     Commodore 64 characters are unavailable to you. To solve this, you
     must copy any letters, numbers, or standard Commodore 64 graphics you
     intend to use into your own character memory in RAM. You can pick and
     choose, take only the ones you want, and don't even have to keep them
     in order!

  108   PROGRAMMING GRAPHICS

    2) Your character set takes memory space away from your BASIC program.
       Of course, with 38K available for a BASIC program, most applications
       won't have problems.

  +-----------------------------------------------------------------------+
  | WARNING: You must be careful to protect the character set from being  |
  | overwritten by your BASIC program, which also uses the RAM.           |
  +-----------------------------------------------------------------------+

    There are two locations in the Commodore 64 to start your character set
  that should NOT be used with BASIC: location 0 and location 2048. The
  first should not be used because the system stores important data on
  page 0. The second can't be used because that is where your BASIC program
  starts! However, there are 6 other starting positions for your custom
  character set.
    The best place to put your character set for use with BASIC while
  experimenting is beginning at 12288 ($3000 in HEX). This is done by
  POKEing the low 4 bits of location 53272 with 12. Try the POKE now, like
  this:

    POKE 53272,(PEEK(53272)AND240)+12

    Immediately, all the letters on the screen turn to garbage, This is
  because there are no characters set up at location 12288 right now...
  only random bytes. Set the Commodore 64 back to normal by hitting the
  <RUN/STOP> key and then the <RESTORE> key.
    Now let's begin creating graphics characters. To protect your char-
  acter set from BASIC, you should reduce the amount of memory BASIC
  thinks it has. The amount of memory in your computer stays the same...
  it's just that you've told BASIC not to use some of it. Type:

    PRINT FRE(0)-(SGN(FRE(0))<0)*65535

    The number displayed is the amount of memory space left unused. Now
  type the following:

    POKE 52148:POKE56,48:CLR

  Now type:

    PRINT FRE(0)-(SGN(FRE(0))<0)*65535

                                                 PROGRAMMING GRAPHICS   109

  See the change? BASIC now thinks it has less memory to work with. The
  memory you just claimed from BASIC is where you are going to put your
  character set, safe from actions of BASIC.
    The next step is to put your characters into RAM. When you begin, there
  is random data beginning at 12288 ($3000 HEX). You must put character
  patterns in RAM (in the same style as the ones in ROM) for the VIC-II
  chip to use.
    The following program moves 64 characters from ROM to your character
  set RAM:

start tok64 page110.prg
  5 printchr$(142)               :rem switch to upper case
  10 poke52,48:poke 56,48:clr    :rem reserve memory for characters
  20 poke56334,peek(56334)and254 :rem turn off keyscan interrupt timer
  30 poke1,peek(1)and251         :rem switch in character
  40 fori=0to511:pokei+12288,peek(i+53248):next
  50 poke1,peek(1)or4            :rem switch in i/o
  60 poke56334,peek(56334)or1    :rem restart keyscan interrupt timer
  70 end
stop tok64

    Now POKE location 53272 with (PEEK(53272)AND240)+12. Nothing happens,
  right? Well, almost nothing. The Commodore 64 is now getting it's
  character information from your RAM, instead of from ROM. But since we
  copied the characters from ROM exactly, no difference can be seen... yet.
    You can easily change the characters now. Clear the screen and type
  an @ sign. Move the cursor down a couple of lines, then type:

  FOR I=12288 TO 12288+7:POKE 1,255-PEEK(I):NEXT

  You just created a reversed @ sign!

  +-----------------------------------------------------------------------+
  | TIP: Reversed characters are just characters with their bit patterns  |
  | in character memory reversed.                                         |
  +-----------------------------------------------------------------------+

    Now move the cursor up to the program again and hit <RETURN> again to
  re-reverse the character (bring it back to normal). By looking at the
  table of screen display codes, you can figure out where in RAM each
  character is. Just remember that each character takes eight memory
  locations to store. Here's a few examples just to get you started:

  110   PROGRAMMING GRAPHICS

  +-----------+--------------+--------------------------------------------+
  | CHARACTER | DISPLAY CODE |      CURRENT STARTING LOCATION IN RAM      |
  +-----------+--------------+--------------------------------------------+
  |     @     |       0      |                    1228                    |
  |     A     |       1      |                   12296                    |
  |     !     |      33      |                   12552                    |
  |     >     |      62      |                   12784                    |
  +-----------+--------------+--------------------------------------------+

    Remember that we only took the first 64 characters. Something else will
  have to be done if you want one of the other characters.
    What if you wanted character number 154, a reversed Z? Well, you could
  make it yourself, by reversing a Z, or you could copy the set of reversed
  characters from the ROM, or just take the one character you want from ROM
  and replace one of the characters you have in RAM that you don't need.

    Suppose you decide that you won't need the > sign. Let's replace the
  > sign with the reversed Z. Type this:

    FOR I=0 TO 7:POKE 12784+I,255-PEEK(I+12496):NEXT

    Now type a > sign. It comes up as a reversed Z. No matter how many
  times you type the >, it comes out as a reversed Z. (This change is
  really an illusion. Though the > sign looks like a reversed Z, it still
  acts like a > in a program. Try something that needs a > sign. It will
  still work fine, only it will look strange.)
    A quick review: You can now copy characters from ROM into RAM. You can
  even pick and choose only the ones you want. There's only one step left
  in programmable characters (the best step!)... making your own
  characters.
    Remember how characters are stored in ROM? Each character is stored as
  a group of eight bytes. The bit patterns of the bytes directly control
  the character. If you arrange 8 bytes, one on top of another, and write
  out each byte as eight binary digits, it forms an eight by eight matrix,
  looking like the characters. When a bit is a one, there is a dot at that
  location. When a bit is a zero, there is a space at that location. When
  creating your own characters, you set up the same kind of table in
  memory. Type NEW and then type this program:

    10 FOR I=12448 TO 12455: READ A:POKE I,A:NEXT
    20 DATA 60, 66, 165, 129, 165, 153, 66, 60

                                                 PROGRAMMING GRAPHICS   111

  Now type RUN. The program will replace the letter T with a smile face
  character. Type a few T's to see the face. Each of the numbers in the
  DATA statement in line 20 is a row in the smile face character. The
  matrix for the face looks like this:

           76543210          BINARY      DECIMAL

          +--------+
    ROW 0 |  ****  |        00111100        60
        1 | *    * |        01000010        66
        2 |* *  * *|        10100101       165
        3 |*      *|        10000001       129
        4 |* *  * *|        10100101       165
        5 |*  **  *|        10011001       153
        6 | *    * |        01000010        66
    ROW 7 |  ****  |        00111100        60
          +--------+

                               7 6 5 4 3 2 1 0

                              +-+-+-+-+-+-+-+-+
                            0 | | | | | | | | |
                              +-+-+-+-+-+-+-+-+
                            1 | | | | | | | | |
                              +-+-+-+-+-+-+-+-+
                            2 | | | | | | | | |
                              +-+-+-+-+-+-+-+-+
                            3 | | | | | | | | |
                              +-+-+-+-+-+-+-+-+
                            4 | | | | | | | | |
                              +-+-+-+-+-+-+-+-+
                            5 | | | | | | | | |
                              +-+-+-+-+-+-+-+-+
                            6 | | | | | | | | |
                              +-+-+-+-+-+-+-+-+
                            7 | | | | | | | | |
                              +-+-+-+-+-+-+-+-+

                 Figure 3-1. Programmable Character Worksheet.

  112   PROGRAMMING GRAPHICS

    The Programmable Character Worksheet (Figure 3-1) will help you design
  your own characters. There is an 8 by 8 matrix on the sheet, with row
  numbers, and numbers at the top of each column. (if you view each row as
  a binary word, the numbers are the value of that bit position. Each is a
  power of 2. The leftmost bit is equal to 128 or 2 to the 7th power, the
  next is equal to 64 or 2 to the 6th, and so on, until you reach the
  rightmost bit (bit 0) which is equal to 1 or 2 to the 0 power.)
    Place an X on the matrix at every location where you want a dot to be
  in your character. When your character is ready you can create the DATA
  statement for your character.
    Begin with the first row. Wherever you placed an X, take the number at
  the top of the column (the power-of-2 number, as explained above) and
  write it down. When you have the numbers for every column of the first
  row, add them together. \Mite this number down, next to the row. This is
  the number that you will put into the DATA statement to draw this row.
    Do the same thing with all of the other rows (1-7). When you are
  finished you should have 8 numbers between 0 and 255. If any of your
  numbers are not within range, recheck your addition. The numbers must be
  in this range to be correct! If you have less than 8 numbers, you missed
  a row. It's OK if some are 0. The 0 rows are just as important as the
  other numbers.
    Replace the numbers in the DATA statement in line 20 with the numbers
  you just calculated, and RUN the program. Then type a T. Every time you
  type it, you'll see your own character!
    If you don't like the way the character turned out, just change the
  numbers in the DATA statement and re-RUN the program until you are happy
  with your character.
    That's all there is to it!

  +-----------------------------------------------------------------------+
  | HINT: For best results, always make any vertical lines in your        |
  | characters at least 2 dots (bits) wide. This helps prevent CHROMA     |
  | noise (color distortion) on your characters when they are displayed   |
  | on a TV screen.                                                       |
  +-----------------------------------------------------------------------+

                                                 PROGRAMMING GRAPHICS   113

    Here is an example of a program using standard programmable characters:

start tok64 page114.prg
  10 rem * example 1 *
  20 rem creating programmable characters
  31 poke 56334,peek(56334)and254: rem turn off kb
  32 poke 1,peek(1)and251: rem turn off i/o
  35 for i=0to63: rem character range to be copied
  36 for j=0to7: rem copy all 8 bytes per character
  37 poke 12288+I*8+j,peek(53248+i*8+j): rem copy a byte
  38 next j:next i: rem goto next byte or character
  39 poke 1,peek(1)or4:poke 56334,peek(56334)or1: rem turn on i/O and kb
  40 poke 53272,(peek(53272)and240)+12: rem set char pointer to mem. 12288
  60 for char=60to63: rem program characters 60 thru 63
  80 for byte=0to7: rem do all 8 bytes of a character
  100 read number: rem read in 1/8th of character data
  120 poke 12288+(8*char)+byte,number: rem store the data in memory
  140 next byte:next char: rem also could be next byte, char
  150 print chr$(147)tab(255)chr$(60);
  155 print chr$(61)tab(55)chr$(62)chr$(63)
  160 rem line 150 puts the newly defined characters on the screen
  170 get a$: rem wait for user to press a key
  180 if a$=""then goto170: rem if no keys were pressed, try again!
  190 poke 53272,21: rem return to normal characters
  200 data 4,6,7,5,7,7,3,3: rem data for character 60
  210 data 32,96,224,160,224,224,192,192: rem data for character 61
  220 data 7,7,7,31,31,95,143,127: rem data for character 62
  230 data 224,224,224,248,248,248,240,224: rem data for character 63
  240 end
stop tok64

  114   PROGRAMMING GRAPHICS

  MULTI-COLOR MODE GRAPHICS

    Standard high-resolution graphics give you control of very small dots
  on the screen. Each dot in character memory can have 2 possible values,
  1 for on and 0 for off. When a dot is off, the color of the screen is
  used in the space reserved for that dot. If the dot is on, the dot is
  colored with the character color you have chosen for that screen posi-
  tion. When you're using standard high-resolution graphics, all the dots
  within each 8X8 character can either have background color or foreground
  color. In some ways this limits the color resolution within that space.
  For example, problems may occur when two different colored lines cross.
    Multi-color mode gives you a solution to this problem. Each dot in
  multi-color mode can be one of 4 colors: screen color (background color
  register #0), the color in background register #1, the color in back-
  ground color register #2, or character color. The only sacrifice is in
  the horizontal resolution, because each multi-color mode dot is twice as
  wide as a high-resolution dot. This minimal loss of resolution is more
  than compensated for by the extra abilities of multi-color mode.

  MULTI-COLOR MODE BIT

    To turn on multi-color character mode, set bit 4 of the VIC-II control
  register at 53270 ($D016) to a 1 by using the following POKE:

    POKE 53270,PEEK(53270)OR 16

    To turn off multi-color character mode, set bit 4 of location 53270 to
  a 0 by the following POKE:

    POKE 53270,PEEK(53270)AND 239

    Multi-color mode is set on or off for each space on the screen, so that
  multi-color graphics can be mixed with high-resolution (hi-res) graphics.
  This is controlled by bit 3 in color memory. Color memory begins at
  location 55296 ($D800 in HEX). If the number in color memory is less than
  8 (0-7) the corresponding space on the video screen will be standard
  hi-res, in the color (0-7) you've chosen. If the number located in color
  memory is greater or equal to 8 (from 8 to 15), then that space will be
  displayed in multi-color mode.

                                                 PROGRAMMING GRAPHICS   115

    By POKEing a number into color memory, you can change the color of the
  character in that position on the screen. POKEing a number from 0 to 7
  gives the normal character colors. POKEing a number between 8 and 15 puts
  the space into multi-color mode. In other words, turning BIT 3 ON in
  color memory, sets MULTI-COLOR MODE. Turning BIT 3 OFF in color memory,
  sets the normal, HIGH-RESOLUTION mode.
    Once multi-color mode is set in a space, the bits in the character
  determine which colors are displayed for the dots. For example, here is
  a picture of the letter A, and its bit pattern:

                          IMAGE    BIT PATTERN

                            **       00011000
                           ****      00111100
                          **  **     01100110
                          ******     01111110
                          **  **     01100110
                          **  **     01100110
                          **  **     01100110
                                     00000000

    In normal or high-resolution mode, the screen color is displayed
  everywhere there is a 0 bit, and the character color is displayed where
  the bit is a 1. Multi-color mode uses the bits in pairs, like so:

                          IMAGE    BIT PATTERN

                           AABB      00011000
                           CCCC      00111100
                         AABBAABB    01100110
                         AACCCCBB    01111110
                         AABBAABB    01100110
                         AABBAABB    01100110
                         AABBAABB    01100110
                                     00000000

    In the image area above, the spaces marked AA are drawn in the
  background #1 color, the spaces marked BB use the background #2 color,
  and the spaces marked CC use the character color. The bit pairs determine
  this, according to the following chart:

  116   PROGRAMMING GRAPHICS

  +----------+--------------------------------------+---------------------+
  | BIT PAIR |          COLOR REGISTER              |       LOCATION      |
  +----------+--------------------------------------+---------------------+
  |    00    |  Background #0 color (screen color)  |   53281 ($D021)     |
  |    01    |  Background #l color                 |   53282 ($D022)     |
  |    10    |  Background #2 color                 |   53283 ($D023)     |
  |    11    |  Color specified by the              |   color RAM         |
  |          |  lower 3 bits in color memory        |                     |
  +----------+--------------------------------------+---------------------+

  Type NEW and then type this demonstration program:

start tok64 page117.prg
  100 poke 53281,1: rem set background color #0 to white
  110 poke 53282,3: rem set background color #1 to cyan
  120 poke 53282,8: rem set background color #2 to orange
  130 poke 53270,peek(53270)or16: rem turn on multicolor mode
  140 c=13*4096+8*256: rem set c to point to color memory
  150 printchr$(147)"aaaaaaaaaa"
  160 forl=0to9
  170 pokec+l,8: rem use multi black
  180 next
stop tok64

    The screen color is white, the character color is black, one color
  register is cyan (greenish blue), the other is orange. You're not really
  putting color codes in the space for character color, you're actually
  using references to the registers associated with those colors. This
  conserves memory, since 2 bits can be used to pick 16 colors (background)
  or 8 colors (character). This also makes some neat tricks possible.
  Simply changing one of the indirect registers will change every dot drawn
  in that color. Therefore everything drawn in the screen and background

                                                 PROGRAMMING GRAPHICS   117

  colors can be changed on the whole screen instantly. Here is an example
  of changing background color register #1:

start tok64 page118.prg
  100 poke53270,peek(53270)or16: rem turn on multicolor mode
  110 print chr$(147)chr$(18);
  120 print"{orange*2}";: rem type c= & 1 for orange or multicolor black bg
  130 forl=1to22:printchr$(65);:next
  135 fort=1to500:next
  140 print"{blue*2}";: rem type ctrl & 7 for blue color change
  145 fort=1to500:next
  150 print"{black}hit a key"
  160 get a$:if a$=""then160
  170 x=int(rnd(1)*16)
  180 poke 53282,x
  190 goto 160
stop tok64

    By using the <C=> key and the COLOR keys the characters can be changed
  to any color, including multi-color characters. For example, type this
  command:

    POKE 53270,PEEK(53270)OR 16:PRINT"<CTRL+3>";: rem lt.red/ multi-color
  red

    The word READY and anything else you type will be displayed in multi-
  color mode. Another color control can set you back to regular text.

  118   PROGRAMMING GRAPHICS

    Here is an example of a program using multi-color programmable
  characters:

start tok64 page119.prg
  10 rem * example 2 *
  20 rem creating multi color programmable characters
  31 poke 56334,peek(56334)and254:poke1,peek(1)and251
  35 fori=0to63:rem character range to be copied from rom
  36 forj=0to7:rem copy all 8 bytes per character
  37 poke 12288+i*8+j,peek(53248+i*8+j):rem copy a byte
  38 next j,i:rem goto next byte or character
  39 poke 1,peek(1)or4:poke 56334,peek(56334)or1:rem turn on i/o and kb
  40 poke 53272,(peek(53272)and240)+12:rem set char pointer to mem. 12288
  50 poke 53270,peek(53270)or16
  51 poke 53281,0:rem set background color #0 to black
  52 poke 53282,2:rem set background color #1 to red
  53 poke 53283,7:rem set background color #2 to yellow
  60 for char=60to63:rem program characters 60 thru 63
  80 for byte=0to7:rem do all 8 bytes of a character
  100 read number:rem read 1/8th of the character data
  120 poke 12288+(8*char)+byte,number:rem store the data in memory
  140 next byte,char
  150 print"{clear}"tab(255)chr$(60)chr$(61)tab(55)chr$(62)chr$(63)
  160 rem line 150 puts the newly defined characters on the screen
  170 get a$:rem wait for user to press a key
  180 if a$=""then170:rem if no keys were pressed, try again
  190 poke53272,21:poke53270,peek(53270)and239:rem return to normal chars
  200 data129,37,21,29,93,85,85,85: rem data for character 60
  210 data66,72,84,116,117,85,85,85: rem data for character 61
  220 data87,87,85,21,8,8,40,0: rem data for character 62
  230 data213,213,85,84,32,32,40,0: rem data for character 63
  240 end
stop tok64

                                                 PROGRAMMING GRAPHICS   119

  EXTENDED BACKGROUND COLOR MODE

    Extended background color mode gives you control over the background
  color of each individual character, as well as over the foreground color.
  For example, in this mode you could display a blue character with a
  yellow background on a white screen.
    There are 4 registers available for extended background color mode.
  Each of the registers can be set to any of the 16 colors.
    Color memory is used to hold the foreground color in extended back-
  ground mode. It is used the same as in standard character mode.
    Extended character mode places a limit on the number of different
  characters you can display, however. When extended color mode is on, only
  the first 64 characters in the character ROM (or the first 64 characters
  in your programmable character set) can be used. This is because two of
  the bits of the character code are used to select the background color.
  It might work something like this:
    The character code (the number you would POKE to the screen) of the
  letter "A" is a 1. When extended color mode is on, if you POKED a 1 to
  the screen, an "A" would appear. If you POKED a 65 to the screen
  normally, you would expect the character with character code (CHR$) 129
  to appear, which is a reversed "A." This does NOT happen in extended
  color mode. Instead you get the same unreversed "A" as before, but on a
  different background color. The following chart gives the codes:

  +------------------------+---------------------------+
  |     CHARACTER CODE     | BACKGROUND COLOR REGISTER |
  +------------------------+---------------------------+
  |  RANGE   BIT 7   BIT 6 |  NUMBER       ADDRESS     |
  +------------------------+---------------------------+
  |   0- 63   0       0    |    0       53281 ($D021)  |
  |  64-127   0       1    |    1       53282 ($D022)  |
  | 128-191   1       0    |    2       53283 ($D023)  |
  | 192-255   1       1    |    3       53284 ($D024)  |
  +------------------------+---------------------------+

    Extended color mode is turned ON by setting bit 6 of the VIC-II regis-
  ter to a 1 at location 53265 ($D011 in HEX). The following POKE does it:

    POKE 53265,PEEK(53265)OR 64

  120   PROGRAMMING GRAPHICS

    Extended color mode is turned OFF by setting bit 6 of the VIC-II regis-
  ter to a 0 at location 53265 ($D011). The following statement will do
  this:

    POKE 53265,PEEK(53265)AND 191

  BIT MAPPED GRAPHICS

    When writing games, plotting charts for business applications, or other
  types of programs, sooner or later you get to the point where you want
  high-resolution displays.
    The Commodore 64 has been designed to do just that: high resolution is
  available through bit mapping of the screen. Bit mapping is the method in
  which each possible dot (pixel) of resolution on the screen is assigned
  its own bit (location) in memory. If that memory bit is a one, the dot it
  is assigned to is on. If the bit is set to zero, the dot is off.
    High-resolution graphic design has a couple of drawbacks, which is why
  it is not used all the time. First of all, it takes lots of memory to bit
  map the entire screen. This is because every pixel must have a memory bit
  to control it. You are going to need one bit of memory for each pixel
  (or one byte for 8 pixels). Since each character is 8 by 8, and there are
  40 lines with 25 characters in each line, the resolution is 320 pixels
  (dots) by 200 pixels for the whole screen. That gives you 64000 separate
  dots, each of which requires a bit in memory. In other words, 8000 bytes
  of memory are needed to map the whole screen.
    Generally, high-resolution operations are made of many short, simple,
  repetitive routines. Unfortunately, this kind of thing is usually rather
  slow if you are trying to write high-resolution routines in BASIC. How-
  ever, short, simple, repetitive routines are exactly what machine lan-
  guage does best. The solution is to either write your programs entirely
  in machine language, or call machine language, high-resolution sub-
  routines from your BASIC program using the SYS command from BASIC. That
  way you get both the ease of writing in BASIC, and the speed of machine
  language for graphics. The VSP cartridge is also available to add high-
  resolution commands to COMMODORE 64 BASIC.
    All of the examples given in this section will be in BASIC to make them
  clear. Now to the technical details.

    BIT MAPPING is one of the most popular graphics techniques in the
  computer world. It is used to create highly detailed pictures. Basically,
  when the Commodore 64 goes into bit map mode, it directly displays an

                                                 PROGRAMMING GRAPHICS   121

  8K section of memory on the TV screen. When in bit map mode, you can
  directly control whether an individual dot on the screen is on or off.
    There are two types of bit mapping available on the Commodore 64.
  They are:

    1) Standard (high-resolution) bit mapped mode (320-dot by 200-dot
       resolution)

    2) Multi-color bit mapped mode (160-dot by 200-dot resolution)

    Each is very similar to the character type it is named for: standard
  has greater resolution, but fewer color selections. On the other hand,
  multi-color bit mapping trades horizontal resolution for a greater number
  of colors in an 8-dot by 8-dot square.

  STANDARD HIGH-RESOLUTION BIT MAP MODE

    Standard bit map mode gives you a 320 horizontal dot by 200 vertical
  dot resolution, with a choice of 2 colors in each 8-dot by 8-dot section.
  Bit map mode is selected (turned ON) by setting bit 5 of the VIC-II
  control register to a 1 at location 53265 ($D011 in HEX). The following
  POKE will do this:

    POKE 53265,PEEK(53265)OR 32

    Bit map mode is turned OFF by setting bit 5 of the VIC-II control
  register to 0 at location 53265 ($D011), like this:

    POKE 53265,PEEK(53265)AND 223

    Before we get into the details of the bit map mode, there is one more
  issue to tackle, and that is where to locate the bit map area.

  HOW IT WORKS

    If you remember the PROGRAMMABLE CHARACTERS section you will recall
  that you were able to set the bit pattern of a character stored in RAM to
  almost anything you wanted. If at the same time you change the character
  that is displayed on the screen, you would be able to change a single
  dot, and watch it happen. This is the basis of bit-mapping. The entire

  122   PROGRAMMING GRAPHICS

  screen is filled with programmable characters, and you make your changes
  directly into the memory that the programmable characters get their
  patterns from.
    Each of the locations in screen memory that were used to control what
  character was displayed, are now used for color information. For example,
  instead of POKEing a I in location 1024 to make an "A" appear in the top
  left hand corner of the screen, location 1024 now controls the colors of
  the bits in that top left space.
    Colors of squares in bit map mode do not come from color memory, as
  they do in the character modes. Instead, colors are taken from screen
  memory. The upper 4 bits of screen memory become the color of any bit
  that is set to 1 in the 8 by 8 area controlled by that screen memory
  location. The lower 4 bits become the color of any bit that is set to
  a 0.

  EXAMPLE: Type the following:

  5 BASE=2*4096:POKE53272,PEEK(53272)OR8:REM PUT BIT MAP AT 8192
  10 POKE53265,PEEK(53265)OR32:REM ENTER BIT MAP MODE

  Now RUN the program.
    Garbage appears on the screen, right? Just like the normal screen mode,
  you have to clear the HIGH-RESOLUTION (HI-RES) screen before you use it.
  Unfortunately, printing a CLR won't work in this case. Instead you have
  to clear out the section of memory that you're using for your
  programmable characters. Hit the <RUN/STOP> and <RESTORE> keys, then add
  the following lines to your program to clear the HI-RES screen:

  20 FORI=BASETOBASE+7999:POKEI,0:NEXT:REM CLEAR BIT
  30 FORI=1024TO2023:POKEI,3:NEXT:REM SET COLOR TO CYAN AND BLACK

    Now RUN the program again. You should see the screen clearing, then the
  greenish blue color, cyan, should cover the whole screen. What we want to
  do now is to turn the dots on and off on the HI-RES screen.

                                                 PROGRAMMING GRAPHICS   123

    To SET a dot (turn a dot ON) or UNSET a dot (turn a dot OFF) you must
  know how to find the correct bit in the character memory that you have to
  set to a 1. In other words, you have to find the character you need to
  change, the row of the character, and which bit of the row that you
  have to change. You need a formula to calculate this.
    We will use X and Y to stand for the horizontal and vertical positions
  of a dot, The dot where X=0 and Y=0 is at the upper-left of the display.
  Dots to the right have higher X values, and the dots toward the bottom
  have higher Y values. The best way to use bit mapping is to arrange the
  bit map display something like this:

  0. . . . . . . . . . . . . . . . . .X. . . . . . . . . . . . . . . . .319

  .                                                                      .

  .                                                                      .

  .                                                                      .

  .                                                                      .

  Y                                                                      .

  .                                                                      .

  .                                                                      .

  .                                                                      .

  .                                                                      .

  199. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

    Each dot will have an X and a Y coordinate. With this format it is easy
  to control any dot on the screen.

  124   PROGRAMMING GRAPHICS

     However, what you actually have is something like this:

  ----- BYTE 0   BYTE 8   BYTE 16    BYTE 24 ..................... BYTE 312
        BYTE 1   BYTE 9      .          .                          BYTE 313
        BYTE 2   BYTE 10     .          .                          BYTE 314
        BYTE 3   BYTE 11     .          .                          BYTE 315
        BYTE 4   BYTE 12     .          .                          BYTE 316
        BYTE 5   BYTE 13     .          .                          BYTE 317
        BYTE 6   BYTE 14     .          .                          BYTE 318
  ----- BYTE 7   BYTE 15     .          .                          BYTE 319

  ----- BYTE 320 BYTE 328 BYTE 336 BYTE 344....................... BYTE 632
        BYTE 321 BYTE 329    .          .                          BYTE 633
        BYTE 322 BYTE 330    .          .                          BYTE 634
        BYTE 323 BYTE 331    .          .                          BYTE 635
        BYTE 324 BYTE 332    .          .                          BYTE 636
        BYTE 325 BYTE 333    .          .                          BYTE 637
        BYTE 326 BYTE 334    .          .                          BYTE 638
  ----- BYTE 327 BYTE 335    .          .                          BYTE 639

    The programmable characters which make up the bit map are arranged in
  25 rows of 40 columns each. While this is a good method of organization
  for text, it makes bit mapping somewhat difficult. (There is a good
  reason for this method. See the section on MIXED MODES.)
    The following formula will make it easier to control a dot on the bit
  map screen:
    The start of the display memory area is known as the BASE, The row
  number (from 0 to 24) of your dot is:

    ROW = INT(Y/8) (There are 320 bytes per line.)

  The character position on that line (from 0 to 39) is:

    CHAR = INT(X/8) (There are 8 bytes per character.)

  The line of that character position (from 0 to 7) is:

    LINE = Y AND 7

                                                 PROGRAMMING GRAPHICS   125

  The bit of that byte is:

    BIT = 7-(X AND 7)

    Now we put these formulas together. The byte in which character memory
  dot (X,Y) is located is calculated by:

    BYTE = BASE + ROW*320+ CHAR*8 + LINE

    To turn on any bit on the grid with coordinates (X,Y), use this line:

  POKE BYTE, PEEK(BYTE) OR 2^BIT

    Let's add these calculations to the program. In the following example,
  the COMMODORE 64 will plot a sine curve:

  50 FORX=0TO319STEP.5:REM WAVE WILL FILL THE SCREEN
  60 Y=INT(90+80*SIN(X/10))
  70 CH=INT(X/8)
  80 RO=INT(Y/8)
  85 LN=YAND7
  90 BY=BASE+RO*320+8*CH+LN
  100 BI=7-(XAND7)
  110 POKEBY,PEEK(BY)OR(2^BI)
  120 NEXTX
  125 POKE1024,16
  130 GOTO130

    The calculation in line 60 will change the values for the sine function
  from a range of +1 to -1 to a range of 10 to 170. Lines 70 to 100
  calculate the character, row, byte, and bit being affected, using the
  formulae as shown above. Line 125 signals the program is finished by
  changing the color of the top left corner of the screen. Line 130 freezes
  the program by putting it into an infinite loop. When you have finished
  looking at the display, just hold down <RUN/STOP> and hit <RESTORE>.

  126   PROGRAMMING GRAPHICS

    As a further example, you can modify the sine curve program to display
  a semicircle. Here are the lines to type to make the changes:

  50 FORX=0TO160:REM DO HALF THE SCREEN
  55 Y1=100+SQR(160*X-X*X)
  56 Y2=100-SQR(160*X-X*X)
  60 FORY=Y1TOY2STEPY1-Y2
  70 CH=INT(X/()
  80 RO=INT(Y/X)
  85 LNYAND7
  90 BY=BASE+RO*320+8*CH+LN
  100 BI=7-(XAND7)
  110 POKEBY,PEEK(BY)OR(2^BI)
  114 NEXT

  This will create a semicircle in the HI-RES area of the screen.

  +-----------------------------------------------------------------------+
  | WARNING: BASIC variables can overlay your high-resolution screen. If  |
  | you need more memory space you must move the bottom of BASIC above the|
  | high-resolution screen area. Or, you must move your high-resolution   |
  | screen area. This problem will NOT occur in machine language. It ONLY |
  | happens when you're writing programs in BASIC.                        |
  +-----------------------------------------------------------------------+

  MULTI-COLOR BET MAP MODE

    Like multi-color mode characters, multi-color bit map mode allows you
  to display up to four different colors in each 8 by 8 section of bit map.
  And as in multi-character mode, there is a sacrifice of horizontal
  resolution (from 320 dots to 160 dots).
    Multi-color bit map mode uses an 8K section of memory for the bit map.
  You select your colors for multi-color bit map mode from (1) the
  background color register 0, (the screen background color), (2) the video
  matrix (the upper 4 bits give one possible color, the lower 4 bits an-
  other), and (3) color memory.
    Multi-color bit mapped mode is turned ON by setting bit 5 of 53265
  ($D011) and bit 4 at location 53270 ($D016) to a 1. The following POKE
  does this:

    POKE 53265,PEEK(53625)OR 32: POKE 53270,PEEK(53270)OR 16

                                                 PROGRAMMING GRAPHICS   127

    Multi-color bit mapped mode is turned OFF by setting bit 5 of 53265
  ($D011) and bit 4 at location 53270 ($D016) to a 0. The following POKE
  does this:

    POKE 53265,PEEK(53265)AND 223: POKE 53270,PEEK(53270)AND 239

    As in standard (HI-RES) bit mapped mode, there is a one to one cor-
  respondence between the 8K section of memory being used for the display,
  and what is shown on the screen. However, the horizontal dots are two
  bits wide. Each 2 bits in the display memory area form a dot, which can
  have one of 4 colors.

    BITS    COLOR INFORMATION COMES FROM

     00     Background color #0 (screen color)
     01     Upper 4 bits of screen memory
     10     Lower 4 bits of screen memory
     11     Color nybble (nybble = 1/2 byte = 4 bits)

  SMOOTH SCROLLING

    The VIC-II chip supports smooth scrolling in both the horizontal and
  vertical directions. Smooth scrolling is a one pixel movement of the
  entire screen in one direction. It can move either UP, or down, or left,
  or right. It is used to move new information smoothly onto the screen,
  while smoothly removing characters from the other side.
    While the VIC-II chip does much of the task for you, the actual scroll-
  ing must be done by a machine language program. The VIC-II chip features
  the ability to place the video screen in any of 8 horizontal positions,
  and 8 vertical positions. Positioning is controlled by the VIC-II
  scrolling registers. The VIC-II chip also has a 38 column mode, and a 24
  row mode. the smaller screen sizes are used to give you a place for your
  new data to scroll on from.

  The following are the steps for SMOOTH SCROLLING:

  128   PROGRAMMING GRAPHICS

  1) Shrink the screen (the border will expand).
  2) Set the scrolling register to maximum (or minimum value depending upon
     the direction of your scroll).
  3) Place the new data on the proper (covered) portion of the screen.
  4) Increment (or decrement) the scrolling register until it reaches the
     maximum (or minimum) value.
  5) At this point, use your machine language routine to shift the entire
     screen one entire character in the direction of the scroll.
  6) Go back to step 2.

    To go into 38 column mode, bit 3 of location 53270 ($D016) must be set
  to a 0. The following POKE does this:

    POKE 53270,PEEK(53270)AND 247

    To return to 40 column mode, set bit 3 of location 53270 ($D016) to a
  1.The following POKE does this:

    POKE 53270,PEEK(53270)OR 8

    To go into 24 row mode, bit 3 of location 53265 ($D011) must be set to
  a 0. The following POKE will do this:

    POKE 53265,PEEK(53265)AND 247

    To return to 25 row mode, set bit 3 of location 53265 ($D011) to a 1.
  The following POKE does this:

    POKE 53265,PEEK(53265)OR 8

    When scrolling in the X direction, it is necessary to place the VIC-II
  chip into 38 column mode. This gives new data a place to scroll from.
  When scrolling LEFT, the new data should be placed on the right. When
  scrolling RIGHT the new data should be placed on the left. Please note
  that there are still 40 columns to screen memory, but only 38 are
  visible.
    When scrolling in the Y direction, it is necessary to place the VIC-II
  chip into 24 row mode. When scrolling UP, place the new data in the LAST
  row. When scrolling DOWN, place the new data on the FIRST row. Unlike X
  scrolling, where there are covered areas on each side of the screen,
  there is only one covered area in Y scrolling. When the Y scrolling

                                                 PROGRAMMING GRAPHICS   129

  register is set to 0, the first line is covered, ready for new data. When
  the Y scrolling register is set to 7 the last row is covered.
    For scrolling in the X direction, the scroll register is located in
  bits 2 to 0 of the VIC-II control register at location 53270 ($D016 in
  HEX). As always, it is important to affect only those bits. The following
  POKE does this:

    POKE 53270,(PEEK(53270)AND 248)+X

  where X is the X position of the screen from 0 to 7.
    For scrolling in the Y direction, the scroll register is located in
  bits 2 to 0 of the VIC-II control register at location 53265 ($D011 in
  HEX). As always, it is important to affect only those bits. The following
  POKE does this:

    POKE 53265,(PEEK(53265)AND 248)+Y

  where Y is the Y position of the screen from 0 to 7.
    To scroll text onto the screen from the bottom, you would step the low-
  order 3 bits of location 53265 from 0-7, put more data on the covered
  line at the bottom of the screen, and then repeat the process. To scroll
  characters onto the screen from left to right, you would step the low-
  order 3 bits of location 53270 from 0 to 7, print or POKE another column
  of new data into column 0 of the screen, then repeat the process.
    If you step the scroll bits by -1, your text will move in the opposite
  direction.

  EXAMPLE: Text scrolling onto the bottom of the screen:

start tok64 page130.prg
  10 poke53265,peek(53265)and247        :rem go into 24 row mode
  20 printchr$(147)                     :rem clear the screen
  30 forx=1to24:printchr$(17);:next     :rem move the cursor to the bottom
  40 poke53265,(peek(53265)and248)+7:print :rem position for 1st scroll
  50 print"     hello";
  60 forp=6to0step-1
  70 poke53265,(peek(53265)and248)+p
  80 forx=1to50:next                    :rem delay loop
  90 next:goto40
stop tok64

  130   PROGRAMMING GRAPHICS

  SPRITES

    A SPRITE is a special type of user definable character which can be
  displayed anywhere on the screen. Sprites are maintained directly by the
  VIC-II chip. And all you have to do is tell a sprite "what to look like,"
  "what color to be," and "where to appear." The VIC-II chip will do the
  rest! Sprites can be any of the 16 colors available.
    Sprites can be used with ANY of the other graphics modes, bit mapped,
  character, multi-color, etc., and they'll keep their shape in all of
  them. The sprite carries its own color definition, its own mode (HI-RES
  or multi-colored), and its own shape.
    Up to 8 sprites at a time can be maintained by the VIC-II chip auto-
  matically. More sprites can be displayed using RASTER INTERRUPT
  techniques.

    The features of SPRITES include:

    1) 24 horizontal dot by 21 vertical dot size.
    2) Individual color control for each sprite.
    3) Sprite multi-color mode.
    4) Magnification (2x) in horizontal, vertical, or both directions.
    5) Selectable sprite to background priority.
    6) Fixed sprite to sprite priorities.
    7) Sprite to sprite collision detection.
    8) Sprite to background collision detection.

    These special sprite abilities make it simple to program many arcade
  style games. Because the sprites are maintained by hardware, it is even
  possible to write a good quality game in BASIC!
    There are 8 sprites supported directly by the VIC-II chip. They are
  numbered from 0 to 7. Each of the sprites has it own definition location,
  position registers and color register, and has its own bits for enable
  and collision detection.

  DEFINING A SPRITE

    Sprites are defined like programmable characters are defined. However,
  since the size of the sprite is larger, more bytes are needed. A sprite
  is 24 by 21 dots, or 504 dots. This works out to 63 bytes (504/8 bits)

                                                 PROGRAMMING GRAPHICS   131

                          [THE PICTURE IS MISSING!]

                    Figure 3-2. Sprite Definition Block.

  132   PROGRAMMING GRAPHICS

  needed to define a sprite. The 63 bytes are arranged in 21 rows of 3
  bytes each. A sprite definition looks like this.

                          BYTE 0  BYTE 1  BYTE 2
                          BYTE 3  BYTE 4  BYTE 5
                          BYTE 6  BYTE 7  BYTE 8
                            ..      ..      ..
                            ..      ..      ..
                            ..      ..      ..
                          BYTE 60 BYTE 61 BYTE 62

    Another way to view how a sprite is created is to take a look at the
  sprite definition block on the bit level. It would look something like
  Figure 3-2.
    In a standard (HI-RES) sprite, each bit set to I is displayed in that
  sprite's foreground color. Each bit set to 0 is transparent and will
  display whatever data is behind it. This is similar to a standard
  character.
    Multi-color sprites are similar to multi-color characters. Horizontal
  resolution is traded for extra color resolution. The resolution of the
  sprite becomes 12 horizontal dots by 21 vertical dots. Each dot in the
  sprite becomes twice as wide, but the number of colors displayable in the
  sprite is increased to 4.

  SPRITE POINTERS

    Even though each sprite takes only 63 bytes to define, one more byte
  is needed as a place holder at the end of each sprite. Each sprite, then,
  takes up 64 bytes. This makes it easy to calculate where in memory your
  sprite definition is, since 64 bytes is an even number and in binary it's
  an even power.
    Each of the 8 sprites has a byte associated with it called the SPRITE
  POINTER. The sprite pointers control where each sprite definition is lo-
  cated in memory. These 8 bytes are always located as the lost 8 bytes
  of the 1K chunk of screen memory. Normally, on the Commodore 64, this
  means they begin at location 2040 ($07F8 in HEX). However, if you move
  the screen, the location of your sprite pointers will also move.
    Each sprite pointer can hold a number from 0 to 255. This number points
  to the definition for that sprite. Since each sprite definition takes
  64 bytes, that means that the pointer can "see" anywhere in the 16K
  block of memory that the VIC-II chip can access (since 256*64=16K).

                                                 PROGRAMMING GRAPHICS   133

    If sprite pointer #0, at location 2040, contains the number 14, for
  example, this means that sprite 0 will be displayed using the 64 bytes
  beginning at location 14*64 = 896 which is in the cassette buffer. The
  following formula makes this clear:

    LOCATION = (BANK * 16384) + (SPRITE POINTER VALUE * 64)

  Where BANK is the 16K segment of memory that the VIC-II chip is looking
  at and is from 0 to 3.
    The above formula gives the start of the 64 bytes of the sprite
  definition block.
    When the VIC-II chip is looking at BANK 0 or BANK 2, there is a ROM
  IMAGE of the character set present in certain locations, as mentioned
  before. Sprite definitions can NOT be placed there. If for some reason
  you need more than 128 different sprite definitions, you should use one
  of the banks without the ROM IMAGE, 1 or 3.

  TURNING SPRITES ON

    The VIC-II control register at location 53269 ($D015 in HEX) is known
  as the SPRITE ENABLE register. Each of the sprites has a bit in this
  register which controls whether that sprite is ON or OFF. The register
  looks like this:

                     $D015  7 6 5 4 3 2 1 0

    To turn on sprite 1, for example, it is necessary to turn that bit to
  a 1. The following POKE does this:

    POKE 53269.PEEK(53269)OR 2

  A more general statement would be the following:

    POKE 53269,PEEK(53269)OR (2^SN)

  where SN is the sprite number, from 0 to 7.

  +-----------------------------------------------------------------------+
  | NOTE: A sprite must be turned ON before it can be seen.               |
  +-----------------------------------------------------------------------+

  134   PROGRAMMING GRAPHICS

  TURNING SPRITES OFF

    A sprite is turned off by setting its bit in the VIC-II control
  register at 53269 ($D015 in HEX) to a 0. The following POKE will do this:

    POKE 53269,PEEK(53269)AND(255-2^SN)

  where SN is the sprite number from 0 to 7.

  COLORS

    A sprite can be any of the 16 colors generated by the VIC-II chip. Each
  of the sprites has its own sprite color register. These are the memory
  locations of the color registers:

            ADDRESS         |          DESCRIPTION
  --------------------------+----------------------------------------------
        53287   ($D027)     |    SPRITE 0 COLOR REGISTER
        53288   ($D028)     |    SPRITE 1 COLOR REGISTER
        53289   ($D029)     |    SPRITE 2 COLOR REGISTER
        53290   ($D02A)     |    SPRITE 3 COLOR REGISTER
        53291   ($D02B)     |    SPRITE 4 COLOR REGISTER
        53292   ($D02C)     |    SPRITE 5 COLOR REGISTER
        53293   ($D02D)     |    SPRITE 6 COLOR REGISTER
        53294   ($D02E)     |    SPRITE 7 COLOR REGISTER

    All dots in the sprite will be displayed in the color contained in the
  sprite color register. The rest of the sprite will be transparent, and
  will show whatever is behind the sprite.

  MULTI-COLOR MODE

    Multi-color mode allows you to have up to 4 different colors in each
  sprite. However, just like other multi-color modes, horizontal resolution
  is cut in half. In other words, when you're working with sprite multi-
  color mode (like in multi-color character mode), instead of 24 dots
  across the sprite, there are 12 pairs of dots. Each pair of dots is
  called a BIT PAIR. Think of each bit pair (pair of dots) as a single dot
  in your overall sprite when it comes to choosing colors for the dots in
  your sprites. The table below gives you the bit pair values needed to

                                                 PROGRAMMING GRAPHICS   135

  turn ON each of the four colors you've chosen for your sprite:

    BIT PAIR                           DESCRIPTION
  -------------------------------------------------------------------------
      00        TRANSPARENT, SCREEN COLOR
      01        SPRITE MULTI-COLOR REGISTER #0 (53285) ($D025)
      10        SPRITE COLOR REGISTER
      11        SPRITE MULTI-COLOR REGISTER #I (53286) ($D026)
  +-----------------------------------------------------------------------+
  | NOTE: The sprite foreground color is a 10. The character foreground   |
  | is a 11.                                                              |
  +-----------------------------------------------------------------------+

  SETTING A SPRITE TO MULTI-COLOR MODE

    To switch a sprite into multi-color mode you must turn ON the VIC-II
  control register at location 53276 ($D01C). The following POKE does this:

    POKE 53276,PEEK(53276)OR(2^SN)

  where SN is the sprite number (0 to 7).
    To switch a sprite out of multi-color mode you must turn OFF the VIC-II
  control register at location 53276 ($D01C). The following POKE does this:

    POKE 53276,PEEK(53276)AND(255-2^SN)

  where SN is the sprite number (0 to 7).

  EXPANDED SPRITES

    The VIC-II chip has the ability to expand a sprite in the vertical
  direction, the horizontal direction, or both at once. When expanded, each
  dot in the sprite is twice as wide or twice as tall. Resolution doesn't
  actually increase... the sprite just gets bigger.
    To expand a sprite in the horizontal direction, the corresponding bit
  in the VIC-II control register at location 53277 ($D01D in HEX) must be
  turned ON (set to a 1). The following POKE expands a sprite in the X
  direction:

    POKE 53277,PEEK(53277)OR(2^SN)

  where SN is the sprite number from 0 to 7.

  136   PROGRAMMING GRAPHICS

    To unexpand a sprite in the horizontal direction, the corresponding bit
  in the VIC-II control register at location 53277 ($D01D in HEX) must be
  turned OFF (set to a 0). The following POKE "unexpands" a sprite in the
  X direction:

    POKE 53277,PEEK(53277)AND (255-2^SN)

  where SN is the sprite number from 0 to 7.
    To expand a sprite in the vertical direction, the corresponding bit in
  the VIC-II control register at location 53271 ($D017 in HEX) must be
  turned ON (set to a 1). The following POKE expands a sprite in the Y
  direction:

    POKE 53271,PEEK(53271)OR(2^SN)

  where SN is the sprite number from 0 to 7.

    To unexpand a sprite in the vertical direction, the corresponding bit
  in the VIC-II control register at location 53271 ($D017 in HEX) must be
  turned OFF (set to a 0). The following POKE "unexpands" a sprite in the
  Y direction:

    POKE 53271,PEEK(53271)AND (255-2^SN)

  where SN is the sprite number from 0 to 7.

  SPRITE POSITIONING

    Once you've made a sprite you want to be able to move it around the
  screen. To do this, your Commodore 64 uses three positioning registers:

    1) SPRITE X POSITION REGISTER
    2) SPRITE Y POSITION REGISTER
    3) MOST SIGNIFICANT BIT X POSITION REGISTER

    Each sprite has an X position register, a Y position register, and a
  bit in the X most significant bit register. This lets you position your
  sprites very accurately. You can place your sprite in 512 possible X
  positions and 256 possible Y positions.
    The X and Y position registers work together, in pairs, as a team. The
  locations of the X and Y registers appear in the memory map as follows:
  First is the X register for sprite 0, then the Y register for sprite 0.

                                                 PROGRAMMING GRAPHICS   137

  Next comes the X register for sprite 1, the Y register for sprite 1, and
  so on. After all 16 X and Y registers comes the most significant bit in
  the X position (X MSB) located in its own register.
    The chart below lists the locations of each sprite position register.
  You use the locations at their appropriate time through POKE statements:

  +-------------------+---------------------------------------------------+
  |     LOCATION      |                                                   |
  +---------+---------+                   DESCRIPTION                     |
  | DECIMAL |   HEX   |                                                   |
  +---------+---------+---------------------------------------------------+
  |  53248  | ($D000) |     SPRITE 0 X POSITION REGISTER                  |
  |  53249  | ($D001) |     SPRITE 0 Y POSITION REGISTER                  |
  |  53250  | ($D002) |     SPRITE 1 X POSITION REGISTER                  |
  |  53251  | ($D003) |     SPRITE 1 Y POSITION REGISTER                  |
  |  53252  | ($D004) |     SPRITE 2 X POSITION REGISTER                  |
  |  53253  | ($D005) |     SPRITE 2 Y POSITION REGISTER                  |
  |  53254  | ($D006) |     SPRITE 3 X POSITION REGISTER                  |
  |  53255  | ($D007) |     SPRITE 3 Y POSITION REGISTER                  |
  |  53256  | ($D008) |     SPRITE 4 X POSITION REGISTER                  |
  |  53257  | ($D009) |     SPRITE 4 Y POSITION REGISTER                  |
  |  53258  | ($D00A) |     SPRITE 5 X POSITION REGISTER                  |
  |  53259  | ($D00B) |     SPRITE 5 Y POSITION REGISTER                  |
  |  53260  | ($D00C) |     SPRITE 6 X POSITION REGISTER                  |
  |  53261  | ($D00D) |     SPRITE 6 Y POSITION REGISTER                  |
  |  53262  | ($D00E) |     SPRITE 7 X POSITION REGISTER                  |
  |  53263  | ($D00F) |     SPRITE 7 Y POSITION REGISTER                  |
  |  53264  | ($D010) |     SPRITE X MSB REGISTER                         |
  +---------+---------+---------------------------------------------------+

    The position of a sprite is calculated from the TOP LEFT corner of the
  24 dot by 21 dot area that your sprite can be designed in. It does NOT
  matter how many or how few dots you use to make up a sprite. Even if only
  one dot is used as a sprite, and you happen to want it in the middle of
  the screen, you must still calculate the exact positioning by starting at
  the top left corner location.

  VERTICAL POSITIONING

    Setting up positions in the horizontal direction is a little more
  difficult than vertical positioning, so we'll discuss vertical (Y)
  positioning first.

  138   PROGRAMMING GRAPHICS

    There are 200 different dot positions that can be individually pro-
  grammed onto your TV screen in the Y direction. The sprite Y position
  registers can handle numbers up to 255. This means that you have more
  than enough register locations to handle moving a sprite up and down. You
  also want to be able to smoothly move a sprite on and off the screen.
  More than 200 values are needed for this.
    The first on-screen value from the top of the screen, and in the Y
  direction for an unexpanded sprite is 30. For a sprite expanded in the Y
  direction it would be 9. (Since each dot is twice as tall, this makes a
  certain amount of sense, as the initial position is STILL calculated from
  the top left corner of the sprite.)
    The first Y value in which a sprite (expanded or not) is fully on the
  screen (all 21 possible lines displayed) is 50.
    The last Y value in which an unexpanded sprite is fully on the screen
  is 229. The last Y value in which an expanded sprite is fully on the
  screen is 208.
    The first Y value in which a sprite is fully off the screen is 250.

  EXAMPLE:

start tok64 page139.prg
  10 print"{clear}"                :rem clear screen
  20 poke 2040,13                  :rem get sprite 0 data from block 13
  30 fori=0to62:poke832+i,129:next :rem poke sprite data into block 13
  40 v=53248                       :rem set beginning of video chip
  50 pokev+21,1                    :rem enable sprite 0
  60 pokev+39,1                    :rem set sprite 0 color
  70 pokev+1,100                   :rem set sprite 0 y position
  80 pokev+16,0:pokev,100          :rem set sprite 0 x position
stop tok64

  HORIZONTAL POSITIONING

    Positioning in the horizontal direction is more complicated because
  there are more than, 256 positions. This means that an extra bit, or 9th
  bit is used to control the X position. By adding the extra bit when
  necessary a sprite now has 512 possible positions in the left/right, X,
  direction. This makes more possible combinations than can be seen on the
  visible part of the screen. Each sprite can have a position from 0 to
  511. However, only those values between 24 and 343 are visible on the
  screen. If the X position of a sprite is greater than 255 (on the right
  side of the screen), the bit in the X MOST SIGNIFICANT BIT POSITION

                                                 PROGRAMMING GRAPHICS   139

        0 ($00)  24 ($18)                     296 ($128)    344 ($158)
                                                       |    |
              |  |
              |  |                                     +----+ 8 ($08)
              |                                        |    |
     29 ($1D) |  +--+                                  |    |
              |  |  |                                  |    |
                 |  |                                  |    |
     50 ($32) +--+-------------------------------------+----+----+ 50 ($32)
              |  |  |                                  |    |    |
              |  |  |                                  |    |    |
              +--+--+                                  |    |    |
                 |                                     |    |    |
                 |                                     +----+----+
                 |                                          |
                 |           VISIBLE VIEWING AREA           |
                 |                                          |
                 |                                          |
                 |                                          |
                 |                                          |
                 |                                          |
                 |                                          |
                 |                                          |
                 |               NTSC*                      |
                 |               40 COLUMNS                 |
                 |               25 ROWS                    |
  208 ($D0) +----+----+                                     |
            |    |    |                                     |
            |    |    |                                  +--+--+ 299 ($E5)
            |    |    |                                  |  |  |
            |    |    |                                  |  |  |
  250 ($FA) +----+----+----------------------------------+--+--+ 250 ($FA)
                 |    |                                  |  |
            |    |    |                                  |  |
            |    |    |                                  +--+
            |    |    |
                 +----+                                  |  |
    488 ($1E8)
                 |                              320 ($140)  344 ($158)
                 24 ($18)

    *North American television transmission standards for your home TV.

  140   PROGRAMMING GRAPHICS

        7 ($07)  31 ($1F)                     287 ($11F)    335 ($14F)
                                                       |    |
              |  |
              |  |                                     +----+ 12 ($0C)
              |                                        |    |
     33 ($21) |  +--+                                  |    |
              |  |  |                                  |    |
                 |  |                                  |    |
     54 ($36) +--+-------------------------------------+----+----+ 54 ($36)
              |  |  |                                  |    |    |
              |  |  |                                  |    |    |
              +--+--+                                  |    |    |
                 |                                     |    |    |
                 |                                     +----+----+
                 |                                          |
                 |           VISIBLE VIEWING AREA           |
                 |                                          |
                 |                                          |
                 |                                          |
                 |                                          |
                 |                                          |
                 |                                          |
                 |                                          |
                 |               NTSC*                      |
                 |               38 COLUMNS                 |
                 |               24 ROWS                    |
  204 ($CC) +----+----+                                     |
            |    |    |                                     |
            |    |    |                                  +--+--+ 225 ($E1)
            |    |    |                                  |  |  |
            |    |    |                                  |  |  |
  246 ($F6) +----+----+----------------------------------+--+--+ 246 ($F6)
                 |    |                                  |  |
            |    |    |                                  |  |
            |    |    |                                  +--+
            |    |    |
                 +----+                                  |  |
    480 ($1E0)
                 |                              311 ($137)  335 ($14F)
                 31 ($1F)

    *North American television transmission standards for your home TV.

                                                 PROGRAMMING GRAPHICS   141

  register must be set to a 1 (turned ON). If the X position of a sprite is
  less than 256 (on the left side of the screen), then the X MSB of that
  sprite must be 0 (turned OFF). Bits 0 to 7 of the X MSB register
  correspond to sprites 0 to 7, respectively.
    The following program moves a sprite across the screen:

  EXAMPLE:

start tok64 p142_1.prg
  10 print"{clear}"
  20 poke2040,13
  30 fori=0to62:poke832+i,129:next
  40 v=53248
  50 pokev+21,1
  60 pokev+39,1
  70 pokev+1,100
  80 forj=0to347
  90 hx=int(j/256):lx=j-256*hx
  100 pokev,lx:pokev+16,hx:next
stop tok64

    When moving expanded sprites onto the left side of the screen in the
  X direction, you have to start the sprite OFF SCREEN on the RIGHT SIDE.
  This is because an expanded sprite is larger than the amount of space
  available on the left side of the screen.

  EXAMPLE:

start tok64 p142_2.prg
  10 print"{clear}"
  20 poke2040,13
  30 fori=0to62:poke832+i,129:next
  40 v=53248
  50 pokev+21,1
  60 pokev+39,1:pokev+23,1:pokev+29,1
  70 pokev+1,100
  80 j=488
  90 hx=int(j/256):lx=j-256*hx
  100 pokev,lx:pokev+16,hx
  110 j=j+1:ifj>511thenj=0
  120 ifj>488orj<348goto90
stop tok64

  142   PROGRAMMING GRAPHICS

  The charts in Figure 3-3 explain sprite positioning.
    By using these values, you can position each sprite anywhere. By moving
  the sprite a single dot position at a time, very smooth movement is easy
  to achieve.

  SPRITE POSITIONING SUMMARY

    Unexpanded sprites are at least partially visible in the 40 column, by
  25 row mode within the following parameters:

                            1 < X < 343

                           30 < Y < 249

  In the 38 column mode, the X parameters change to she following:

                           8 <= X <= 334

  In the 24 row mode, the Y parameters change to the following:

                          34 <= Y <= 245

    Expanded sprites are at least partially visible in the 40 column, by 25
  row mode within the following parameters:

                         489 >= X <= 343
                           9 >= Y <= 249

  In the 38 column mode, the X parameters change to the following:

                         496 >= X <= 334

  In the 24 row mode, the Y parameters change to the following:

                          13 <= Y <= 245

                                                 PROGRAMMING GRAPHICS   143

  SPRITE DISPLAY PRIORITIES

    Sprites have the ability to cross each other's paths, as well as cross
  in front of, or behind other objects on the screen. This can give you a
  truly three dimensional effect for games.
    Sprite to sprite priority is fixed. That means that sprite 0 has the
  highest priority, sprite 1 has the next priority, and so on, until we get
  to sprite 7, which has the lowest priority. In other words, if sprite 1
  and sprite 6 are positioned so that they cross each other, sprite 1 will
  be in front of sprite 6.
    So when you're planning which sprites will appear to be in the fore-
  ground of the picture, they must be assigned lower sprite numbers than
  those sprites you want to put towards the back of the scene. Those
  sprites will be given higher sprite numbers,

  +-----------------------------------------------------------------------+
  | NOTE: A "window" effect is possible. If a sprite with higher priority |
  | has "holes" in it (areas where the dots are not set to 1 and thus     |
  | turned ON), the sprite with the lower priority will show through. This|
  | also happens with sprite and background data.                         |
  +-----------------------------------------------------------------------+

    Sprite to background priority is controllable by the SPRITE-BACK-
  GROUND priority register located at 53275 ($D01B). Each sprite has a bit
  in this register. If that bit is 0, that sprite has a higher priority
  than the background on the screen. In other words, the sprite appears in
  front of background data. If that bit is a 1, that sprite has a lower
  priority than the background. Then the sprite appears behind the back-
  ground data.

  COLLISION DETECTS

    One of the more interesting aspects of the VIC-II chip is its collision
  detection abilities. Collisions can be detected between sprites, or be-
  tween sprites and background data. A collision occurs when a non-zero
  part of a sprite overlaps a non-zero portion of another sprite or char-
  acters on the screen.

  144   PROGRAMMING GRAPHICS

  SPRITE TO SPRITE COLLISIONS

    Sprite to sprite collisions are recognized by the computer, or flagged,
  in the sprite to sprite collision register at location 53278 ($D01E in
  HEX) in the VIC-II chip control register. Each sprite has a bit in this
  register. If that bit is a 1, then that sprite is involved in a
  collision. The bits in this register will remain set until read (PEEKed).
  Once read, the register is automatically cleared, so it is a good idea to
  save the value in a variable until you are finished with it.

  +-----------------------------------------------------------------------+
  | NOTE: Collisions can take place even when the sprites are off screen. |
  +-----------------------------------------------------------------------+

  SPRITE TO DATA COLLISIONS

    Sprite to data collisions are detected in the sprite to data collision
  register at location 53279 ($D01F in HEX) of the VIC-II chip control
  register.
    Each sprite has a bit in this register. If that bit is a 1 , then that
  sprite is involved in a collision. The bits in this register remain set
  until read (PEEKed). Once read, the register is automatically cleared, so
  it is a good idea to save the value in a variable until you are finished
  with it.

  +-----------------------------------------------------------------------+
  | NOTE: MULTI-COLOR data 01 is considered transparent for collisions,   |
  | even though it shows up on the screen. When setting up a background   |
  | screen, it is a good idea to make everything that should not cause a  |
  | collision 01 in multi-color mode.                                     |
  +-----------------------------------------------------------------------+

                                                 PROGRAMMING GRAPHICS   145

start tok64 page146.prg
  10 rem sprite example 1... the hot air balloon
  30 vic=13*4096:rem this is where the vic registers begin
  35 pokevic+21,1:rem enable sprite 0
  36 pokevic+33,14:rem set background color to light blue
  37 pokevic+23,1:rem expand sprite 0 in y
  38 pokevic+29,1:rem expand sprite 0 in x
  40 poke2040,192:rem set sprite 0's pointer
  180 pokevic+0,100:rem set sprite 0's x position
  190 pokevic+1,100:rem set sprite 0's y position
  220 pokevic+39,1:rem set sprite 0's color
  250 fory=0to63:rem byte counter with sprite loop
  300 reada:rem read in a byte
  310 poke192*64+y,a:rem store the data in sprite area
  320 nexty:rem close loop
  330 dx=1:dy=1
  340 x=peek(vic):rem look at sprite 0's x position
  350 y=peek(vic+1):rem look at sprite 0's y position
  360 ify=50ory=208thendy=-dy:rem if y is on the edge of the...
  370 rem screen, then reverse delta y
  380 ifx=24and(peek(vic+16)and1)=0thendx=-dx:rem if sprite is touching...
  390 rem the left edge(x=24 and the msb for sprite 0 is 0), reverse it
  400 ifx=40and(peek(vic+16)and1)=1thendx=-dx:rem if sprite is touching...
  410 rem the right edge (x=40 and the msb for sprite 0 is 1), reverse it
  420 ifx=255anddx=1thenx=-1:side=1
  430 rem switch to other side of the screen
  440 ifx=0anddx=-1thenx=256:side=0
  450 rem switch to other side of the screen
  460 x=x+dx:rem add delta x to x
  470 x=xand255:rem make sure x is in allowed range
  480 y=y+dy:rem add delta y to y
  485 pokevic+16,side
  490 pokevic,x:rem put new x value into sprite 0's x position
  510 pokevic+1,y:rem put new y value into sprite 0's y position
  530 goto340
  600 rem ***** sprite data *****
  610 data0,127,0,1,255,192,3,255,224,3,231,224
  620 data7,217,240,7,223,240,7,217,240,3,231,224
  630 data3,255,224,3,255,224,2,255,160,1,127,64
  640 data1,62,64,0,156,128,0,156,128,0,73,0,0,73,0
  650 data0,62,0,0,62,0,0,62,0,0,28,0,0
stop tok64

  146   PROGRAMMING GRAPHICS

start tok64 page147.prg
  10 rem sprite example 2...
  20 rem the hot air balloon again
  30 vic=13*4096:rem this is where the vic registers begin
  35 pokevic+21,63:rem enable sprites 0 thru 5
  36 pokevic+33,14:rem set background color to light blue
  37 pokevic+23,3:rem expand sprites 0 and 1 in y
  38 pokevic+29,3:rem expand sprites 0 and 1 in x
  40 poke2040,192:rem set sprite 0's pointer
  50 poke2041,193:rem set sprite 1's pointer
  60 poke2042,192:rem set sprite 2's pointer
  70 poke2043,193:rem set sprite 3's pointer
  80 poke2044,192:rem set sprite 4's pointer
  90 poke2045,193:rem set sprite 5's pointer
  100 pokevic+4,30:rem set sprite 2's x position
  110 pokevic+5,58:rem set sprite 2's y position
  120 pokevic+6,65:rem set sprite 3's x position
  130 pokevic+7,58:rem set sprite 3's y position
  140 pokevic+8,100:rem set sprite 4's x position
  150 pokevic+9,58:rem set sprite 4's y position
  160 pokevic+10,100:rem set sprite 5's x position
  170 pokevic+11,58:rem set sprite 5's y position
  175 print"{white}{clear}"tab(15)"this is two hires sprites";
  176 printtab(55)"on top of each other"
  180 pokevic+0,100:rem set sprite 0's x position
  190 pokevic+1,100:rem set sprite 0's y position
  200 pokevic+2,100:rem set sprite 1's x position
  210 pokevic+3,100:rem set sprite 1's y position
  220 pokevic+39,1:rem set sprite 0's color
  230 pokevic+41,1:rem set sprite 2's color
  240 pokevic+43,1:rem set sprite 4's color
  250 pokevic+40,6:rem set sprite 1's color
  260 pokevic+42,6:rem set sprite 3's color
  270 pokevic+44,6:rem set sprite 5's color
  280 forx=192to193:rem the start of the loop that defines the sprites
  290 fory=0to63:rem byte counter with sprite loop
  300 reada:rem read in a byte
  310 pokex*64+y,a:rem store the data in sprite area
  320 nexty,x:rem close loops
  330 dx=1:dy=1
  340 x=peek(vic):rem look at sprite 0's x position
  350 ify=50ory=208thendy=-dy:rem if y is on the edge of the...

  370 rem screen, then reverse delta y
  380 ifx=24and(peek(vic+16)and1)=0thendx=-dx:rem if sprite is...
  390 rem touching the left edge, then reverse it
  400 ifx=40and(peek(vic+16)and1)=1thendx=-dx:rem if sprite is...
  410 rem touching the right edge, then reverse it
  420 ifx=255anddx=1thenx=-1:side=3
  430 rem switch to other side of the screen
  440 ifx=0anddx=-1thenx=256:side=0
  450 rem switch to other side of the screen
  460 x=x+dx:rem add delta x to x
  470 x=xand255:rem make sure x is in allowed range
  480 y=y+dy:rem add delta y to y
  485 pokevic+16,side
  490 pokevic,x:rem put new x value into sprite 0's x position
  500 pokevic+2,x:rem put new x value into sprite 1's x position
  510 pokevic+1,y:rem put new y value into sprite 0's y position
  520 pokevic+3,y:rem put new y value into sprite 1's y position
  530 goto340
  600 rem ***** sprite data *****
  610 data0,255,0,3,153,192,7,24,224,7,56,224,14,126,112,14,126,112,14,126
  620 data112,6,126,96,7,56,224,7,56,224,1,56,128,0,153,0,0,90,0,0,56,0
  630 data0,56,0,0,0,0,0,0,0,0,126,0,0,42,0,0,84,0,0,40,0,0
  640 data0,0,0,0,102,0,0,231,0,0,195,0,1,129,128,1,129,128,1,129,128
  650 data1,129,128,0,195,0,0,195,0,4,195,32,2,102,64,2,36,64,1,0,128
  660 data1,0,128,0,153,0,0,153,0,0,0,0,0,84,0,0,42,0,0,20,0,0
stop tok64

start tok64 page148.prg
  10 rem sprite example 3...
  20 rem the hot air gorf
  30 vic=53248:rem this is where the vic registers begin
  35 pokevic+21,1:rem enable sprite 0
  36 pokevic+33,14:rem set background color to light blue
  37 pokevic+23,1:rem expand sprite 0 in y
  38 pokevic+29,1:rem expand sprite 0 in x

  40 poke2040,192:rem set sprite 0's pointer
  50 pokevic+28,1:rem turn on multicolor
  60 pokevic+37,7:rem set multicolor 0
  70 pokevic+38,4:rem set multicolor 1
  180 pokevic+0,100:rem set sprite 0's x position
  190 pokevic+1,100:rem set sprite 0's y position
  220 pokevic+39,2:rem set sprite 0's color
  290 fory=0to63:rem byte counter with sprite loop
  300 reada:rem read in a byte
  310 poke12288+y,a:rem store the data in sprite area
  320 next y:rem close loop
  330 dx=1:dy=1
  340 x=peek(vic):rem look at sprite 0's x position
  350 y=peek(vic+1):rem look at sprite 0's y position
  360 ify=50ory=208then dy=-dy:rem if y is on the edge of the...
  370 rem screen, then reverse delta y
  380 ifx=24and(peek(vic+16)and1)=0thendx=-dx:rem if sprite is...
  390 rem touching the left edge, then reverse it
  400 ifx=40and(peek(vic+16)and1)=1thendx=-dx:rem if sprite is...
  410 rem touching the right edge, then reverse it
  420 ifx=255anddx=1thenx=-1:side=1
  430 rem switch to other side of the screen
  440 ifx=0anddx=-1thenx=256:side=0
  450 rem switch to other side of the screen
  460 x=x+dx:rem add delta x to x
  470 x=xand255:rem make sure that x is in allowed range
  480 y=y+dy:rem add delta y to y
  485 pokevic+16,side
  490 pokevic,x:rem put new x value into sprite 0's x position
  510 pokevic+1,y:rem put new y value into sprite 0's y position
  520 geta$:rem get a key from the keyboard
  521 ifa$="m"thenpokevic+28,1:rem user selected multicolor
  522 ifa$="h"thenpokevic+28,0:rem user selected high resolution
  530 goto340
  600 rem ***** sprite data *****
  610 data64,0,1,16,170,4,6,170,144,10,170,160,42,170,168,41,105,104,169
  620 data235,106,169,235,106,169,235,106,170,170,170,170,170,170,170,170
  630 data170,170,170,170,166,170,154,169,85,106,170,85,170,42,170,168,10
  640 data170,160,1,0,64,1,0,64,5,0,80,0
stop tok64

                                                 PROGRAMMING GRAPHICS   149

  OTHER GRAPHICS FEATURES

  SCREEN BLANKING

    Bit 4 of the VIC-II control register controls the screen blanking func-
  tion. It is found in the control register at location 53265 ($D011). When
  it is turned ON (in other words, set to a 1) the screen is normal. When
  bit 4 is set to 0 (turned OFF), the entire screen changes to border
  color.
    The following POKE blanks the screen. No data is lost, it just isn't
  displayed.

    POKE 53265,PEEK(53265)AND 239

  To bring back the screen. use the POKE shown below:

    POKE 53265,PEEK(53265)OR 16
  +-----------------------------------------------------------------------+
  | NOTE: Turning off the screen will speed up the processor slightly.    |
  | This means that program RUNning is also sped up.                     |
  +-----------------------------------------------------------------------+

  RASTER REGISTER

    The raster register is found in the VIC-II chip at location 53266
  ($D012). The raster register is a dual purpose register. When you read
  this register it returns the lower 8 bits of the current raster position.
  The raster position of the most significant bit is in register location
  53265 ($D011). You use the raster register to set up timing changes in
  your display so that you can get rid of screen flicker. The changes on
  your screen should be mode when the raster is not in the visible display
  area, which is when your dot positions fall between 51 and 251.
    When the raster register is written to (including the MSB) the number
  written to is saved for use with the raster compare function. When the
  actual raster value becomes the same as the number written to the raster
  register, a bit in the VIC-II chip interrupt register 53273 ($D019) is
  turned ON by setting it to 1.

  +-----------------------------------------------------------------------+
  | NOTE: If the proper interrupt bit is enabled (turned on), an interrupt|
  | (IRQ) will occur.                                                     |
  +-----------------------------------------------------------------------+

  150   PROGRAMMING GRAPHICS

  INTERRUPT STATUS REGISTER

    The interrupt status register shows the current status of any interrupt
  source. The current status of bit 2 of the interrupt register will be a 1
  when two sprites hit each other. The same is true, in a corresponding 1
  to 1 relationship, for bits 0-3 listed in the chart below. Bit 7 is also
  set with a 1, whenever an interrupt occurs.
    The interrupt status register is located at 53273 ($D019) and is as
  follows:

    LATCH  BIT#             DESCRIPTION
  -------------------------------------------------------------------------
    IRST    0   Set when current raster count = stored raster count
    IMDC    1   Set by SPRITE-DATA collision (1st one only, until reset)
    IMMC    2   Set by SPRITE-SPRITE collision (1st one only, until reset)
     ILP    3   Set by negative transition of light pen (1 per frame)
     IRQ    7   Set by latch set and enabled
  -------------------------------------------------------------------------
    Once an interrupt bit has been set, it's "latched" in and must be
  cleared by writing a 1 to that bit in the interrupt register when you're
  ready to handle it. This allows selective interrupt handling, without
  having to store the other interrupt bits.
    The INTERRUPT ENABLE REGISTER is located at 53274 ($D01A). It has the
  same format as the interrupt status register. Unless the corresponding
  bit in the interrupt enable register is set to a 1, no interrupt from
  that source will take place. The interrupt status register can still be
  polled for information, but no interrupts will be generated.
    To enable an interrupt request the corresponding interrupt enable bit
  (as shown in the chart above) must be set to a 1.
    This powerful interrupt structure lets you use split screen modes. For
  instance you can have half of the screen bit mapped, half text, more than
  8 sprites at a time, etc. The secret is to use interrupts properly. For
  example, if you want the top half of the screen to be bit mapped and the
  bottom to be text, just set the raster compare register (as explained
  previously) for halfway down the screen. When the interrupt occurs, tell
  the VIC-II chip to get characters from ROM, then set the raster compare
  register to interrupt at the top of the screen. When the interrupt occurs
  at the top of the screen, tell the VIC-II chip to get characters from RAM
  (bit map mode).
    You can also display more than 8 sprites in the same way. Unfortunately
  BASIC isn't fast enough to do this very well. So if you want to start
  using display interrupts, you should work in machine language.

                                                 PROGRAMMING GRAPHICS   151

  SUGGESTED SCREEN AND CHARACTER COLOR COMBINATIONS

    Color TV sets are limited in their ability to place certain colors next
  to each other on the same line. Certain combinations of screen and char-
  acter colors produce blurred images. This chart shows which color com-
  binations to avoid, and which work especially well together.

                          CHARACTER COLOR
            0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
         0| x| o| x| o| o| /| x| o| o| x| o| o| o| o| o| o|
          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
         1| o| x| o| x| o| o| o| x| /| o| /| o| o| x| o| o|
          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
         2| x| o| x| x| /| x| x| o| o| x| o| x| x| x| x| /|
          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
         3| o| x| x| x| x| /| o| x| x| x| x| /| x| x| /| x|
          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
         4| o| /| x| x| x| x| x| x| x| x| x| x| x| x| x| /|
          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
         5| o| /| x| /| x| x| x| x| x| x| x| /| x| o| x| /|
          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  SCREEN 6| /| o| x| o| x| x| x| x| x| x| x| x| x| /| o| o|
  COLOR   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
         7| o| x| o| x| x| x| /| x| /| o| /| o| o| x| x| x|
          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
         8| /| o| o| x| x| x| x| o| x| o| x| x| x| x| x| /|
          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
         9| x| o| x| x| x| x| x| o| o| x| o| x| x| x| x| o|
          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        10| /| /| o| x| x| x| x| /| x| o| x| x| x| x| x| /|   o = EXCELLENT
          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        11| o| o| x| /| x| x| x| o| x| x| x| x| o| o| /| o|   / = FAIR
          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        12| o| o| /| x| x| x| /| x| x| /| x| o| x| x| x| o|   x = POOR
          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        13| o| x| x| x| x| o| /| x| x| x| x| o| x| x| x| x|
          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        14| o| o| x| o| x| x| o| x| x| x| x| /| x| x| x| /|
          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        15| o| o| o| x| /| /| o| x| x| /| /| o| o| x| /| x|
          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

  152   PROGRAMMING GRAPHICS

  PROGRAMMING SPRITES - ANOTHER LOOK

    For those of you having trouble with graphics, this section has been
  designed as a more elementary tutorial approach to sprites.

  MAKING SPRITES IN BASIC - A SHORT PROGRAM

    There are at least three different BASIC programming techniques which
  let you create graphic images and cartoon animations on the Commodore 64.
  You can use the computer's built-in graphics character set (see Page
  376). You can program your own characters (see Page 108) or... best of
  all... you can use the computer's built-in "sprite graphics. To
  illustrate how easy it is, here's one of the shortest spritemaking
  programs you can write in BASIC:

start tok64 page153.prg
  10 print"{clear}"
  20 poke2040,13
  30 fors=832to832+62:pokes,255:next
  40 v=53248
  50 pokev+21,1
  60 pokev+39,1
  70 pokev,24
  80 pokev+1,100
stop tok64

    This program includes the key "ingredients" you need to create any
  sprite. The POKE numbers come from the SPRITEMAKING CHART on Page 176.
  This program defines the first sprite... sprite 0... as a solid white
  square on the screen. Here's a line-by-line explanation of the program:

    LINE 10 clears the screen.

    LINE 20 sets the "sprite pointer" to where the Commodore 64 will read
  its sprite data from. Sprite 0 is set at 2040, sprite 1 at 2041, sprite
  2 at 2042, and so on up to sprite 7 at 2047. You can set all 8 sprite
  pointers to 13 by using this line in place of line 20:

    20 FOR SP=2040TO2047:POKE SP,13:NEXT SP

    LINE 30 puts the first sprite (sprite 0) into 63 bytes of the Commodore
  64's RAM memory starting at location 832 (each sprite requires 63 bytes

                                                 PROGRAMMING GRAPHICS   153

  of memory). The first sprite (sprite 0) is "addressed" at memory
  locations 832 to 894.

    LINE 40 sets the variable "V" equal to 53248, the starting address of
  the VIDEO CHIP. This entry lets us use the form (V+number) for sprite
  settings. 're using the form (V+number) when POKEing sprite settings
  because this format conserves memory and lets us work with smaller
  numbers. For example, in line 50 we typed POKE V+21. This is the same as
  typing POKE 53248+21 or POKE 53269... but V+21 requires less space than
  53269, and is easier to remember.

    LINE 50 enables or "turns on" sprite 0. There are 8 sprites, numbered
  from 0 to 7. To turn on an individual sprite, or a combination of
  sprites, all you have to do is POKE V+21 followed by a number from 0
  (turn all sprites off) to 255 (turn all 8 sprites on). You can turn on
  one or more sprites by POKEing the following numbers:
  +------+------+------+------+------+------+------+------+------+-------+
  |ALL ON|SPRT 0|SPRT 1|SPRT 2|SPRT 3|SPRT 4|SPRT 5|SPRT 6|SPRT 7|ALL OFF|
  |  255 |   1  |   2  |   4  |   8  |  16  |  32  |  64  |  128 |   0   |
  +------+------+------+------+------+------+------+------+------+-------+

    POKE V+21,1 turns on sprite 0. POKE V+21,128 turns on sprite 7. You
  can also turn on combinations of sprites. For example, POKE V+21,129
  turns on both sprite 0 and sprite 7 by adding the two "turn on" numbers
  (1+128) together. (See SPRITEMAKING CHART, Page 176.)

    LINE 60 sets the COLOR of sprite 0. There are 16 possible sprite
  colors, numbered from 0 (black) to 15 (grey). Each sprite requires a
  different POKE to set its color, from V+39 to V+46. POKE V+39,1 colors
  sprite 0 white. POKE V+46,15 colors sprite 7 grey. (See the SPRITEMAKING
  CHART for more information.)
    When you create a sprite, as you just did, the sprite will STAY IN
  MEMORY until you POKE it off, redefine it, or turn off your computer.
  This lets you change the color, position and even shape of the sprite in
  DIRECT or IMMEDIATE mode, which is useful for editing purposes. As an
  example, RUN the program above, then type this line in DIRECT mode
  (without a line number) and hit the <RETURN> key:

    POKE V+39,8

    The sprite on the screen is now ORANGE. Try POKEing some other numbers
  from 0 to 15 to see the other sprite colors. Because you did this in

  154   PROGRAMMING GRAPHICS

  DIRECT mode, if you RUN your program the sprite will return to its origi-
  nal color (white).

    LINE 70, determines the HORIZONTAL or "X" POSITION of the sprite on the
  screen. This number represents the location of the UPPER LEFT CORNER of
  the sprite. The farthest left horizontal (X) position which you can see
  on your television screen is position number 24, although you can move
  the sprite OFF THE SCREEN to position number 0.

    LINE 80 determines the VERTICAL or "Y" POSITION of the sprite. In this
  program, we placed the sprite at X (horizontal) position 24, and Y
  (vertical) position 100. To try another location, type this POKE in
  DIRECT mode and hit <RETURN>:

    POKE V,24:POKE V+1,50

    This places the sprite at the upper left corner of the screen. To move
  the sprite to the lower left corner, type this:

    POKE V,24:POKE V+1,229

    Each number from 832 to 895 in our sprite 0 address represents one
  block of 8 pixels, with three 8-pixel blocks in each horizontal row of
  the sprite. The loop in line 80 tells the computer to POKE 832,255 which
  makes the first 8 pixels solid . . . then POKE 833,255 to make the second
  8 pixels solid, and so on to location 894 which is the last group of 8
  pixels in the bottom right corner of the sprite. To better see how this
  works, try typing the following in DIRECT r-node, and notice that the
  second group of 8 pixels is erased:

    POKE 833,0 (to put it back type POKE 833,255 or RUN your program)

    The following line, which you can add to your program. erases the
  blocks in the MIDDLE of the sprite you created:

    90 FOR A=836 TO 891 STEP 3:POKE A,O:NEXT A

    Remember, the pixels that make up the sprite are grouped in blocks of
  eight. This line erases the 5th group of eight pixels (block 836) and
  every third block up to block 890. Try POKEing any of the other numbers
  from 832 to 894 with either a 255 to make them solid or 0 to make them
  blank.

                                                 PROGRAMMING GRAPHICS   155

  +-----------------------------------------------------------------------+
  | CRUNCHING YOUR SPRITE PROGRAMS                                        |
  |                                                                       |
  | Here's a helpful "crunching" tip: The program described above is      |
  | already short, but it can be made even shorter by "crunching" it      |
  | smaller. In our example we list the key sprite settings on separate   |
  | program lines so you can see what's happening in the program. In      |
  | actual practice, a good programmer would probably write this program  |
  | as a TWO LINE PROGRAM... by "crunching" it as follows:                |
  |                                                                       |
  | 10 PRINTCHR$(147):V=53248:POKEV+21,1:POKE2040.13:POKEV+39,1           |
  | 20 FORS=832TO894:POKES,255:NEXT:POKEV,24:POKEV+1,100                  |
  |                                                                       |
  | For more tips on how to crunch your programs so they fit in less      |
  | memory and run more efficiently, see the "crunching guide" on Page 24.|
  +-----------------------------------------------------------------------+

                                  TV SCREEN
            +---------------------------------------------------+
            |        ^                                          |
            |        |                                          |
            |<-------+---- X POSITION = HORIZONTAL ------------>|
            |        |                                          |
            |        |                                          |
            |        |                                          |
            |        |                                          |
            |        |                                          |
            |        |                          +-+             |
            |        |                          | |             |
            |        |                          +-+             |
            |        |                          /               |
            |        |                         /                |
            |        |                        /                 |
            |        |                       /                  |
            +-------------------------------/-------------------+
                                           /
    A sprite located here must have both its X-position (horizontal) and
    Y-position (vertical) set so it can be displayed on the screen.

  Figure 3-4. The display screen is divided into a grid of X and Y coor-
  dinates.

  156   PROGRAMMING GRAPHICS

  POSITIONING SPRITES ON THE SCREEN

    The entire display screen is divided into a grid of X and Y coordi-
  nates, like a graph. The X COORDINATE is the HORIZONTAL position across
  the screen and the Y COORDINATE is the VERTICAL position up and down (see
  Figure 3-4).
    To position any sprite on the screen, you must POKE TWO SETTINGS...
  the X position and the Y position... these tell the computer where to
  display the UPPER LEFT HAND CORNER of the sprite. Remember that a sprite
  consists of 504 individual pixels, 24 across by 21 down... so if you POKE
  a sprite onto the upper left corner of your screen, the sprite will be
  displayed as a graphic image 24 pixels ACROSS and 21 pixels DOWN starting
  at the X-Y position you defined. The sprite will be displayed based on
  the upper left corner of the entire sprite, even if you define the sprite
  using only a small part of the 24X21-pixel sprite area.
    To understand how X-Y positioning works, study the following diagram
  (Figure 3-5), which shows the X and Y numbers in relation to your display
  screen. Note that the GREY AREA in the diagram shows your television
  viewing area... the white area represents positions which are OFF your
  viewing screen...

                         [THE PICTURE IS MISSING!]

                                                 PROGRAMMING GRAPHICS   157

    To display a sprite in a given location, You must POKE the X and Y
  settings for each SPRITE... remembering that every sprite has its own
  unique X POKE and Y POKE. The X and Y settings for ail 8 sprites are
  shown here:

  POKE THESE VALUES TO SET X-Y SPRITE POSITIONS

  +------+-------+-------+-------+-------+-------+-------+-------+--------+
  |      |SPRT 0 |SPRT 1 |SPRT 2 |SPRT 3 |SPRT 4 |SPRT 5 |SPRT 6 |SPRT 7  |
  +------+-------+-------+-------+-------+-------+-------+-------+--------+
  |SET X |V,X    |V+2,X  |V+4,X  |V+6,X  |V+8,X  |V+10,X |V+12,X |V+14,X  |
  |SET Y |V+1,Y  |V+3,Y  |V+5,Y  |V+7,Y  |V+9,Y  |V+11,Y |V+13,Y |V+15,Y  |
  |RIGHTX|V+16,1 |V+16,2 |V+16,4 |V+16,8 |V+16,16|V+16,32|V+16,64|V+16,128|
  +------+-------+-------+-------+-------+-------+-------+-------+--------+

    POKEING AN X POSITION: The possible values of X are 0 to 255, counting
  from left to right. Values 0 to 23 place all or part of the sprite OUT OF
  THE VIEWING AREA off the left side of the screen... values 24 to 255
  place the sprite IN THE VIEWING AREA up to the 255th position (see next
  paragraph for settings beyond the 255th X position). To place the sprite
  at one of these positions, just type the X-POSITION POKE for the sprite
  you're using. For example, to POKE sprite I at the farthest left X
  position IN THE VIEWING AREA, type: POKE V+2,24.

    X VALUES BEYOND THE 255TH POSITION: To get beyond the 255th position
  across the screen, you need to make a SECOND POKE using the numbers in
  the "RIGHT X" row of the chart (Figure 3-5). Normally, the horizontal (X)
  numbering would continue past the 255th position to 256, 257, etc., but
  because registers only contain 8 bits we must use a "second register" to
  access the RIGHT SIDE of the screen and start our X numbering over again
  at 0. So to get beyond X position 255, you must POKE V+16 and a number
  (depending on the sprite). This gives you 65 additional X positions
  (renumbered from 0 to 65) in the viewing area on the RIGHT side of the
  viewing screen. (You can actually POKE the right side X value as high as
  255, which takes you off the right edge of the viewing screen.)

    POKEING A Y POSITION: The possible values of Y are 0 to 255, counting
  from top to bottom. Values 0 to 49 place all or part of the sprite OUT
  OF THE VIEWING AREA off the TOP of the screen. Values 50 to 229 place the
  sprite IN THE VIEWING AREA. Values 230 to 255 place all or part of the
  sprite OUT OF THE VIEWING AREA off the BOTTOM of the screen.

  158   PROGRAMMING GRAPHICS

    Let's see how this X-Y positioning works, using sprite 1. Type this
  program:
start tok64 page159.prg
  10 print"{clear}":v=53248:pokev+21,2:poke2041,13
  20 fors=832to895:pokes,255:next:pokev+40,7
  30 pokev+2,24
  40 pokev+3,50
stop tok64

  This simple program establishes sprite 1 as a solid box and positions it
  at the upper left corner of the screen. Now change line 40 to read:

    40 POKE V+3,229

  This moves the sprite to the bottom left corner of the screen. Now let's
  test the RIGHT X LIMIT of the sprite. Change line 30 as shown:

    30 POKE V+2,255

  This moves the sprite to the RIGHT but reaches the RIGHT X LIMIT, which
  is 255. At this point, the "most significant bit" in register 16 must be
  SET. In other words, you must type POKE V+ 16 and the number shown in the
  "RIGHT X" column in the X-Y POKE CHART above to RESTART the X position
  counter at the 256th pixel/position on the screen. Change line 30 as
  follows:

    30 POKE V+16,PEEK(V+16)OR 2:POKE V+2,0

  POKE V+16,2 sets the most significant bit of the X position for sprite 1
  and restarts it at the 256th pixel/position on the screen. POKE V+2,0
  displays the sprite at the NEW POSITION ZERO, which is now reset to the
  256th pixel.
    To get back to the left side of the screen, you must reset the most
  significant bit of the X position counter to 0 by typing (for sprite 1):

    POKE V+16, PEEK(V+16)AND 253

    TO SUMMARIZE how the X positioning works... POKE the X POSITION for any
  sprite with a number from 0 to 255. To access a position beyond the 255th
  position/pixel across the screen, you must use an additional POKE (V+16)
  which sets the most significant bit of the X position and start counting
  from 0 again at the 256th pixel across the screen.

                                                 PROGRAMMING GRAPHICS   159

  This POKE starts the X numbering over again from 0 at the 256th position
  (Example: POKE V+16,PEEK(V+16)OR 1 and POKE V,1 must be included to place
  sprite 0 at the 257th pixel across the screen.) To get back to the left
  side X positions you have to TURN OFF the control setting by typing
  POKE V+16,PEEK(V+16)AND 254.

  POSITIONING MULTIPLE SPRITES ON THE SCREEN

    Here's a program which defines THREE DIFFERENT SPRITES (0, 1 and 2) in
  different colors and places them in different positions on the screen:

start tok64 page160.prg
  10 print"{clear}":v=53248:fors=832to895:pokes,255:next
  20 form=2040to2042:pokem,13:next
  30 pokev+21,7
  40 pokev+39,1:pokev+40,7:pokev+41,8
  50 pokev,24:pokev+1,50
  60 pokev+2,12:pokev+3,229
  70 pokev+4,255:pokev+5,50
stop tok64

    For convenience, all 3 sprites have been defined as solid squares,
  getting their data from the same place. The important lesson here is how
  the 3 sprites are positioned. The white sprite 0 is at the top lefthand
  corner. The yellow sprite 1 is at the bottom lefthand corner but HALF the
  sprite is OFF THE SCREEN (remember, 24 is the leftmost X position in the
  viewing area... an X position less than 24 puts all or part of the sprite
  off the screen and we used an X position 12 here which put the sprite
  halfway off the screen). Finally, the orange sprite 2 is at the RIGHT X
  LIMIT (position 255)... but what if you want to display a sprite in the
  area to the RIGHT of X position 255?

  DISPLAYING A SPRITE BEYOND THE 255TH X-POSITION

    Displaying a sprite beyond the 255th X position requires a special POKE
  which SETS the most significant bit of the X position and starts over at
  the 256th pixel position across the screen. Here's how it works...
    First, you POKE V+16 with the number for the sprite you're using (check
  the "RIGHT X" row in the X-Y chart... we'll use sprite 0). Now we assign
  an X position, keeping in mind that the X counter starts over from 0 at
  the 256th position on the screen. Change line 50 to read as follows:
    50 POKE V+16,1:POKE V,24:POKE V+1,75

  160   PROGRAMMING GRAPHICS

  This line POKEs V+ 16 with the number required to "open up" the right
  side of the screen... the new X position 24 for sprite 0 now begins 24
  pixels to the RIGHT of position 255. To check the right edge of the
  screen, change line 60 to:

    60 POKE V+16,1:POKE V,65:POKE V+1,75

    Some experimentation with the settings in the sprite chart will give
  you the settings you need to position and move sprites on the left and
  right sides of the screen. The section on "moving sprites" will also
  increase your understanding of how sprite positioning works.

  SPRITE PRIORITIES

    You can actually make different sprites seem to move IN FRONT OF or
  BEHIND each other on the screen. This incredible three dimensional illu-
  sion is achieved by the built-in SPRITE PRIORITIES which determine which
  sprites have priority over the others when 2 or more sprites OVERLAP on
  the screen.
    The rule is "first come, first served" which means lower-numbered
  sprites AUTOMATICALLY have priority over higher-numbered sprites. For
  example, if you display sprite 0 and sprite 1 so they overlap on the
  screen, sprite 0 will appear to be IN FRONT OF sprite 1. Actually, sprite
  0 always supersedes all the other sprites because it's the lowest num-
  bered sprite. In comparison, sprite 1 has priority over sprites 2-7;
  sprite 2 has priority over sprites 3-7, etc. Sprite 7 (the last sprite)
  has LESS PRIORITY than any of the other sprites, and will always appear
  to be displayed "BEHIND" any other sprites which overlap its position.
    To illustrate how priorities work, change lines 50, 60, and 70 in the
  program above to the following:

  50 POKEV,24:POKEV+1,50:POKEV+16,0
  60 POKEV+2,34:POKEV+3,60
  70 POKEV+4,44:POKEV+5,70

  You should see a white sprite on top of a yellow sprite on top of an
  orange sprite. Of course, now that you see how priorities work, you can
  also MOVE SPRITES and take advantage of these priorities in your ani-
  mation.

                                                 PROGRAMMING GRAPHICS   161

  DRAWING A SPRITE

    Drawing a Commodore sprite is like coloring the empty spaces in a
  coloring book. Every sprite consists of tiny dots called pixels. To draw
  a sprite, all you have to do is "color in" some of the pixels.
    Look at the spritemaking grid in Figure 3-6. This is what a blank
  sprite looks like:

                        [THE PICTURE IS MISSING!]

                      Figure 3-6. Spritemaking grid.

  Each little "square" represents one pixel in the sprite. There are 24
  pixels across and 21 pixels up and down, or 504 pixels in the entire
  sprite. To make the sprite look like something, you have to color in
  these pixels using a special PROGRAM... but how can you control over 500
  individual pixels? That's where computer programming can help you. In-
  stead of typing 504 separate numbers, you only have to type 63 numbers
  for each sprite. Here's how it works...

  162   PROGRAMMING GRAPHICS

  CREATING A SPRITE... STEP BY STEP

    To make this as easy as possible for you, we've put together this
  simple step by step guide to help you draw your own sprites.

  STEP 1:

  Write the spritemaking program shown here ON A PIECE OF PAPER... note
  that line 100 starts a special DATA section of your program which will
  contain the 63 numbers you need to create your sprite.

                        [THE PICTURE IS MISSING!]

  STEP 2:

  Color in the pixels on the spritemaking grid on Page 162 (or use a piece
  of graph paper... remember, a sprite has 24 squares across and 21 squares
  down). We suggest you use a pencil and draw lightly so you can reuse this
  grid. You can create any image you like, but for our example we'll draw
  a simple box.

  STEP 3:

  Look at the first EIGHT pixels. Each column of pixels has a number (128,
  64, 32, 16, 8, 4, 2, 1). The special type of addition we are going to
  show you is a type of BINARY ARITHMETIC which is used by most computers

                                                 PROGRAMMING GRAPHICS   163

  as a special way of counting. Here's a close-up view of the first eight
  pixels in the top left hand corner of the sprite:

       |128| 64| 32| 16|  8|  4|  2|  1|
       +---+---+---+---+---+---+---+---+
       |@@@|@@@|@@@|@@@|@@@|@@@|@@@|@@@|
       |@@@|@@@|@@@|@@@|@@@|@@@|@@@|@@@|
       +---+---+---+---+---+---+---+---+
  STEP 4:

  Add up the numbers of the SOLID pixels. This first group of eight pixels
  is completely solid, so the total number is 255.

  STEP 5:

  Enter that number as the FIRST DATA STATEMENT in line 100 of the
  Spritemaking Program below. Enter 255 for the second and third groups
  of eight.

  STEP 6:

  Look at the FIRST EIGHT PIXELS IN THE SECOND ROW of the sprite. Add up
  the values of the solid pixels. Since only one of these pixels is solid,
  the total value is 128. Enter this as the first DATA number in line 101.

       |128| 64| 32| 16|  8|  4|  2|  1|
       +---+---+---+---+---+---+---+---+
       |@@@|   |   |   |   |   |   |   |
       |@@@|   |   |   |   |   |   |   |
       +---+---+---+---+---+---+---+---+
  STEP 7:

  Add up the values of the next group of eight pixels (which is 0 because
  they're all BLANK) and enter in line 101. Now move to the next group of
  pixels and repeat the process for each GROUP OF EIGHT PIXELS (there are
  3 groups across each row, and 21 rows). This will give you a total of 63
  numbers. Each number represents ONE group of 8 pixels, and 63 groups of
  eight equals 504 total individual pixels. Perhaps a better way of looking
  at the program is like this... each line in the program represents ONE
  ROW in the sprite. Each of the 3 numbers in each row represents ONE GROUP
  OF EIGHT PIXELS. And each number tells the computer which pixels to make
  SOLID and which pixels to leave blank.

  164   PROGRAMMING GRAPHICS

  STEP 8:

  CRUNCH YOUR PROGRAM INTO A SMALLER SPACE BY RUNNING TOGETHER ALL THE DATA
  STATEMENTS, AS SHOWN IN THE SAMPLE PROGRAM BELOW. Note that we asked you
  to write your sprite program on a piece of paper. We did this for a good
  reason. The DATA STATEMENT LINES 100-120 in the program in STEP 1 are
  only there to help you see which numbers relate to which groups of pixels
  in your sprite. Your final program should be "crunched" like this:

start tok64 page165.prg
  10 print"{clear}":poke53280,5:poke53281,6
  20 v=53248:pokev+34,3
  30 poke 53269,4:poke2042,13
  40 forn=0to62:readq:poke832+n,q:next
  100 data255,255,255,128,0,1,128,0,1,128,0,1,144,0,1,144,0,1,144,0,1,144,0
  101 data1,144,0,1,144,0,1,144,0,1,144,0,1,144,0,1,144,0,1,128,0,1,128,0,1
  102 data128,0,1,128,0,1,128,0,1,128,0,1,255,255,255
  200 x=200:y=100:poke53252,x:poke53253,y
stop tok64

  MOVING YOUR SPRITE ON THE SCREEN

    Now that you've created your sprite, let's do some interesting things
  with it. To move your sprite smoothly across the screen, add these two
  lines to your program:

    50 POKE V+5,100:FOR X=24TO255:POKE V+4,X:NEXT:POKE V+16,4
    55 FOR X=0TO65:POKE V+4,X:NEXT X:POKE V+16,0:GOTO 50

    LINE 50 POKEs the Y POSITION at 100 (try 50 or 229 instead for
  variety). Then it sets up a FOR... NEXT loop which POKEs the sprite into
  X position 0 to X position 255, in order. When it reaches the 255th
  position, it POKEs the RIGHT X POSITION (POKE V+16,4) which is required
  to cross to the right side of the screen.

    LINE 55 has a FOR... NEXT loop which continues to POKE the sprite in
  the last 65 positions on the screen. Note that the X value was reset to
  zero but because you used the RIGHT X setting (POKE V+16,2) X starts over
  on the right side of the screen.
    This line keeps going back to itself (GOTO 50). If you just want the
  sprite to move ONCE across the screen and disappear, then take out
  GOTO50.

                                                 PROGRAMMING GRAPHICS   165

    Here's a line which moves the sprite BACK AND FORTH:

    50 POKE V+5,100:FOR X=24TO255:POKE V+4,X:NEXT:POKE V+16,4:
       FOR X=0TO65: POKE V+4,X: NEXT X
    55 FOR X=65TO0 STEP-1:POKE V+4,X:NEXT:POKE V+16,0: FOR
       X=255TO24 STEP-1: POKE V+4,X:NEXT
    60 GOTO 50

  Do you see how these programs work? This program is the same as the
  previous one, except when it reaches the end of the right side of the
  screen, it REVERSES ITSELF and goes back in the other direction. That is
  what the STEP-1 accomplishes... it tells the program to POKE the sprite
  into X values from 65 to 0 on the right side of the screen, then from 255
  to 0 on the left side of the screen, STEPping backwards minus-1 position
  at a time.

  VERTICAL SCROLLING

    This type of sprite movement is called "scrolling." To scroll your
  sprite up or down in the Y position, you only have to use ONE LINE. ERASE
  LINES 50 and 55 by typing the line numbers by themselves and hitting
  <RETURN> like this:

    50 <RETURN>
    60 <RETURN>

  Now enter LINE 50 again as follows:

    50 POKE V+4,24:FOR Y=0TO255:POKE V+5,Y:NEXT

  THE DANCING MOUSE-A SPRITE PROGRAM EXAMPLE

    Sometimes the techniques described in a programmer's reference manual
  are difficult to understand, so we've put together a fun sprite program
  called "Michael's Dancing Mouse." This program uses three different
  sprites in a cute animation with sound effects-and to help you understand
  how it works we've included an explanation of EACH COMMAND so you can see
  exactly how the program is constructed:

  166   PROGRAMMING GRAPHICS

start tok64 page167.prg
  5 s=54272:pokes+24,15:pokes,220:pokes+1,68:pokes+5,15:pokes+6,215
  10 pokes+7,120:pokes+8,100:pokes+12,15:pokes+13,215
  15 print"{clear}":v=53248:pokev+21,1
  20 fors1=12288to12350:readq1:pokes1,q1:next
  25 fors2=12352to12414:readq2:pokes2,q2:next
  30 fors3=12416to12478:readq3:pokes3,q3:next
  35 pokev+39,15:pokev+1,68
  40 printtab(160)"{white}i am the dancing mouse!{light blue}"
  45 p=192
  50 forx=0to347step3
  55 rx=int(x/256):lx=x-rx*256
  60 pokev,lx:pokev+16,rx
  70 ifp=192thengosub200
  75 ifp=193thengosub300
  80 poke2040,p:fort=1to60:next
  85 p=p+1:ifp>194thenp=192
  90 next
  95 end
  100 data30,0,120,63,0,252,127,129,254,127,129,254,127,189,254,127,255,254
  101 data63,255,252,31,187,248,3,187,192,1,255,128,3,189,192,1,231,128,1,
  102 data255,0,31,255,0,0,124,0,0,254,0,1,199,32,3,131,224,7,1,192,1,192,0
  103 data3,192,0,30,0,120,63,0,252,127,129,254,127,129,254,127,189,254,127
  104 data255,254,63,255,252,31,221,248,3,221,192,1,255,128,3,255,192,1,195
  105 data128,1,231,3,31,255,255,0,124,0,0,254,0,1,199,0,7,1,128,7,0,204,1
  106 data128,124,7,128,5630,0,120,63,0,252,127,129,254,127,129,254,127,189
  107 data254,127,255,25463,255,252,31,221,248,3,221,192,1,255,134,3,189
  108 data204,1,199,152,1,255,48,1,255,224,1,252,0,3,254,0
  109 data7,14,0,204,14,0,248,56,0,112,112,0,0,60,0,-1
  200 pokes+4,129:pokes+4,128:return
  300 pokes+11,129:pokes+11,128:return
stop tok64

                                                 PROGRAMMING GRAPHICS   167

  LINE 5:

    S=54272             Sets the variable 5 equal to 54272, which is the
                        beginning memory location of the SOUND CHIP.
                        From now on, instead of poking a direct memory
                        location, we will POKE S plus a value.
    POKES+24,15         Same as POKE 54296,15 which sets VOLUME to
                        highest level.
    POKES,220           Same as POKE 54272,220 which sets Low Fre-
                        quency in Voice 1 for a note which approximates
                        high C in Octave 6.
    POKES+1,68          Same as POKE 54273,68 which sets High Fre-
                        quency in Voice I for a note which approximates
                        high C in Octave 6.
    POKES+5,15          Same as POKE 54277,15 which sets Attack/Decay
                        for Voice 1 and in this case consists of the
                        maximum DECAY level with no attack, which pro-
                        duces the "echo" effect.
    POKES+6,215         Same as POKE 54278,215 which sets Sustain/Re-
                        lease for Voice 1 (215 represents a combination
                        of sustain and release values).
  LINE 10:

    POKES+7,120         Same as POKE 54279,120 which sets the Low Fre-
                        quency for Voice 2.
    POKES+8,100         Same as POKE 54280,100 which sets the High
                        Frequency for Voice 2.
    POKES+12,15         Same as POKE 54284,15 which sets Attack/Decay
                        for Voice 2 to same level as Voice 1 above.
    POKES+13,215        Same as POKE 54285,215 which sets Sustain/Re-
                        lease for Voice 2 to same level as Voice 1 above.

  LINE 15:

    PRINT"<SHIFT+CLR/HOME>" Clears the screen when the program begins.

    V=53248             Defines the variable "V" as the starting location
                        of the VIC chip which controls sprites. From now
                        on we will define sprite locations as V plus a
                        value.

    POKEV+21,1          Turns on (enables) sprite number 1.

  168   PROGRAMMING GRAPHICS

  LINE 20:

    FORS1=12288         We are going to use ONE SPRITE (sprite 0) in this
    TO 12350            animation, but we are going to use THREE sets of
                        sprite data to define three separate shapes. To
                        get our animation, we will switch the POINTERS
                        for sprite 0 to the three places in memory where
                        we have stored the data which defines our three
                        different shapes. The same sprite will be rede-
                        fined rapidly over and over again as 3 different
                        shapes to produce the dancing mouse animation.
                        You can define dozens of sprite shapes in DATA
                        STATEMENTS, and rotate those shapes through
                        one or more sprites. So you see, you don't have to
                        limit one sprite to one shape or vice-versa. One
                        sprite can have many different shapes, simply by
                        changing the POINTER SETTING FOR THAT SPRITE to
                        different places in memory where the sprite data
                        for different shapes is stored. This line means we
                        have put the DATA for "sprite shape 1" at memory
                        locations 12288 to 12350.

    READ Q1             Reads 63 numbers in order from the DATA state-
                        ments which begin at line 100. Q1 is an arbitrary
                        variable name. It could just as easily be A, Z1 or
                        another numeric variable.

    POKES1,Q1           Pokes the first number from the DATA statements
                        (the first "Q1" is 30) into the first memory
                        location (the first memory location is 12288). This
                        is the same as POKE12288,30.

    NEXT                This tells the computer to look BETWEEN the FOR and
                        NEXT parts of the loop and perform those in-between
                        commands (READQ1 and POKES1,Q1 using the NEXT
                        numbers in order). In other words, the NEXT
                        statement makes the computer READ the NEXT Q1 from
                        the DATA STATEMENTS, which is 0, and also
                        increments S1 by 1 to the next value, which is
                        12289. The result is POKE12289,0... the NEXT
                        command makes the loop keep going back until the
                        last values in the series, which are POKE 12350,0.

                                                 PROGRAMMING GRAPHICS   169

  LINE 25:

    FORS2=12352         The second shape of sprite zero is defined by the
    TO 12414            DATA which is located at locations 12352 to 12414.
                        NOTE that location 12351 is SKIPPED... this is the
                        64th location which is used in the definition of
                        the first sprite group but does not contain any of
                        the sprite data numbers. Just remember when
                        defining sprites in consecutive locations that you
                        will use 64 locations, but only POKE sprite data
                        into the first 63 locations.

    READQ2              Reads the 63 numbers which follow the numbers we
                        used for the first sprite shape. This READ simply
                        looks for the very next number in the DATA area and
                        starts reading 63 numbers, one at a time.

    POKES2,Q2           Pokes the data (Q2) into the memory locations (S2)
                        for our second sprite shape, which begins at
                        location 12352.

    NEXT                Same use as line 20 above.

  LINE 30:

    FORS3=12416         The third shape of sprite zero is defined by the
    TO 12478            DATA to be located at locations 12416 to 12478.
    READQ3              Reads last 63 numbers in order as Q3.
    POKES3,Q3           Pokes those numbers into locations 12416 to 12478.
    NEXT                Same as lines 20 and 25.

  LINE 35:

    POKEV+39,15         Sets color for sprite 0 to light grey.

    POKEV+1,68          Sets the upper right hand corner of the sprite
                        square to vertical (Y) position 68. For the sake of
                        comparison, position 50 is the top lefthand corner
                        Y position on the viewing screen.

  170   PROGRAMMING GRAPHICS

  LINE 40:

    PRINTTAB(160)       Tabs 160 spaces from the top lefthand CHARACTER
                        SPACE on the screen, which is the same as 4 rows
                        beneath the clear command... this starts your PRINT
                        message on the 6th line down on the screen.
    "{white}            Hold down the <CTRL> key and press the key marked
                        <WHT> at the same time. If you do this inside
                        quotation marks, a "reversed E" will appear. This
                        sets the color to everything PRINTed from then on
                        to WHITE.
    I AM THE            This is a simple PRINT statement.
    DANCING
    MOUSE!

    {light blue}        This sets the color back to light blue when the
                        PRINT statement ends. Holding down <C=> and <7>
                        a at the same time inside quotation marks
                        causes a "reversed diamond symbol" to appear.

  LINE 45:

    P=192               Sets the variable P equal to 192. This number 192
                        is the pointer you must use, in this case to
                        "point" sprite 0 to the memory locations that begin
                        at location 12288. Changing this pointer to the
                        locations of the other two sprite shapes is the
                        secret of using one sprite to create an animation
                        that is actually three different shapes.

  LINE 50:

    FORX=0TO347         Steps the movement of your sprite 3 X positions at
    STEP3               a time (to provide fast movement) from position 0
                        to position 347.

                                                 PROGRAMMING GRAPHICS   171

  LINE 55:

    RX=INT(X/256)       RX is the integer of X/256 which means that RX is
                        rounded off to 0 when X is less than 256, and RX
                        becomes 1 when X reaches position 256. We will
                        use RX in a moment to POKE V+16 with a 0 or 1
                        to turn on the "RIGHT SIDE" of the screen.

    LX=X-RX*256         When the sprite is at X position 0, the formula
                        looks like this: LX = 0 - (0 times 256) or 0. When
                        the sprite is at X position 1 the formula looks
                        like this: LX = 1 - (0 times 256) or 1. When the
                        sprite is at X position 256 the formula looks like
                        this: LX = 256 - (1 times 256) or 0 which resets X
                        back to 0 which must be done when you start over on
                        the RIGHT SIDE of the screen (POKEV+16,1).

  LINE 60:

    POKEV,LX            You POKE V by itself with a value to set the Hori-
                        zontal (X) Position of sprite 0 on the screen. (See
                        SPRITEMAKING CHART on Page 176). As shown above,
                        the value of LX, which is the horizontal position
                        of the sprite, changes from 0 to 255 and when it
                        reaches 255 it automatically resets back to zero
                        because of the LX equation set up in line 55.

    POKEV+16,RX         POKEV+16 always turns on the "right side" of the
                        screen beyond position 256, and resets the
                        horizontal positioning coordinates to zero. RX is
                        either a 0 or a 1 based on the position of the
                        sprite as determined by the RX formula in line 55.

  LINE 70:

    IFP=192THEN         If the sprite pointer is set to 192 (the first
    GOSUB200            sprite shape) the waveform control for the first
                        sound effect is set to 129 and 128 per line 200.

  172   PROGRAMMING GRAPHICS

  LINE 75:

    IFP=193THEN         If the sprite pointer is set to 193 (the second
    GOSUB300            sprite shape) the waveform control for the second
                        sound effect (Voice 2) is set to 129 and 128 per
                        line 300.

  LINE 80:

    POKE2040,P          Sets the SPRITE POINTER to location 192 (remember
                        P=192 in line 45? Here's where we use the P).

    FORT=1TO60:         A simple time delay loop which sets the speed at
    NEXT                which the mouse dances. (Try a faster or slower
                        speed by increasing/decreasing the number 60.)

  LINE 85:

    P=P+1               Now we increase the value of the pointer by adding
                        1 to the original value of P.

    IFP>194THEN         We only want to point the sprite to 3 memory lo-
    P=192               cations. 192 points to locations 12288 to 12350,
                        193 points to locations 12352 to 12414, and 194
                        points to locations 12416 to 12478. This line tells
                        the computer to reset P back to 192 as soon as P
                        becomes 195 so P never really becomes 195. P is
                        192, 193, 194 and then resets back to 192 and the
                        pointer winds up pointing consecutively to the
                        three sprite shapes in the three 64-byte groups of
                        memory locations containing the DATA.

                                                 PROGRAMMING GRAPHICS   173

  LINE 90:

    NEXTX               After the sprite has become one of the 3 different
                        shapes defined by the DATA, only then is it allowed
                        to move across the screen. It will jump 3 X
                        positions at a time (instead of scrolling smoothly
                        one position at a time, which is also possible).
                        STEPping 3 positions at a time makes the mouse
                        "dance" faster across the screen. NEXT X matches
                        the FOR... X position loop in line 50.

  LINE 95

    END                 ENDs the program, which occurs when the sprite
                        moves off the screen.

  LINES 100-109

    DATA                The sprite shapes are read from the data numbers,
                        in order. First the 63 numbers which comprise
                        sprite shape 1 are read, then the 63 numbers for
                        sprite shape 2, and then sprite shape 3. This data
                        is permanently read into the 3 memory locations and
                        after it is read into these locations, all the
                        program has to do is point sprite 0 at the 3 memory
                        locations and the sprite automatically takes the
                        shape of the data in those locations. We are
                        pointing the sprite at 3 locations one at a time
                        which produces the "animation" effect. If you want
                        to see how these numbers affect each sprite, try
                        changing the first 3 numbers in LINE 100 to 255,
                        255, 255. See the section on defining sprite shapes
                        for more information.

  174   PROGRAMMING GRAPHICS

  LINE 200:

    POKES+4,129         Waveform control set to 129 turns on the sound
                        effect.
    POKES+4,128         Waveform control set to 128 turns off the sound
                        effect.
    RETURN              Sends program back to end of line 70 after
                        waveform control settings are changed, to resume
                        program.

  LINE 300:

    POKES+11,129        Waveform control set to 129 turns on the sound
                        effect.
    POKES+11,128        Waveform control set to 128 turns off the sound
                        effect.
    RETURN              Sends program back to end of line 75 to resume.

                                                 PROGRAMMING GRAPHICS   175

  EASY SPRITEMAKING CHART
  +----------+------+------+------+------+-------+-------+-------+--------+
  |          |SPRT 0|SPRT 1|SPRT 2|SPRT 3|SPRT 4 |SPRT 5 |SPRT 6 | SPRT 7 |
  +----------+------+------+------+------+-------+-------+-------+--------+
  |Turn on   |V+21,1|V+21,2|V+21,4|V+21,8|V+21,16|V+21,32|V+21,64|V+21,128|
  +----------+------+------+------+------+-------+-------+-------+--------+
  |Put in mem| 2040,| 2041,| 2042,| 2043,| 2044, | 2045, | 2046, | 2047,  |
  |set point.|  192 |  193 |  194 |  195 |  196  |  197  |  198  |  199   |
  +----------+------+------+------+------+-------+-------+-------+--------+
  |Locations | 12288| 12352| 12416| 12480| 12544 | 12608 | 12672 | 12736  |
  |for Sprite|  to  |  to  |  to  |  to  |  to   |  to   |  to   |  to    |
  |Pixel     | 12350| 12414| 12478| 12542| 12606 | 12670 | 12734 | 12798  |
  +----------+------+------+------+------+-------+-------+-------+--------+
  |Color     |V+39,C|V+40,C|V+41,C|V+42,C|V+43,C |V+44,C |V+45,C |V+46,C  |
  +----------+------+------+------+------+-------+-------+-------+--------+
  |Set LEFT X| V+0,X| V+2,X| V+4,X| V+6,X| V+8,X |V+10,X |V+12,X |V+14,X  |
  +----------+------+------+------+------+-------+-------+-------+--------+
  |Set RIGHT |V+16,1|V+16,2|V+16,4|V+16,8|V+16,16|V+16,32|V+16,64|V+16,128|
  |X position| V+0,X| V+2,X| V+4,X| V+6,X| V+8,X |V+10,X |V+12,X |V+14,X  |
  +----------+------+------+------+------+-------+-------+-------+--------+
  |Set Y pos.| V+1,Y| V+3,Y| V+5,Y| V+7,Y| V+9,Y |V+11,Y |V+13,Y |V+15,Y  |
  +----------+------+------+------+------+-------+-------+-------+--------+
  |Exp. Horiz|V+29,1|V+29,2|V+29,4|V+29,8|V+29,16|V+29,32|V+29,64|V+29,128|
  +----------+------+------+------+------+-------+-------+-------+--------+
  |Exp. Vert.|V+23,1|V+23,2|V+23,4|V+23,8|V+23,16|V+23,32|V+23,64|V+23,128|
  +----------+------+------+------+------+-------+-------+-------+--------+
  |Multi-Col.|V+28,1|V+28,2|V+28,4|V+28,8|V+28,16|V+28,32|V+28,64|V+28,128|
  +----------+------+------+------+------+-------+-------+-------+--------+
  |M-Color 1 |V+37,C|V+37,C|V+37,C|V+37,C|V+37,C |V+37,C |V+37,C |V+37,C  |
  +----------+------+------+------+------+-------+-------+-------+--------+
  |M-Color 2 |V+38,C|V+38,C|V+38,C|V+38,C|V+38,C |V+38,C |V+38,C |V+38,C  |
  +----------+------+------+------+------+-------+-------+-------+--------+
  |Priority  | The rule is that lower numbered sprites always have display|
  |of sprites| priority over higher numbered sprites. For example, sprite |
  |          | 0 has priority over ALL other sprites, sprite 7 has last   |
  |          | priority. This means lower numbered sprites always appear  |
  |          | to move IN FRONT OF or ON TOP OF higher numbered sprites.  |
  +----------+------------------------------------------------------------+
  |S-S Collis| V+30   IF PEEK(V+30)ANDX=X THEN [action]                   |
  +----------+------------------------------------------------------------+
  |S-B Collis| V+31   IF PEEK(V+31)ANDX=X THEN [action]                   |
  +----------+------------------------------------------------------------+

  176   PROGRAMMING GRAPHICS

  SPRITEMAKING NOTES

            Alternative Sprite Memory Pointers and Memory Locations
                            Using Cassette Buffer
  +---------------+-------+-------+-------+-------------------------------+
  | Put in Memory |SPRT 0 |SPRT 1 |SPRT 2 | If you're using 1 to 3 sprites|
  | (Set pointers)|2040,13|2041,14|2042,15| you can use these memory      |
  +---------------+-------+-------+-------+ locations in the cassette     |
  | Sprite Pixel  | 832   | 896   | 960   | buffer (832 to 1023) but for  |
  | Locations for | to 894| to 958|to 1022| more than 3 sprites we suggest|
  | Blocks 13-15  |       |       |       | using locations from 12288 to |
  +---------------+-------+-------+-------+ 12798 (see chart).            |
  TURNING ON SPRITES:                     +-------------------------------+

    You can turn on any individual sprite by using POKE V+21 and the number
  from the chart... BUT... turning on just ONE sprite will turn OFF any
  others. To turn on TWO OR MORE sprites, ADD TOGETHER the numbers of the
  sprites you want to turn on (Example: POKE V+21, 6 turns on sprites 1 and
  2). Here is a method you can use to turn one sprite off and on without
  affecting any of the others (useful for animation).

  EXAMPLE:

    To turn off just sprite 0 type: POKE V+21,PEEK V+21AND(255-1). Change
  the number 1 in (255-1) to 1,2,4,8,16,32,64, or 128 (for sprites 0-7). To
  re-enable the sprite and not affect the other sprites currently turned
  on, POKE V+21, PEEK(V+21)OR 1 and change the OR 1 to OR 2 (sprite 2), OR
  4 (sprite 3), etc.

  X POSITION VALUES BEYOND 255:

    X positions run from 0 to 255... and then START OVER from 0 to 255. To
  put a sprite beyond X position 255 on the far right side of the screen,
  you must first POKE V+ 16 as shown, THEN POKE a new X valve from 0 to 63,
  which will place the sprite in one of the X positions at the right side
  of the screen. To get back to positions 0-255, POKE V+16,0 and POKE in an
  X value from 0 to 255.

  Y POSITION VALUES:

    Y positions run from 0 to 255, including 0 to 49 off the TOP of the
  viewing area, 50 to 229 IN the,viewing area, and 230 to 255 off the
  BOTTOM of the viewing area.
                                                 PROGRAMMING GRAPHICS   177

  SPRITE COLORS:

    To make sprite 0 WHITE, type: POKE V+39,1 (use COLOR POKE SETTING shown
  in chart, and INDIVIDUAL COLOR CODES shown below):

    0-BLACK     4-PURPLE        8-ORANGE        12-MED. GREY
    1-WHITE     5-GREEN         9-BROWN         13-LT. GREEN
    2-RED       6-BLUE          10-LT. RED      14-LT. BLUE
    3-CYAN      7-YELLOW        11-DARK GREY    15-LT. GREY

  MEMORY LOCATION:

    You must "reserve" a separate 64-BYTE BLOCK of numbers in the
  computer's memory for each sprite of which 63 BYTES will be used for
  sprite data. The memory settings shown below are recommended for the
  "sprite pointer" settings in the chart above. Each sprite will be unique
  and you'll have to define it as you wish. To make all sprites exactly the
  same, point the sprites you want to look the same to the same register
  for sprites.

  DIFFERENT SPRITE POINTER SETTINGS:

    These sprite pointer settings are RECOMMENDATIONS ONLY.
    Caution: you can set your sprite pointers anywhere in RAM memory but if
  you set them too "low" in memory a long BASIC program may overwrite your
  sprite data, or vice versa. To protect an especially LONG BASIC PROGRAM
  from overwriting sprite data, you may want to set the sprites at a higher
  area of memory (for example, 2040,192 for sprite 0 at locations 12288 to
  12350... 2041,193 at locations 12352 to 12414 for sprite 1 and so on...
  by adjusting the memory locations from which sprites get their "data,"
  you can define as many as 64 different sprites plus a sizable BASIC
  program. To do this, define several sprite "shapes" in your DATA
  statements and then redefine a particular sprite by changing the
  "pointer" so the sprite you are using is "pointed" at different areas of
  memory containing different sprite picture data. See the "Dancing Mouse"
  to see how this works. If you want two or more sprites to have THE SAME
  SHAPE (you can still change position and color of each sprite), use the
  same sprite pointer and memory location for the sprites you want to match
  (for example, you can point sprites 0 and 1 to the same location by using
  POKE 2040,192 and POKE 2041, 192).

  178   PROGRAMMING GRAPHICS

  PRIORITY:

    Priority means one sprite will appear to move "in front of" or "behind"
  another sprite on the display screen. Sprites with more priority always
  appear to move "in front of" or "on top of" sprites with less priority.
  The rule is that lower numbered sprites have priority over higher
  numbered sprites. Sprite 0 has priority over all other sprites. Sprite 7
  has no priority in relation to the other sprites. Sprite 1 has priority
  over sprites 2-7, etc. If you put two sprites in the some position, the
  sprite with the higher priority will appear IN FRONT OF the sprite with
  the lower priority. The sprite with lower priority will either be
  obscured, or will "show through" (from "behind") the sprite with higher
  priority.

  USING MULTI-COLOR:

    You can create multi-colored sprites although using multi-color mode
  requires that you use PAIRS of pixels instead of individual pixels in
  your sprite picture (in other words each colored "dot" or "block" in the
  sprite will consist of two pixels side by side). You have 4 colors to
  choose from: Sprite Color (chart,above), Multi-Color 1, Multi-Color 2 and
  "Background Color" (background is achieved by using zero settings which
  let the background color "show through"). Consider one horizontal 8-pixel
  block in a sprite picture. The color of each PAIR of pixels is determined
  according to whether the left, right, or both pixels are solid, like
  this:

  +-+-+
  | | | BACKGROUND      (Making BOTH PIXELS BLANK (zero) lets the
  +-+-+                  INNER SCREEN COLOR (background)show through.)

  +-+-+
  | |@| MULTI-COLOR 1   (Making the RIGHT PIXEL SOLID in a pair of pixels
  +-+-+                  sets BOTH PIXELS to Multi-Color 1.)

  +-+-+
  |@| | SPRITE COLOR    (Making the LEFT PIXEL SOLID in a pair of pixels
  +-+-+                  sets BOTH PIXELS to Sprite Color.)

  +-+-+
  |@|@| MULTI-COLOR 2   (Making BOTH PIXELS SOLID in a pair of pixels
  +-+-+                  sets BOTH PIXELS to Multi-Color 2.)

                                                 PROGRAMMING GRAPHICS   179

  Look at the horizontal 8-pixel row shown below. This block sets the first
  two pixels to background color, the second two pixels to Multi-Color 1,
  the third two pixels to Sprite Color and the fourth two pixels to Multi-
  Color 2. The color of each PAIR of pixels depends on which bits in each
  pair are solid and which are blank, according to the illustration above.
  After you determine which colors you want in each pair of pixels, the
  next step is to add the values of the solid pixels in the 8-pixel block,
  and POKE that number into the proper memory location. For example, if the
  8-pixel row shown below is the first block in a sprite which begins at
  memory location 832, the value of the solid pixels is 16+8+2+1 27, so you
  would POKE 832,27.

                     |128| 64| 32| 16|  8|  4|  2|  1|   16+8+2+1 = 27
                     +---+---+---+---+---+---+---+---+
                     |   |   |   |@@@|@@@|   |@@@|@@@|
                     |   |   |   |@@@|@@@|   |@@@|@@@|
                     +---+---+---+---+---+---+---+---+

                         LOOKS LIKE THIS IN SPRITE

                     +-------+-------+-------+-------+
                     |BACKGR.|MULTI- |SPRITE |MULTI- |
                     | COLOR |COLOR 1| COLOR |COLOR 2|
                     +-------+-------+-------+-------+

  COLLISION:

    You can detect whether a sprite has collided with another sprite by
  using this line: IF PEEK(V+30)ANDX=XTHEN [insert action here]. This line
  checks to see if a particular sprite has collided with ANY OTHER SPRITE,
  where X equals 1 for sprite 0, 2 for sprite 1, 4 for sprite 2, 8 for
  sprite 3, 16 for sprite 4, 32 for sprite 5, 64 for sprite 6, and 128 for
  sprite 7. To check to see if the sprite has collided with a "BACKGROUND
  CHARACTER" use this line: IF PEEK(V+31)ANDX=XTHEN [insert action here].

  180   PROGRAMMING GRAPHICS

  USING GRAPHIC CHARACTERS IN DATA STATEMENTS

    The following program allows you to create a sprite using blanks and
  solid circles <SHIFT+Q> in DATA statements. The sprite and the numbers
  POKED into the sprite data registers are displayed.

start tok64 page181.prg
  10 print"{clear}":fori=0to63:poke832+i,0:next
  20 gosub60000
  999 end
  60000 data"         QQQQQQQ        "
  60001 data"       QQQQQQQQQQQ      "
  60002 data"      QQQQQQQQQQQQQ     "
  60003 data"      QQQQQ   QQQQQ     "
  60004 data"     QQQQQ QQQ  QQQQ    "
  60005 data"     QQQQQ QQQ QQQQQ    "
  60006 data"     QQQQQ QQQ  QQQQ    "
  60007 data"      QQQQQ   QQQQQ     "
  60008 data"      QQQQQQQQQQQQQ     "
  60009 data"      QQQQQQQQQQQQQ     "
  60010 data"      Q QQQQQQQQQ Q     "
  60011 data"       Q QQQQQQQ Q      "
  60012 data"       Q  QQQQQ  Q      "
  60013 data"        Q  QQQ  Q       "
  60014 data"        Q  QQQ  Q       "
  60015 data"         Q  Q  Q        "
  60016 data"         Q  Q  Q        "
  60017 data"          QQQQQ         "
  60018 data"          QQQQQ         "
  60019 data"          QQQQQ         "
  60020 data"           QQQ          "
  60100 v=53248:pokev,200:pokev+1,100:pokev+21,1:pokev+39,14:poke2040,13
  60105 pokev+23,1:pokev+29,1
  60110 fori=0to20:reada$:fork=0to2:t=0:forj=0to7:b=0
  60140 ifmid$(a$,j+k*8+1,1)="Q"thenb=1
  60150 t=t+b*2^(7-j):next:printt;:poke832+i*3+k,t:next:print:next
  60200 return
stop tok64

                                                 PROGRAMMING GRAPHICS   181

                                                 CHAPTER 4

                                               PROGRAMMING
                                                 SOUND AND
                                             MUSIC ON YOUR
                                              COMMODORE 64

                           o Introduction
                               Volume Control
                               Frequencies of Sound Waves
                           o Using Multiple Voices
                           o Changing Waveforms
                           o The Envelope Generator
                           o Filtering
                           o Advanced Techniques
                           o Synchronization and Ring
                             Modulation

                                     183

  INTRODUCTION

    Your Commodore computer is equipped with one of the most sophisticated
  electronic music synthesizers available on any computer. It comes
  complete with three voices, totally addressable, ATTACK/DECAY/SUSTAIN/
  RELEASE (ADSR), filtering, modulation, and "white noise." All of these
  capabilities are directly available for you through a few easy to use
  BASIC and/or assembly language statements and functions. This means that
  you can make very complex sounds and songs using programs that are
  relatively simple to design.
    This section of your Programmer's Reference Guide has been created to
  help you explore all the capabilities of the 6581 "SID" chip, the sound
  and music synthesizer inside your Commodore computer. We'll explain both
  the theory behind musical ideas and the practical aspects of turning
  those ideas into real finished songs on your Commodore computer.
    You need not be an experienced programmer nor a music expert to achieve
  exciting results from the music synthesizer. This section is full of
  programming examples with complete explanations to get you started.
    You get to the sound generator by POKEing into specified memory
  locations. A full list of the locations used is provided in Appendix O.
  We will go through each concept, step by step. By the end you should be
  able to create an almost infinite variety of sounds, and be ready to
  perform experiments with sound on your own.
    Each section of this chapter begins by giving you an example and a full
  line-by-line description of each program, which will show you how to use
  the characteristic being discussed. The technical explanation is for you
  to read whenever you are curious about what is actually going on. The
  workhorse of your sound programs is the POKE statement. POKE sets the
  indicated memory location (MEM) equal to a specified value (NUM).

    POKE MEM,NUM

    The memory locations (MEM) used for music synthesis start at 54272
  ($D400) in the Commodore 64. The memory locations 54272 to 54296
  inclusive are the POKE locations you need to remember when you're using
  the 6581 (SID) chip register map. Another way to use the locations above
  is to remember only location 54272 and then add a number from 0 through
  24 to it. By doing this you can POKE all the locations from 54272 to
  54296 that you need from the SID chip. The numbers (NUM) that you use in
  your POKE statement must be between 0 and 255, inclusive.

  184   PROGRAMMING SOUND AND MUSIC

    When you've had a little more practice with making music, then you can
  get a little more involved, by using the PEEK function. PEEK is a
  function that is equal to the value currently in the indicated memory
  location.
    X=PEEK(MEM)

    The value of the variable X is set equal to the current contents of
  memory location MEM.
    Of course, your programs include other BASIC commands, but for a full
  explanation of them, refer to the BASIC Statements section of this
  manual.
    Let's jump right in and try a simple program using only one of the
  three voices. Computer ready? Type NEW, then type in this program, and
  save it on your Commodore DATASSETTE(TM) or disk. Then, RUN it.

  EXAMPLE PROGRAM 1:
start tok64 page185.prg
  5 s=54272
  10 forl=stos+24:pokel,0:next:rem clear sound chip
  20 pokes+5,9:pokes+6,0
  30 pokes+24,15              :rem set volume to maximum
  40 readhf,lf,dr
  50 ifhf<0thenend
  60 pokes+1,hf:pokes,lf
  70 pokes+4,33
  80 fort=1todr:next
  90 pokes+4,32:fort=1to50:next
  100 goto40
  110 data25,177,250,28,214,250
  120 data25,177,250,25,177,250
  130 data25,177,125,28,214,125
  140 data32,94,750,25,177,250
  150 data28,214,250,19,63,250
  160 data19,63,250,19,63,250
  170 data21,154,63,24,63,63
  180 data25,177,250,24,63,125
  190 data19,63,250,-1,-1,-1
stop tok64

    Here's a line-by-line description of the program you've just typed in.
  Refer to it whenever you feel the need to investigate parts of the pro-
  gram that you don't understand completely.

                                          PROGRAMMING SOUND AND MUSIC   185

  LINE-BY-LINE EXPLANATION OF EXAMPLE PROGRAM 1:

  +--------+--------------------------------------------------------------+
  | Line(s)|                         Description                          |
  +--------+--------------------------------------------------------------+
  | 5      | Set S to start of sound chip.                                |
  | 10     | Clear all sound chip registers.                              |
  | 20     | Set Attack/Decay for voice 1 (A=O,D=9).                      |
  |        | Set Sustain/Release for voice 1 (S=O,R=O),                   |
  | 30     | Set volume at maximum.                                       |
  | 40     | Read high frequency, low frequency, duration of note.        |
  | 50     | When high frequency less than zero, song is over.            |
  | 60     | Poke high and low frequency of voice 1.                      |
  | 70     | Gate sawtooth waveform for voice 1.                          |
  | 80     | Timing loop for duration of note.                            |
  | 90     | Release sawtooth waveform for voice 1.                       |
  | 100    | Return for next note.                                        |
  | 110-180| Data for song: high frequency, low frequency, duration       |
  |        | (number of counts) for each note.                            |
  | 190    | Last note of song and negative Is signaling end of song.     |
  +--------+--------------------------------------------------------------+

  VOLUME CONTROL

    Chip register 24 contains the overall volume control. The volume can be
  set anywhere between 0 and 15. The other four bits are used for purposes
  we'll get into later. For now it is enough to know volume is 0 to 15.
  Look at line 30 to see how it's set in Example Program 1.

  FREQUENCIES OF SOUND WAVES

    Sound is created by the movement of air in waves. Think of throwing a
  stone into a pool and seeing the waves radiate outward. When similar
  waves are created in air, we hear it. If we measure the time between one
  peak of a wave and the next, we find the number of seconds for one cycle
  of the wave (n = number of seconds). The reciprocal of this number (1/n)
  gives you the cycles per second. Cycles per second are more commonly
  known as the frequency. The highness or lowness of a sound (pitch) is
  determined by the frequency of the sound waves produced.
    The sound generator in your Commodore computer uses two locations to
  determine the frequency. Appendix E gives you the frequency values you
  need to reproduce a full eight octaves of musical notes. To create a

  186   PROGRAMMING SOUND AND MUSIC

  frequency other than the ones listed in the note table use "Fout" (fre-
  quency output) and the following formula to represent the frequency (Fn)
  of the sound you want to create. Remember that each note requires both a
  high and a low frequency number.

             Fn = Fout/.06097

    Once you've figured out what Fn is for your "new" note the next step is
  to create the high and low frequency values for that note. To do this you
  must first round off Fn so that any numbers to the right of the decimal
  point are left off. You are now left with an integer value. Now you can
  set the high frequency location (Fhi) by using the formula
  Fhi=INT(Fn/256) and the low frequency location (Flo) should be
  Flo=Fn-(256*Fhi).
    At this point you have already played with one voice of your computer.
  If you wanted to stop here you could find a copy of your favorite tune
  and become the maestro conducting your own computer orchestra in your "at
  home" concert hall.

  USING MULTIPLE VOICES

    Your Commodore computer has three independently controlled voices
  (oscillators). Our first example program used only one of them. later on,
  you'll learn how to change the quality of the sound made by the voices.
  But right now, let's get all three voices singing.
    This example program shows you one way to translate sheet music for
  your computer orchestra. Try typing it in, and then SAVE it on your
  DATASSETTE(TM) or disk. Don't forget to type NEW before typing in this
  program.

  EXAMPLE PROGRAM 2:

start tok64 page187.prg
  10 s=54272:forl=stos+24:pokel,0:next
  20 dimh(2,200),l(2,200),c(2,200)
  30 dimfq(11)
  40 v(0)=17:v(1)=65:v(2)=33
  50 pokes+10,8:pokes+22,128:pokes+23,244
  60 fori=0to11:readfq(i):next
  100 fork=0to2
  110 i=0
  120 readnm

  130 ifnm=0then250
  140 wa=v(k):wb=wa-1:ifnm<0thennm=-nm:wa=0:wb=0
  150 dr%nm/128:oc%=(nm-128*dr%)/16
  160 nt=nm-128*dr%-16*oc%
  170 fr=fq(nt)
  180 ifoc%=7then200
  190 forj=6tooc%step-1:fr=fr/2:next
  200 hf%=fr/256:lf%=fr-256*hf%
  210 ifdr%=1thenh(k,i)=hf%:l(k,i)=lf%:c(k,i)=wa:i=i+1:goto120
  220 forj=1todr%-1:h(k,i)=hf%:l(k,i)=lf%:c(k,i)=wa:i=i+1:next
  230 h(k,i)=hf%:l(k,i)=lf%:c(k,i)=wb
  240 i=i+1:goto120
  250 ifi>imthenim=i
  260 next
  500 pokes+5,0:pokes+6,240
  510 pokes+12,85:pokes+13,133
  520 pokes+19,10:pokes+20,197
  530 pokes+24,31
  540 fori=0toim
  550 pokes,l(0,i):pokes+7,l(1,i):pokes+14,l(2,i)
  560 pokes+1,h(0,i):pokes+8,h(1,i):pokes+15,h(2,i)
  570 pokes+4,c(0,i):pokes+11,c(1,i):pokes+18,c(2,i)
  580 fort=1to80:next:next
  590 fort=1to200:next:pokes+24,0
  600 data34334,36376,38539,40830
  610 data43258,45830,48556,51443
  620 data54502,57743,61176,64814
  1000 data594,594,594,596,596,1618,587,592,587.585,331,336
  1010 data1097,583,585,585,585,587,587,1609,585,331,337,594,594,593
  1020 data1618,594,596,594,592,587,1616,587,585,331,336,841,327
  1999 data1607,0
  2000 data583,585,583,583,327,329,1611,583,585,578,578,578
  2010 data196,198,583,326,578,326,327,329,327,329,326,578,583
  2020 data1606,582,322,324,582,587,329,327,1606,583,327,329,587,331,329
  2999 data329,328,1609,578,834,324,322,327,585,1602,0
  3000 data567,566,567,304,306,308,310,1591,567,311,310,567
  3010 data306,304,299,308,304,171,176,306,291,551,306,308
  3020 data310,308,310,306,295,297,299,304,1586,562,567,310,315,311
  3030 data308,313,297,1586,567,560,311,309,308,309,306,308
  3999 data1577,299,295,306,310,311,304,562,546,1575,0
stop tok64

  188   PROGRAMMING SOUND AND MUSIC

    Here is a line,-by-line explanation of Example Program 2. For now, we
  are interested in how the three voices are controlled.

  LINE-BY-LINE EXPLANATION OF EXAMPLE PROGRAM 2:

  +---------+-------------------------------------------------------------+
  | Line(s) |                       Description                           |
  +---------+-------------------------------------------------------------+
  | 10      | Set S equal to start of sound chip and clear all sound      |
  |         | chip registers.                                             |
  | 20      | Dimension arrays to contain activity of song, 1/16th of a   |
  |         | measure per location.                                       |
  | 30      | Dimension array to contain base frequency for each note.    |
  | 40      | Store waveform control byte for each voice.                 |
  | 50      | Set high pulse width for voice 2.                           |
  |         | Set high frequency for filter cutoff.                       |
  |         | Set resonance for filter and filter voice 3.                |
  | 60      | Read in base frequency for each note.                       |
  | 100     | Begin decoding loop for each voice.                         |
  | 110     | Initialize pointer to activity array.                       |
  | 120     | Read coded note.                                            |
  | 130     | If coded note is zero, then next voice.                     |
  | 140     | Set waveform controls to proper voice.                      |
  |         | If silence, set waveform controls to 0.                     |
  | 150     | Decode duration and octave.                                 |
  | 160     | Decode note.                                                |
  | 170     | Get base frequency for this note.                           |
  | 180     | If highest octave, skip division loop.                      |
  | 190     | Divide base frequency by 2 appropriate number of times.     |
  | 200     | Get high and low frequency bytes.                           |
  | 210     | If sixteenth note, set activity array: high frequency, low  |
  |         | frequency, and waveform control (voice on).                 |
  | 220     | For all but last beat of note, set activity array: high     |
  |         | frequency, low frequency, waveform control (voice on).      |
  | 230     | For last beat of note, set activity array: high frequency,  |
  |         | low frequency, waveform control (voice off).                |
  | 240     | Increment pointer to activity array. Get next note.         |
  | 250     | If longer than before, reset number of activities.          |
  | 260     | Go back for next voice.                                     |
  | 500     | Set Attack/Decay for voice 1 (A=0, D=0).                    |
  |         | Set Sustain/Release for voice 1 (S=15, R=0).                |

                                          PROGRAMMING SOUND AND MUSIC   189

  +---------+-------------------------------------------------------------+
  | Line(s) |                       Description                           |
  +---------+-------------------------------------------------------------+
  | 510     | Set Attack/Decay for voice 2 (A=5, D=5).                    |
  |         | Set Sustain/Release for voice 2 (S=8, R=5).                 |
  | 520     | Set Attack/Decay for voice 3 (A=O, D=10).                   |
  |         | Set Sustain/Release for voice 3 (S=12, R=5).                |
  | 530     | Set volume 15, low-pass filtering.                          |
  | 540     | Start loop for every 1/16th of a measure.                   |
  | 550     | POKE low frequency from activity array for all voices.      |
  | 560     | POKE high frequency from activity array for all voices.     |
  | 570     | POKE waveform control from activity array for all voices.   |
  | 580     | Timing loop for 1/16th of a measure and back for next       |
  |         | 1/16th measure.                                             |
  | 590     | Pause, then turn off volume.                                |
  | 600-620 | Base frequency data.                                        |
  |1000-1999| Voice 1 data.                                               |
  |2000-2999| Voice 2 data.                                               |
  |3000-3999| Voice 3 data.                                               |
  +-----------------------------------------------------------------------+

    The values used in the data statements were found by using the note
  table in Appendix E and the chart below:

                    +-----------------+------------+
                    |   NOTE TYPE     |  DURATION  |
                    +-----------------+------------+
                    |        1/16     |     128    |
                    |        1/8      |     256    |
                    | DOTTED 1/8      |     384    |
                    |        1/4      |     512    |
                    |    1/4+1/16     |     640    |
                    | DOTTED 1/4      |     768    |
                    |        1/2      |    1024    |
                    |    1/2+1/16     |    1152    |
                    |    1/2+1/8      |    1280    |
                    | DOTTED 1/2      |    1536    |
                    |  WHOLE          |    2048    |
                    +-----------------+------------+

  190   PROGRAMMING SOUND AND MUSIC

    The note number from the note table is added to the duration above.
  Then each note can be entered using only one number which is decoded by
  your program. This is only one method of coding note values. You may be
  able to come up with one with which you are more comfortable. The formula
  used here for encoding a note is as follows:

    1) The duration (number of 1/16ths of a measure) is multiplied by 8.
    2) The result of step 1 is added to the octave you've chosen (0-7).
    3) The result of step 2 is then multiplied by 16.
    4) Add your note choice (0-11) to the result of the operation in step
       3.

  In other words:

                            ((((D*8)+O)*16)+N)

  Where D = duration, O = octave, and N = note
    A silence is obtained by using the negative of the duration number
  (number of 1/16ths of a measure * 128).

  CONTROLLING MULTIPLE VOICES

    Once you have gotten used to using more than one voice, you will find
  that the timing of the three voices needs to be coordinated. This is ac-
  complished in this program by:

    1) Divide each musical measure into 16 parts.
    2) Store the events that occur in each 1/16th measure interval in three
       separate arrays.

    The high and low frequency bytes are calculated by dividing the fre-
  quencies of the highest octave by two (lines 180 and 190). The waveform
  control byte is a start signal for beginning a note or continuing a note
  that is already playing. It is a stop signal to end a note. The waveform
  choice is made once for each voice in line 40.
    Again, this is only one way to control multiple voices. You may come
  up with your own methods. However, you should now be able to take any
  piece of sheet music and figure out the notes for all three voices.

                                          PROGRAMMING SOUND AND MUSIC   191

  CHANGING WAVEFORMS

    The tonal quality of a sound is called the timbre. The timbre of a
  sound is determined primarily by its "waveform." If you remember the
  example of throwing a pebble into the water you know that the waves
  ripple evenly across the pond. These waves almost look like the first
  sound wave we're going to talk about, the sinusoidal wave, or sine wave
  for short (shown below).

                              +               +
                            +   +           +   +
                           /     \         /     \
                         ./.......\......./.......\.
                                   \     /
                                    +   +
                                      +

    To make what we're talking about a bit more practical, let's go back to
  the first example program to investigate different waveforms. The reason
  for this is that you can hear the changes more easily using only one
  voice. LOAD the first music program that you typed in earlier, from your
  DATASSETTE(TM) or disk, and RUN it again. That program is using the
  sawtooth waveform (shown here)

                              +       +       +
                             /|      /|      /|
                            / |     / |     / |
                           /  |    /  |    /  |
                         ./...|.../...|.../...|.....
                              |  /    |  /    |  /
                              | /     | /     | /
                              |/      |/      |/
                              +       +       +

  from the 6581 SID chip's sound generating device. Try changing the note
  start number in line 70 from 33 to 17 and the note stop number in line 90
  from 32 to 16. Your program should now look like this:

  192   PROGRAMMING SOUND AND MUSIC

  EXAMPLE PROGRAM 3 (EXAMPLE 1 MODIFIED):

start tok64 page193.prg
  5 s=54272
  10 forl=stos+24:pokel,0:next
  20 pokes+5,9:pokes+6,0
  30 pokes+24,15
  40 readhf,lf,dr
  50 ifhf<0thenend
  60 pokes+1,hf:pokes,lf
  70 pokes+4,17
  80 fort=1todr:next
  90 pokes+4,16:fort=1to50:next
  100 goto40
  110 data25,177,250,28,214,250
  120 data25,177,250,25,177,250
  130 data25,177,125,28,214,125
  140 data32,94,750,25,177,250
  150 data28,214,250,19,63,250
  160 data19,63,250,19,63,250
  170 data21,154,63,24,63,63
  180 data25,177,250,24,63,125
  190 data19,63,250,-1,-1,-1
stop tok64

  Now RUN the program.
    Notice how the sound quality is different, less twangy, more hollow.
  That's because we changed the sawtooth waveform into a triangular
  waveform (shown left). The third musical waveform is called a variable
  pulse wave (shown right).

              +               +          +----+  +----+  +----+  |
             / \             / \         |    |  |    |  |    |  |
            /   \           /   \        |    |  |    |  |    |  |
           /     \         /     \       |    |  |    |  |    |  |
         ./.......\......./.......\.    .|....|..|....|..|....|..|.
                   \     /               |    |  |    |  |    |  |
                    \   /                |    |  |    |  |    |  |
                     \ /                 |    |  |    |  |    |  |
                      +                  |    +--+    +--+    +--+
                                                  <-->
                                              PULSE WIDTH

                                          PROGRAMMING SOUND AND MUSIC   193

    It is a rectangular wave and you determine the length of the pulse
  cycle by defining the proportion of the wave which will be high. This is
  accomplished for voice 1 by using registers 2 and 3: Register 2 is the
  low byte of the pulse width (Lpw = 0 through 255). Register 3 is the high
  4 bits (Hpw = 0 through 15).
    Together these registers specify a 12-bit number for your pulse width,
  which you can determine by using the following formula:

                        PWn = Hpw*256 + Lpw

  The pulse width is determined by the following equation:

                       PWout = (PWn/40.95) %

    When PWn has a value of 2048, it will give you a square wave. That
  means that register 2 (Lpw) = 0 and register 3 (Hpw) = 8.
    Now try adding this line to your program:

    15 POKES+3,8:POKES+2,0

  Then change the start number in line 70 to 65 and the stop number in fine
  90 to 64, and RUN the program. Now change the high pulse width (register
  3 in line 15) from an 8 to a 1. Notice how dramatic the difference in
  sound quality is?
    The last waveform available to you is white noise (shown here).

                                   .   .       .
                          .     . .          .   .
                           .  .     .       .
                         ...........................
                             . . .        .
                                      .  . .  .
                            .                   . .

  It is used mostly for sound effects and such. To hear how it sounds, try
  changing the start number in line 70 to 129 and the stop number in line
  90 to 128.

  UNDERSTANDING WAVEFORMS

    When a note is played, it consists of a sine wave oscillating at the
  fundamental frequency and the harmonics of that wave.

  194   PROGRAMMING SOUND AND MUSIC

    The fundamental frequency defines the overall pitch of the note.
  Harmonics are sine waves having frequencies which are integer multiples
  of the fundamental frequency. A sound wave is the fundamental frequency
  and all of the harmonics it takes to make up that sound.

                       [THE PICTURE IS MISSING!]

    In musical theory let's say that the fundamental frequency is harmonic
  number 1. The second harmonic has a frequency twice the fundamental
  frequency, the third harmonic is three times the fundamental frequency,
  and so on. The amounts of each harmonic present in a note give it its
  timbre.
    An acoustic instrument, like a guitar or a violin, has a very compli-
  cated harmonic structure. In fact, the harmonic structure may vary as a
   single note is played. You have already played with the waveforms
  available in your Commodore music synthesizer. Now let's talk about how
  the harmonics work with the triangular, sawtooth, and rectangular waves.
    A triangular wave contains only odd harmonics. The amount of each
  harmonic present is proportional to the reciprocal of the square of the
  harmonic number. In other words harmonic number 3 is 1/9 quieter than
  harmonic number 1, because the harmonic 3 squared is 9 (3 X 3) and the
  reciprocal of 9 is 1/9.
    As you can see, there is a similarity in shape of a triangular wave to
  a sine wave oscillating at the fundamental frequency.
    Sawtooth waves contain all the harmonics. The amount of each harmonic
  present is proportional to the reciprocal of the harmonic number. For
  example, harmonic number 2 is 1/2 as loud as harmonic number 1.
    The square wave contains odd harmonics in proportion to the reciprocal
  of the harmonic number. Other rectangular waves have varying harmonic
  content. By changing the pulse width, the timbre of the sound of a
  rectangular wave can be varied tremendously.

                                          PROGRAMMING SOUND AND MUSIC   195

    By choosing carefully the waveform used, you can start with a harmonic
  structure that looks somewhat like the sound you want. To refine the
  sound, you can add another aspect of sound quality available on your
  Commodore 64 called filtering, which we'll discuss later in this section.

  THE ENVELOPE GENERATOR

    The volume of a musical tone changes from the moment you first hear it,
  all the way through until it dies out and you can't hear it anymore. When
  a note is first struck, it rises from zero volume to its peak volume. The
  rate at which this happens is called the ATTACK. Then, it fails from the
  peak to some middle-ranged volume. The rate at which the fall of the note
  occurs is called the DECAY. The mid-ranged volume itself is called the
  SUSTAIN level. And finally, when the note stops playing, it fails from
  the SUSTAIN level to zero volume. The rate at which it fails is called
  the RELEASE. Here is a sketch of the four phases of a note:

                              +
                             / \
                            /   \
                           /     \
         SUSTAIN LEVEL . ./. . . .+--------+
                         /                  \
                        /                    \
                       /                      \

                       |      |   |        |   |
                       |   A  | D |    S   | R |

    Each of the items mentioned above give certain qualities and restric-
  tions to a note. The bounds are called parameters.
    The parameters ATTACK/DECAY/SUSTAIN/RELEASE and collectively called
  ADSR, can be controlled by your use of another set of locations in the
  sound generator chip. LOAD your first example program again. RUN it again
  and remember how it sounds. Then, changing line 20 so the program is like
  this:

  196   PROGRAMMING SOUND AND MUSIC

  EXAMPLE PRO6RAM 4 (EXAMPLE 1 MODIFIED):

start tok64 page197.prg
  5 s=54272
  10 forl=stos+24:pokel,0:next
  20 pokes+5,88:pokes+6,195
  30 pokes+24,15
  40 readhf,lf,dr
  50 ifhf<0thenend
  60 pokes+1,hf:pokes,lf
  70 pokes+4,33
  80 fort=1todr:next
  90 pokes+4,32:fort=1to50:next
  100 goto40
  110 data25,177,250,28,214,250
  120 data25,177,250,25,177,250
  130 data25,177,125,28,214,125
  140 data32,94,750,25,177,250
  150 data28,214,250,19,63,250
  160 data19,63,250,19,63,250
  170 data21,154,63,24,63,63
  180 data25,177,250,24,63,125
  190 data19,63,250,-1,-1,-1
stop tok64

    Registers 5 and 6 define the ADSR for voice 1. The ATTACK is the high
  nybble of register 5. Nybble is half a byte, in other words the lower 4
  or higher 4 on/off locations (bits) in each register. DECAY is the low
  nybble. You can pick any number 0 through 15 for ATTACK, multiply it by
  16 and add to any number 0 through 15 for DECAY. The values that
  correspond to these numbers are listed below.
    SUSTAIN level is the high nybble of register 6. It can be 0 through 15.
  It defines the proportion of the peak volume that the SUSTAIN level will
  be. RELEASE rate is the low nybble of register 6.

                                          PROGRAMMING SOUND AND MUSIC   197

    Here are the meanings of the values for ATTACK, DECAY, and RELEASE:

  +-----+------------------------+--------------------------------+
  |VALUE|ATTACK RATE (TIME/CYCLE)| DECAY/RELEASE RATE (TIME/CYCLE)|
  +-----+------------------------+--------------------------------+
  |  0  |           2 ms         |               6 ms             |
  |  1  |           8 ms         |              24 ms             |
  |  2  |          16 ms         |              48 ms             |
  |  3  |          24 ms         |              72 ms             |
  |  4  |          38 ms         |             114 ms             |
  |  5  |          56 ms         |             168 ms             |
  |  6  |          68 ms         |             204 ms             |
  |  7  |          80 ms         |             240 ms             |
  |  8  |         100 ms         |             300 ms             |
  |  9  |         250 ms         |             750 ms             |
  | 10  |         500 ms         |             1.5 s              |
  | 11  |         800 ms         |             2.4 s              |
  | 12  |           1 s          |               3 s              |
  | 13  |           3 s          |               9 s              |
  | 14  |           5 s          |              15 s              |
  | 15  |           8 s          |              24 s              |
  +-----+------------------------+--------------------------------+

    Here are a few sample settings to try in your example program. Try
  these and a few of your own. The variety of sounds you can produce is
  astounding! For a violin type sound, try changing line 20 to read:

    20 POKES+5,88:POKES+6,89:REM A=5;D=8;S=5;R=9

  Change the waveform to triangle and get a xylophone type sound by using
  these lines:

    20 POKES+5,9:POKES+6,9:REM A=0;D=9;S=O;R=9
    70 POKES+4,17
    90 POKES+4,16:FORT=1TO50:NEXT

  198   PROGRAMMING SOUND AND MUSIC

  Change the waveform to square and try a piano type sound with these
  lines:

    15 POKES+3,8:POKES+2,0
    20 POKES+5,9:POKES+6,0: REM A=0;D=9;S=0;R=0
    70 POKES+4,65
    90 POKES+4,64:FORT=1TO50:NEXT

    The most exciting sounds are those unique to the music synthesizer
  itself, ones that do not attempt to mimic acoustic instruments. For
  example try:

    20 POKES+5,144:POKES+6,243:REM A=9;D=O; S=15;R=3

  FILTERING

    The harmonic content of a waveform can be changed by using a filter.
  The SID chip is equipped with three types of filtering. They can be used
  separately or in combination with one another. Let's go back to the
  sample program you've been using to play with a simple example that uses
  a filter. There are several filter controls to set.
    You add line 15 in the program to set the cutoff frequency of the
  filter. The cutoff frequency is the reference point for the filter. You
  SET the high and low frequency cutoff points in registers 21 and 22. To
  turn ON the filter for voice 1, POKE register 23.
    Next change line 30 to show that a high-pass filter will be used (see
  the SID register map).

                                          PROGRAMMING SOUND AND MUSIC   199

EXAMPLE PROGRAM 5 (EXAMPLE 1 MODIFIED):

start tok64 page200.prg
  5 s=54272
  10 forl=stos+24:pokel,0:next
  15 pokes+22,128:pokes+21,0:pokes+23,1
  20 pokes+5,9:pokes+6,0
  30 pokes+24,79
  40 readhf,lf,dr
  50 ifhf<0thenend
  60 pokes+1,hf:pokes,lf
  70 pokes+4,33
  80 fort=1todr:next
  90 pokes+4,32:fort=1to50:next
  100 goto40
  110 data25,177,250,28,214,250
  120 data25,177,250,25,177,250
  130 data25,177,125,28,214,125
  140 data32,94,750,25,177,250
  150 data28,214,250,19,63,250
  160 data19,63,250,19,63,250
  170 data21,154,63,24,63,63
  180 data25,177,250,24,63,125
  190 data19,63,250,-1,-1,-1
stop tok64

    Try RUNning the program now. Notice the lower tones have had their
  volume cut down. It makes the overall quality of the note sound tinny.
  This is because you are using a high-pass filter which attenuates (cuts
  down the level of) frequencies below the specified cutoff frequency.
    There are three types of filters in your Commodore computer's SID chip.
  We have been using the high-pass filter. It will pass all the frequencies
  at or above the cutoff, while attenuating the frequencies below the
  cutoff.

                             |
                      AMOUNT |      +-----
                      PASSED |     /
                             |    /
                             |   /
                             +------|-------
                                FREQUENCY

  200   PROGRAMMING SOUND AND MUSIC

    The SID chip also has a low-pass filter. As its name implies, this
  filter will pass the frequencies below cutoff and attenuate those above.

                             |
                      AMOUNT | -----+
                      PASSED |       \
                             |        \
                             |         \
                             +------|-------
                                FREQUENCY

    Finally, the chip is equipped with a bandpass filter, which passes a
  narrow band of frequencies around the cutoff, and attenuates all others.

                             |
                      AMOUNT |      +
                      PASSED |     / \
                             |    /   \
                             |   /     \
                             +------|-------
                                FREQUENCY

    The high- and low-pass filters can be combined to form a notch reject
  filter which passes frequencies away from the cutoff while attenuating
  at the cutoff frequency.

                             |
                      AMOUNT | --+     +---
                      PASSED |    \   /
                             |     \ /
                             |      +
                             +------|-------
                                FREQUENCY

                                          PROGRAMMING SOUND AND MUSIC   201

    Register 24 determines which type filter you want to use. This is in
  addition to register 24's function as the overall volume control. Bit 6
  controls the high-pass filter (0 = off, 1 = on), bit 5 is the bandpass
  filter, and bit 4 is the low-pass filter. The low 3 bits of the cutoff
  frequency are determined by register 21 (Lcf) (Lcf = 0 through 7). While
  the 8 bits of the high cutoff frequency are determined by register 22
  (Hcf) (Hcf = 0 through 255).
    Through careful use of filtering, you can change the harmonic structure
  of any waveform to get just the sound you want. In addition, changing the
  filtering of a sound as it goes through the ADSR phases of its life can
  produce interesting effects.

  ADVANCED TECHNIQUES

    The SID chip's parameters can be changed dynamically during a note or
  sound to create many interesting and fun effects. In order to make this
  easy to do, digitized outputs from oscillator three and envelope
  generator three are available for you in registers 27 and 28, respec-
  tively.
    The output of oscillator 3 (register 27) is directly related to the
  waveform selected. If you choose the sawtooth waveform of oscillator 3,
  this register will present a series of numbers incremented (increased
  step by step) from 0 to 255 at a rate determined by the frequency of
  oscillator 3. If you choose the triangle waveform, the output will incre-
  ment from 0 up to 255, then decrement (decrease step by step) back down
  to 0. If you choose the pulse wave, the output will jump back-and-forth
  between 0 and 255. Finally, choosing the noise waveform will give you a
  series of random numbers. When oscillator 3 is used for modulation, you
  usually do NOT want to hear its output. Setting bit 7 of register 24
  turns the audio output of voice 3 off. Register 27 always reflects the
  changing output of the oscillator and is not affected in any way by the
  envelope (ADSR) generator.

  202   PROGRAMMING SOUND AND MUSIC

    Register 25 gives you access to the output of the envelope generator
  of oscillator 3. It functions in much the same fashion that the output of
  oscillator 3 does. The oscillator must be turned on to produce any output
  from this register.
    Vibrato (a rapid variation in frequency) can be achieved by adding the
  output of oscillator 3 to the frequency of another oscillator. Example
  Program 6 illustrates this idea.

  EXAMPLE PROGRAM 6:

start tok64 page203.prg
  10 s=54272
  20 forl=0to24:pokes+l,0:next
  30 pokes+3,8
  40 pokes+5,41:pokes+6,89
  50 pokes+14,117
  60 pokes+18,16
  70 pokes+24,143
  80 readfr,dr
  90 iffr=0thenend
  100 pokes+4,65
  110 fort=1todr*2
  120 fq=fr+peek(s+27)/2
  130 hf=int(fq/256):lf=lqand255
  140 pokes+0,lf:pokes+1,hf
  150 next
  160 pokes+4,64
  170 goto80
  500 data4817,2,5103,2,5407,2
  510 data8583,4,5407,2,8583,4
  520 data5407,4,8583,12,9634,2
  530 data10207,2,10814,2,8583,2
  540 data9634,4,10814,2,8583,2
  550 data8583,12
  560 data0,0
stop tok64

                                          PROGRAMMING SOUND AND MUSIC   203

  LINE-BY-LINE EXPLANATION OF EXAMPLE PROGRAM 6:

  +----------+------------------------------------------------------------+
  | Lines(s) |                        Description                         |
  +----------+------------------------------------------------------------+
  | 10       | Set S to beginning of sound chip.                          |
  | 20       | Clear all sound chip locations.                            |
  | 30       | Set high pulse width for voice 1.                          |
  | 40       | Set Attack/Decay for voice 1 (A=2, D=9).                   |
  |          | Set Sustain/Release for voice 1 (S=5, R=9).                |
  | 50       | Set low frequency for voice 3.                             |
  | 60       | Set triangle waveform for voice 3.                         |
  | 70       | Set volume 15, turn off audio output of voice 3.           |
  | 80       | Read frequency and duration of note.                       |
  | 90       | If frequency equals zero, stop.                            |
  | 100      | POKE start pulse waveform control voice 1.                 |
  | 110      | Start timing loop for duration.                            |
  | 120      | Get new frequency using oscillator 3 output.               |
  | 130      | Get high and low frequency.                                |
  | 140      | POKE high and low frequency for voice 1.                   |
  | 150      | End of timing loop.                                        |
  | 160      | POKE stop pulse waveform control voice 1.                  |
  | 170      | Go back for next note.                                     |
  | 500-550  | Frequencies and durations for song,                        |
  | 560      | Zeros signal end of song.                                  |
  +----------+------------------------------------------------------------+

    A wide variety of sound effects can also be achieved using dynamic
  effects. For example, the following siren program dynamically changes the
  frequency output of oscillator 1 when it's based on the output of
  oscillator 3's triangular wave:

  204   PROGRAMMING SOUND AND MUSIC

  EXAMPLE PROGRAM 7:

start tok64 page205.prg
  10 s=54272
  20 forl=0to24:pokes+l,0:next
  30 pokes+14,5
  40 pokes+18,16
  50 pokes+3,1
  60 pokes+24,143
  70 pokes+6,240
  80 pokes+4,65
  90 fr=5389
  100 fort=1to200
  110 fq=fr+peek(s+27)*3.5
  120 hf=int(fq/256):lf=fq-hf*256
  130 pokes+0,lf:pokes+1,hf
  140 next
  150 pokes+24,0
stop tok64

  LINE-BY-LINE EXPLANATION OF EXAMPLE PROGRAM 7:

  +---------+-------------------------------------------------------------+
  | Line(s) |                         Description                         |
  +---------+-------------------------------------------------------------+
  | 10      | Set S to start of sound chip.                               |
  | 20      | Clear sound chip registers.                                 |
  | 30      | Set low frequency of voice 3.                               |
  | 40      | Set triangular waveform voice 3.                            |
  | 50      | Set high pulse width for voice 1.                           |
  | 60      | Set volume 15, turn off audio output of voice 3.            |
  | 70      | Set Sustain/Release for voice I (S=15, R=0).                |
  | 80      | POKE start pulse waveform control voice 1.                  |
  | 90      | Set lowest frequency for siren.                             |
  | 100     | Begin timing loop.                                          |
  | 110     | Get new frequency using output of oscillator 3.             |
  | 120     | Get high and low frequencies.                               |
  | 130     | POKE high.and low frequencies for voice 1.                  |
  | 140     | End timing loop.                                            |
  | 150     | Turn off volume.                                            |
  +---------+-------------------------------------------------------------+

                                          PROGRAMMING SOUND AND MUSIC   205

    The noise waveform can be used to provide a wide range of sound
  effects. This example mimics a hand clap using a filtered noise waveform:

  EXAMPLE PROGRAM 8:

start tok64 page206.prg
  10 s=54272
  20 forl=0to24:pokes+l,0:next
  30 pokes+0,240:pokes+1,33
  40 pokes+5,8
  50 pokes+22,104
  60 pokes+23,1
  70 pokes+24,79
  80 forn=1to15
  90 pokes+4,129
  100 fort=1to250:next:pokes+4,128
  110 fort=1to30:next:next
  120 pokes+24,0
stop tok64

  LINE-BY-LINE EXPLANATION OF EXAMPLE PROGRAM 8:

  +---------+-------------------------------------------------------------+
  | Line(s) |                         Description                         |
  +---------+-------------------------------------------------------------+
  |    10   | Set S to start of sound chip.                               |
  |    20   | Clear all sound chip registers.                             |
  |    30   | Set high and low frequencies for voice 1.                   |
  |    40   | Set Attack/Decay for voice I (A=0, D=8).                    |
  |    50   | Set high cutoff frequency for filter.                       |
  |    60   | Turn on filter for voice 1.                                 |
  |    70   | Set volume 15, high-pass filter.                            |
  |    80   | Count 15 claps.                                             |
  |    90   | Set start noise waveform control.                           |
  |   100   | Wait, then set stop noise waveform control.                 |
  |   110   | Wait, then start next clap-                                 |
  |   120   | Turn off volume.                                            |
  +---------+-------------------------------------------------------------+

  206   PROGRAMMING SOUND AND MUSIC

  SYNCHRONIZATION AND RING MODULATION

    The 6581 SID chip lets you create more complex harmonic structures
  through synchronization or ring modulation of two voices.
    The process of synchronization is basically a logical ANDing of two
  wave forms. When either is zero, the output is zero. The following
  example uses this process to create an imitation of a mosquito:

  EXAMPLE PROGRAM 9:

start tok64 page207.prg
  10 s=54272
  20 forl=0to24:pokes+l,0:next
  30 pokes+1,100
  40 pokes+5,219
  50 pokes+15,28
  60 pokes+24,15
  70 pokes+4,19
  80 fort=1to5000:next
  90 pokes+4,18
  100 fort=1to1000:next:pokes+24,0
stop tok64

  LINE-BY-LINE EXPLANATION OF EXAMPLE PROGRAM 9:
  +---------+-------------------------------------------------------------+
  | Line(s) |                     Description                             |
  +---------+-------------------------------------------------------------+
  |   10    | Set S to start of sound chip.                               |
  |   20    | Clear sound chip registers.                                 |
  |   30    | Set high frequency voice 1.                                 |
  |   40    | Set Attack/Decay for voice 1 (A=13, D=11).                  |
  |   50    | Set high frequency voice 3.                                 |
  |   60    | Set volume 15.                                              |
  |   70    | Set start triangle, sync waveform control for voice 1.      |
  |   80    | Timing loop.                                                |
  |   90    | Set stop triangle, sync waveform control for voice 1.       |
  |  100    | Wait, then turn off volume.                                 |
  +-----------------------------------------------------------------------+
    The synchronization feature is enabled (turned on) in line 70, where
  bits 0, 1, and 4 of register 4 are set. Bit 1 enables the syncing
  function between voice 1 and voice 3. Bits 0 and 4 have their usual
  functions of gating voice 1 and setting the triangular waveform.

                                          PROGRAMMING SOUND AND MUSIC   207

    Ring modulation (accomplished for voice 1 by setting bit 3 of register
  4 in line 70 of the program below) replaces the triangular output of
  oscillator I with a "ring modulated" combination of oscillators 1 and 3.
  This produces non-harmonic overtone structures for use in mimicking bell
  or gong sounds. This program produces a clock chime imitation:

  EXAMPLE PROGRAM 10:
start tok64 page208.prg
  10 s=54272
  20 forl=0to24:pokes+l,0:next
  30 pokes+1,130
  40 pokes+5,9
  50 pokes+15,30
  60 pokes+24,15
  70 forl=1to12:pokes+4,21
  80 fort=1to1000:next:pokes+4,20
  90 fort=1to1000:next:next
stop tok64

  LINE-BY-LINE EXPLANATION OF EXAMPLE PROGRAM 10:
  +---------+-------------------------------------------------------------+
  | Line(s) |                     Description                             |
  +---------+-------------------------------------------------------------+
  |   10    | Set S to start of sound chip.                               |
  |   20    | Clear sound chip registers.                                 |
  |   30    | Set high frequency for voice 1.                             |
  |   40    | Set Attack/Decay for voice 1 (A=0, D=9).                    |
  |   50    | Set high frequency for voice 3.                             |
  |   60    | Set volume 15.                                              |
  |   70    | Count number of clings, set start triangle, ring mod        |
  |         | waveform control voice 1.                                   |
  |   80    | Timing loop, set stop triangle, ring mod.                   |
  |   90    | Timing loop, next ding.                                     |
  +---------+-------------------------------------------------------------+
    The effects available through the use of the parameters of your
  Commodore 64's SID chip are numerous and varied. Only through ex-
  perimentation on your own will you fully appreciate the capabilities of
  your machine. The examples in this section of the Programmer's Reference
  Guide merely scratch the surface.
    Watch for the book MAKING MUSIC ON YOUR COMMODORE COMPUTER for
  everything from simple fun and games to professional-type musical
  instruction.

  208   PROGRAMMING SOUND AND MUSIC

                                                 CHAPTER 5

                                                  BASIC TO
                                                   MACHINE
                                                  LANGUAGE

                           o What Is Machine Language?
                           o How Do You Write Machine
                             Language Programs?
                           o Hexadecimal Notation
                           o Addressing Modes
                           o Indexing
                           o Subroutines
                           o Useful Tips for the Beginner
                           o Approaching a Large Task
                           o MCS6510 Microprocessor
                             Instruction Set
                           o Memory Management on the
                             Commodore 64
                           o The KERNAL
                           o KERNAL Power-Up Activities
                           o Using Machine Language From
                             BASIC
                           o Commodore 64 Memory Map

                                     209

  WHAT IS MACHINE LANGUAGE?

    At the heart of every microcomputer, is a central microprocessor. It's
  a very special microchip which is the "brain" of the computer. The
  Commodore 64 is no exception. Every microprocessor understands its own
  language of instructions. These instructions are called machine language
  instructions. To put it more precisely, machine language is the ONLY
  programming language that your Commodore 64 understands. It is the NATIVE
  language of the machine.
    If machine language is the only language that the Commodore 64
  understands, then how does it understand the CBM BASIC programming
  language? CBM BASIC is NOT the machine language of the Commodore 64.
  What, then, makes the Commodore 64 understand CBM BASIC instructions like
  PRINT and GOTO?
    To answer this question, you must first see what happens inside your
  Commodore 64. Apart from the microprocessor which is the brain of the
  Commodore 64, there is a machine language program which is stored in a
  special type of memory so that it can't be changed. And, more impor-
  tantly, it does not disappear when the Commodore 64 is turned off, unlike
  a program that you may have written. This machine language program is
  called the OPERATING SYSTEM of the Commodore 64. Your Commodore 64 knows
  what to do when it's turned on because its OPERATING SYSTEM (program) is
  automatically "RUN."

  210   BASIC TO MACHINE LANGUAGE

    The OPERATING SYSTEM is in charge of "organizing" all the memory in
  your machine for various tasks. It also looks at what characters you type
  on the keyboard and puts them onto the screen, plus a whole number of
  other functions. The OPERATING SYSTEM can be thought of as the
  "intelligence and personality" of the Commodore 64 (or any computer for
  that matter). So when you turn on your Commodore 64, the OPERATING SYSTEM
  takes control of your machine, and after it has done its housework, it
  then says:

    READY.

    The OPERATING SYSTEM of the Commodore 64 then allows you to type on the
  keyboard, and use the built-in SCREEN EDITOR on the Commodore 64. The
  SCREEN EDITOR allows you to move the cursor, DELete, INSert, etc., and
  is, in fact, only one part of the operating system that is built in for
  your convenience.
    All of the commands that are available in CBM BASIC are simply
  recognized by another huge machine language program built into your
  Commodore 64. This huge program "RUNS" the appropriate piece of machine
  language depending on which CBM BASIC command is being executed. This
  program is called the BASIC INTERPRETER, because it interprets each
  command, one by one, unless it encounters a command it does not
  understand, and then the familiar message appears:

    ?SYNTAX ERROR

    READY.

  WHAT DOES MACHINE CODE LOOK LIKE?

    You should be familiar with the PEEK and POKE commands in the CBM BASIC
  language for changing memory locations. You've probably used them for
  graphics on the screen, and for sound effects. Each memory location has
  its own number which identifies it. This number is known as the "address"
  of a memory location. If you imagine the memory in the Commodore 64 as a
  street of buildings, then the number on each door is, of course, the
  address. Now let's look at which parts of the street are used for what
  purposes.

                                            BASIC TO MACHINE LANGUAGE   211

  SIMPLE MEMORY MAP OF THE COMMODORE 64

  +-------------+---------------------------------------------------------+
  |   ADDRESS   |                      DESCRIPTION                        |
  +-------------+---------------------------------------------------------+
  |             |                                                         |
  |    0 & 1    | -6510 Registers.                                        |
  |             |                                                         |
  |     2       | -Start of memory.                                       |
  |             |                                                         |
  |     2-1023  | -Memory used by the operating system.                   |
  |             |                                                         |
  |  1024-2039  | -Screen memory.                                         |
  |             |                                                         |
  |  2040-2047  | -SPRITE pointers.                                       |
  |             |                                                         |
  |  2048-40959 | -This is YOUR memory. This is where your BASIC or       |
  |             |  machine language programs, or both, are stored.        |
  |             |                                                         |
  | 40960-49151 | -8K CBM BASIC Interpreter.                              |
  |             |                                                         |
  | 49152-53247 | -Special programs RAM area.                             |
  |             |                                                         |
  | 53248-53294 | -VIC-II.                                                |
  |             |                                                         |
  | 54272-55295 | -SID Registers.                                         |
  |             |                                                         |
  | 55296-56296 | -Color RAM.                                             |
  |             |                                                         |
  | 56320-57343 | -I/O Registers. (6526's)                                |
  |             |                                                         |
  | 57344-65535 | -8K CBM KERNAL Operating System.                        |
  |             |                                                         |
  +-------------+---------------------------------------------------------+

  212   BASIC TO MACHINE LANGUAGE

    If you don't understand what the description of each part of memory
  means right now, this will become clear from other parts of this manual.
    Machine language programs consist of instructions which may or may not
  have operands (parameters) associated with them. Each instruction takes
  up one memory location, and any operand is contained in one or two
  locations following the instruction.
    In your BASIC programs, words like PRINT and GOTO do, in fact, only
  take up one memory location, rather than one for each character of the
  word. The contents of the location that represents a particular BASIC
  keyword is called a token. In machine language, there are different
  tokens for different instructions, which also take up just one byte (mem-
  ory location=byte).
    Machine language instructions are very simple. Therefore, each indi-
  vidual instruction cannot achieve a great deal. Machine language in-
  structions either change the contents of a memory location, or change one
  of the internal registers (special storage locations) inside the micro-
  processor. The internal registers form the very basis of machine lan-
  guage.

  THE REGISTERS INSIDE THE 6510 MICROPROCESSOR

  THE ACCUMULATOR

    This is THE most important register in the microprocessor. Various ma-
  chine language instructions allow you to copy the contents of a memory
  location into the accumulator, copy the contents of the accumulator into
  a memory location, modify the contents of the accumulator or some other
  register directly, without affecting any memory. And the accumulator is
  the only register that has instructions for performing math.

  THE X INDEX REGISTER

    This is a very important register. There are instructions for nearly
  all of the transformations you can make to the accumulator. But there are
  other instructions for things that only the X register can do. Various
  machine language instructions allow you to copy the contents of a memory
  location into the X register, copy the contents of the X register into a
  memory location, and modify the contents of the X, or some other register
  directly.

                                            BASIC TO MACHINE LANGUAGE   213

  THE Y INDEX REGISTER

    This is a very important register. There are instructions for nearly
  all of the transformations you can make to the accumulator, and the X
  register. But there are other instructions for things that only the Y
  register can do. Various machine language instructions allow you to copy
  the contents of a memory location into the Y register, copy the contents
  of the Y register into a memory location, and modify the contents of the
  Y, or some other register directly.

  THE STATUS REGISTER

    This register consists of eight "flags" (a flag = something that indi-
  cates whether something has, or has not occurred).

  THE PROGRAM COUNTER

    This contains the address of the current machine language instruction
  being executed. Since the operating system is always "RUN"ning in the
  Commodore 64 (or, for that matter, any computer), the program counter is
  always changing. It could only be stopped by halting the microprocessor
  in some way.

  THE STACK POINTER

    This register contains the location of the first empty place on the
  stack. The stack is used for temporary storage by machine language pro-
  grams, and by the computer.

  THE INPUT/OUTPUT PORT

    This register appears at memory locations 0 (for the DATA DIRECTION
  REGISTER) and 1 (for the actual PORT). It is an 8-bit input/output port.
  On the Commodore 64 this register is used for memory management, to
  allow the chip to control more than 64K of RAM and ROM memory.
    The details of these registers are not given here. They are explained
  as the principles needed to explain them are explained.

  HOW DO YOU WRITE MACHINE LANGUAGE PROGRAMS?

    Since machine language programs reside in memory, and there is no
  facility in your Commodore 64 for writing and editing machine language

  214   BASIC TO MACHINE LANGUAGE

  programs, you must use either a program to do this, or write for yourself
  a BASIC program that "allows" you to write machine language.
    The most common methods used to write machine language programs are
  assembler programs. These packages allow you to write machine language
  instructions in a standardized mnemonic format, which makes the machine
  language program a lot more readable than a stream of numbers! Let's
  review: A program that allows you to write machine language programs in
  mnemonic format is called an assembler. Incidentally, a program that
  displays a machine language program in mnemonic format is called a
  disassembler. Available for your Commodore 64 is a machine language
  monitor cartridge (with assembler/disassembler, etc.) made by Commodore:

  64MON

    The 64MON cartridge available from your local dealer, is a program that
  allows you to escape from the world of CBM BASIC, into the land of
  machine language. It can display the contents of the internal registers
  in the 6510 microprocessor, and it allows you to display portions of mem-
  ory, and change them on the screen, using the screen editor. It also has
  a built-in assembler and disassembler, as well as many other features
  that allow you to write and edit machine language programs easily. You
  don't HAVE to use an assembler to write machine language, but the task is
  considerably easier with it. If you wish to write machine language
  programs, it is strongly suggested that you purchase an assembler of some
  sort. Without an assembler you will probably have to "POKE" the machine
  language program into memory, which is totally unadvisable. This manual
  will give its examples in the format that 64MON uses, from now on. Nearly
  all assembler formats are the same, therefore the machine language
  examples shown will almost certainly be compatible with any assembler.
  But before explaining any of the other features of 64MON, the hexadecimal
  numbering system must be explained.

  HEXADECIMAL NOTATION

  Hexadecimal notation is used by most machine language programmers when
  they talk about a number or address in a machine language program.
    Some assemblers let you refer to addresses and numbers in decimal
  (base 10), binary (base 2), or even octal (base 8) as well as hexadecimal

                                            BASIC TO MACHINE LANGUAGE   215

  (base 16) (or just "hex" as most people say). These assemblers do the
  conversions for you.
    Hexadecimal probably seems a little hard to grasp at first, but like
  most things, it won't take long to master with practice.
    By looking at decimal (base 10) numbers, you can see that each digit
  fails somewhere in the range between zero and a number equal to the base
  less one (e.g., 9). THIS IS TRUE OF ALL NUMBER BASES. Binary (base 2)
  numbers have digits ranging from zero to one (which is one less than the
  base). Similarly, hexadecimal numbers should have digits ranging from
  zero to fifteen, but we do not have any single digit figures for the
  numbers ten to fifteen, so the first six letters of the alphabet are used
  instead:

                    +---------+-------------+----------+
                    | DECIMAL | HEXADECIMAL |  BINARY  |
                    +---------+-------------+----------+
                    |    0    |      0      | 00000000 |
                    |    1    |      1      | 00000001 |
                    |    2    |      2      | 00000010 |
                    |    3    |      3      | 00000011 |
                    |    4    |      4      | 00000100 |
                    |    5    |      5      | 00000101 |
                    |    6    |      6      | 00000110 |
                    |    7    |      7      | 00000111 |
                    |    8    |      8      | 00001000 |
                    |    9    |      9      | 00001001 |
                    |   10    |      A      | 00001010 |
                    |   11    |      B      | 00001011 |
                    |   12    |      C      | 00001100 |
                    |   13    |      D      | 00001101 |
                    |   14    |      E      | 00001110 |
                    |   15    |      F      | 00001111 |
                    |   16    |     10      | 00010000 |
                    +---------+-------------+----------+

  216   BASIC TO MACHINE LANGUAGE

    Let's look at it another way; here's an example of how a base 10
  (decimal number) is constructed:

    Base raised by
    increasing powers:... 10^3 10^2 10^1 10^0
                         ---------------------
    Equals:.............. 1000  100   10    1
                         ---------------------

    Consider 4569 (base 10)  4    5    6    9 = (4*1000)+(5*100)+(6*10)+9

  Now look at an example of how a base 16 (hexadecimal number) is
  constructed:

    Base raised by
    increasing powers:... 16^3 16^2 16^1 16^0
                         ---------------------
    Equals:.............. 4096  256   16    1
                         ---------------------

    Consider 11D9 (base 16)  1    1    D    9 = 1*4096+1*256+13*16+9

  Therefore, 4569 (base 10) = 11D9 (base 16)
    The range for addressable memory locations is 0-65535 (as was stated
  earlier). This range is therefore 0-FFFF in hexadecimal notation.
    Usually hexadecimal numbers are prefixed with a dollar sign ($). This
  is to distinguish them from decimal numbers. Let's look at some "hex"
  numbers, using 64MON, by displaying the contents of some memory by
  typing:

    SYS 8*4096   (or SYS 12*4096)
    B*
       PC  SR AC XR YR SP
    .;0401 32 04 5E 00 F6 (these may be different)

  Then if you type in:

  .M 0000 0020 (and press <RETURN>).

  you will see rows of 9 hex numbers. The first 4-digit number is the ad-
  dress of the first byte of memory being shown in that row, and the other
  eight numbers are the actual contents of the memory locations beginning
  at that start address.
                                            BASIC TO MACHINE LANGUAGE   217

    You should really try to learn to "think" in hexadecimal. It's not too
  difficult, because you don't have to think about converting it back into
  decimal. For example, if you said that a particular value is stored at
  $14ED instead of 5357, it shouldn't make any difference.

  YOUR FIRST MACHINE LANGUAGE INSTRUCTION

  LDA - LOAD THE ACCUMULATOR

    In 6510 assembly language, mnemonics are always three characters. LDA
  represents "load accumulator with...", and what the accumulator should be
  loaded with is decided by the parameter(s) associated with that
  instruction. The assembler knows which token is represented by each
  mnemonic, and when it "assembles" an instruction, it simply puts into
  memory (at whatever address has been specified), the token, and what
  parameters, are given. Some assemblers give error messages, or warnings
  when you try to assemble something that either the assembler, or the 6510
  microprocessor, cannot do.
    If you put a "#" symbol in front of the parameter associated with the
  instruction, this means that you want the register specified in the
  instruction to be loaded with the "value" after the "#". For example:

    LDA #$05  <----[ $=HEX ]

  This instruction will put $05 (decimal 5) into the accumulator register.
  The assembler will put into the specified address for this instruction,
  $A9 (which is the token for this particular instruction, in this mode),
  and it will put $05 into the next location after the location containing
  the instruction ($A9).
    If the parameter to be used by an instruction has "#" before it; i.e.,
  the parameter is a "value," rather than the contents of a memory loca-
  tion, or another register, the instruction is said to be in the
  "immediate" mode. To put this into perspective, let's compare this with
  another mode:
    If you want to put the contents of memory location $102E into the
  accumulator, you're using the "absolute" mode of instruction:

    LDA $102E

  The assembler can distinguish between the two different modes because the
  latter does not have a "#" before the parameter. The 6510 microprocessor

  218   BASIC TO MACHINE LANGUAGE

  can distinguish between the immediate mode, and the absolute mode of the
  LDA instruction, because they have slightly different tokens. LDA
  (immediate) has $A9 as its token, and LDA (absolute), has $AD as its
  token.
    The mnemonic representing an instruction usually implies what it does.
  For instance, if we consider another instruction, LDX, what do you think
  this does?
    If you said "load the X register with...", go to the top of the class.
  If you didn't, then don't worry, learning machine language does take
  patience, and cannot be learned in a day.
    The various internal registers can be thought of as special memory
  locations, because they too can hold one byte of information. It is not
  necessary for us to explain the binary numbering system (base 2) since it
  follows the same rules as outlined for hexadecimal and decimal outlined
  previously, but one "bit" is one binary digit and eight bits make up one
  byte! This means that the maximum number that can be contained in a
  byte is the largest number that an eight digit binary number can be. This
  number is 11111111 (binary), which equals $FF (hexadecimal), which equals
  255 (decimal). You have probably wondered why only numbers from zero to
  255 could be put into a memory location. If you try POKE 7680,260 (which
  is a BASIC statement that "says": "Put the number two hundred and sixty,
  into memory location seven thousand, six hundred and eighty", the BASIC
  interpreter knows that only numbers 0 - 255 can be put in a memory
  location, and your Commodore 64 will reply with:

    ?ILLEGAL QUANTITY ERROR

    READY.

  If the limit of one byte is $FF (hex), how is the address parameter in
  the absolute instruction "LDA $102E" expressed in memory? It's expressed
  in two bytes (it won't fit into one, of course). The lower (rightmost)
  two digits of the hexadecimal address form the "low byte" of the address,
  and the upper (leftmost) two digits form the "high byte."
    The 6510 requires any address to be specified with its low byte first,
  and then the high byte. This means that the instruction "LDA $102E" is
  represented in memory by the three consecutive values:

    $AD, $2E, $10

  Now all you need to know is one more instruction and then you can write
  your first program. That instruction is BRK. For a full explanation of

                                            BASIC TO MACHINE LANGUAGE   219

  this I instruction, refer to M.O.S. 6502 Programming Manual. But right
  now, you can think of it as the END instruction in machine language.
    If we write a program with 64MON and put the BRK instruction at the
  end, then when the program is executed, it will return to 64MON when it
  is finished. This might not happen if there is a mistake in your program,
  or the BRK instruction is never reached (just like an END statement in
  BASIC may never get executed). This means that if the Commodore 64 didn't
  have a STOP key, you wouldn't be able to abort your BASIC programs!

  WRITING YOUR FIRST PROGRAM

    If you've used the POKE statement in BASIC to put characters onto the
  screen, you're aware that the character codes for POKEing are different
  from CBM ASCII character values. For example, if you enter:

    PRINT ASC("A") (and press <RETURN> )

  the Commodore 64 will respond with:

    65

    READY.

  However, to put an "A" onto the screen by POKEing, the code is 1, enter:

    <SHIFT+CLR/HOME> to clear the screen

    POKE 1024,1:POKE 55296,14 (and <RETURN> (1024 is the start of screen
    memory)

  The "P" in the POKE statement should now be an "A."
    Now let's try this in machine language. Type the following in 64MON:
  (Your cursor should be flashing alongside a "." right now.)

    .A 1400 LDA#$01 (and press <RETURN>)

  220   BASIC TO MACHINE LANGUAGE

  The Commodore 64 will prompt you with:

    .A 1400 A9 01      LDA #$01
    .A 1402

  Type:

    .A 1402 STA $0400

  (The STA instruction stores the contents of the accumulator in a
  specified memory location.)
  The Commodore 64 will prompt you with:

    .A 1405

  Now type in:

    .A 1405 LDA #$0E
    .A 1407 STA $D800
    .A 140A BRK

  Clear the screen, and type:

    G 1400

    The G should turn into an "A" if you've done everything correctly. You
  have now written your first machine language program. Its purpose is to
  store one character ("A") at the first location in the screen memory.
  Having achieved this, we must now explore some of the other instructions,
  and principles.

  ADDRESSING MODES

  ZERO PAGE

    As shown earlier, absolute addresses are expressed in terms of a high
  and a low order byte. The high order byte is often referred to as the
  page of memory. For example, the address $1637 is in page $16 (22), and
  $0277 is in page $02 (2). There is, however, a special mode of addressing
  known as zero page addressing and is, as the name implies, associated

                                            BASIC TO MACHINE LANGUAGE   221

  with the addressing of memory locations in page zero. These addresses,
  therefore, ALWAYS have a high order byte of zero. The zero page mode of
  addressing only expects one byte to describe the address, rather than two
  when using an absolute address. The zero page addressing mode tells the
  microprocessor to assume that the high order address is zero. Therefore
  zero page addressing can reference memory locations whose addresses are
  between $0000 and $00FF. This may not seem too important at the moment,
  but you'll need the principles of zero page addressing soon.

  THE STACK

    The 6510 microprocessor has what is known as a stack. This is used by
  both the programmer and the microprocessor to temporarily remember
  things, and to remember, for example, an order of events. The GOSUB
  statement in BASIC, which allows the programmer to call a subroutine,
  must remember where it is being called from, so that when the RETURN
  statement is executed in the subroutine, the BASIC interpreter "knows"
  where to go back to continue executing. When a GOSUB statement is
  encountered in a program by the BASIC interpreter, the BASIC interpreter
  "pushes" its current position onto the stack before going to do the
  subroutine, and when a RETURN is executed, the interpreter "pulls" off
  the stack the information that tells it where it was before the
  subroutine call was made. The interpreter uses instructions like PHA,
  which pushes the contents of the accumulator onto the stack, and PLA (the
  reverse) which pulls a value off the stack and into the accumulator. The
  status register can also be pushed and pulled with the PHP and PLP,
  respectively.
    The stack is 256 bytes long, and is located in page one of memory. It
  is therefore from $01 00 to $01 FF. It is organized backwards in memory.
  In other words, the first position in the stack is at $01 FF, and the
  last is at $0100. Another register in the 651 0 microprocessor is called
  the stack pointer, and it always points to the next available location in
  the stack. When something is pushed onto the stack, it is placed where
  the stack pointer points to, and the stack pointer is moved down to the
  next position (decremented). When something is pulled off the stack, the
  stack pointer is incremented, and the byte pointed to by the stack
  pointer is placed into the specified register.

  222   BASIC TO MACHINE LANGUAGE

    Up to this point, we have covered immediate, zero page, and absolute
  mode instructions. We have also covered, but have not really talked
  about, the "implied" mode. The implied mode means that information is
  implied by an instruction itself. In other words, what registers, flags,
  and memory the instruction is referring to. The examples we have seen are
  PHA, PLA, PHP, and PLP, which refer to stack processing and the
  accumulator and status registers, respectively.

  +-----------------------------------------------------------------------+
  | NOTE: The X register will be referred to as X from now on, and        |
  | similarly A (accumulator), Y (Y index register), S (stack pointer),   |
  | and P (processor status).                                             |
  +-----------------------------------------------------------------------+

  INDEXING

    Indexing plays an extremely important part in the running of the 6510
  microprocessor. It can be defined as "creating an actual address from a
  base address plus the contents of either the X or Y index registers."
    For example, if X contains $05, and the microprocessor executes an LDA
  instruction in the "absolute X indexed mode" with base address (e.g.,
  $9000), then the actual location that is loaded into the A register is
  $9000 + $05 = $9005. The mnemonic format of an absolute indexed
  instruction is the same as an absolute instruction except a ",X" or ",Y"
  denoting the index is added to the address.

  EXAMPLE:

    LDA $9000,X

    There are absolute indexed, zero page indexed, indirect indexed, and
  indexed indirect modes of addressing available on the 6510
  microprocessor.

  INDIRECT INDEXED

    This only allows usage of the Y register as the index. The actual ad-
  dress can only be in zero page, and the mode of instruction is called
  indirect because the zero page address specified in the instruction con-
  tains the low byte of the actual address, and the next byte to it
  contains the high order byte.

                                            BASIC TO MACHINE LANGUAGE   223

  EXAMPLE:

    Let us suppose that location $02 contains $45, and location $03 con-
  tains $1E. If the instruction to load the accumulator in the indirect
  indexed mode is executed and the specified zero page address is $02, then
  the actual address will be:

    Low order = contents of $02
    High order = contents of $03
    Y register = $00

  Thus the actual address = $1E45 + Y = $1E45.
    The title of this mode does in fact imply an indirect principle,
  although this may be difficult to grasp at first sight. Let's look at it
  another way:
    "I am going to deliver this letter to the post office at address $02,
  MEMORY ST., and the address on the letter is $05 houses past $1600,
  MEMORY street." This is equivalent to the code:

    LDA #$00      - load low order actual base address
    STA $02       - set the low byte of the indirect address
    LDA #$16      - load high order indirect address
    STA $03       - set the high byte of the indirect address
    LDY #$05      - set the indirect index (Y)
    LDA ($02),Y   - load indirectly indexed by Y

  INDEXED INDIRECT

    Indexed indirect only allows usage of the X register as the index. This
  is the some as indirect indexed, except it is the zero page address of
  the pointer that is indexed, rather than the actual base address.
  Therefore, the actual base address IS the actual address because the
  index has already been used for the indirect. Index indirect would also
  be used if a table of indirect pointers were located in zero page memory,
  and the X register could then specify which indirect pointer to use.

  224   BASIC TO MACHINE LANGUAGE

  EXAMPLE:

    Let us suppose that location $02 contains $45, and location $03 con-
  tains $10. If the instruction to load the accumulator in the indexed
  indirect mode is executed and the specified zero page address is $02,
  then the actual address will be:

    Low order = contents of ($02+X)
    High order = contents of ($03+X)
    X register = $00

  Thus the actual pointer is in = $02 + X = $02.
    Therefore, the actual address is the indirect address contained in $02
  which is again $1045.
    The title of this mode does in fact imply the principle, although it
  may be difficult to grasp at first sight. Look at it this way:
    "I am going to deliver this letter to the fourth post office at address
  $01,MEMORY ST., and the address on the letter will then be delivered to
  $1600, MEMORY street." This is equivalent to the code:

    LDA #$00    - load low order actual base address
    STA $06     - set the low byte of the indirect address
    LDA #$16    - load high order indirect address
    STA $07     - set the high byte of the indirect address
    LDX #$05    - set the indirect index (X)
    LDA ($02,X) - load indirectly indexed by X

  +-----------------------------------------------------------------------+
  | NOTE: Of the two indirect methods of addressing, the first (indirect  |
  | indexed) is far more widely used.                                     |
  +-----------------------------------------------------------------------+

                                            BASIC TO MACHINE LANGUAGE   225

  BRANCHES AND TESTING

    Another very important principle in machine language is the ability to
  test, and detect certain conditions, in a similar fashion to the "IF...
  THEN, IF... GOTO" structure in CBM BASIC.
    The various flags in the status register are affected by different in-
  structions in different ways. For example, there is a flag that is set
  when an instruction has caused a zero result, and is reset when a result
  is not zero. The instruction:

    LDA #$00

  will cause the zero result flag to be set, because the instruction has
  resulted in the accumulator containing a zero.
    There are a set of instructions that will, given a particular
  condition, branch to another part of the program. An example of a branch
  instruction is BEQ, which means Branch if result EQual to zero. The
  branch instructions branch if the condition is true, and if not, the
  program continues onto the next instruction, as if nothing had occurred.
  The branch instructions branch not by the result of the previous
  instructions), but by internally examining the status register. As was
  just mentioned, there is a zero result flag in the status register. The
  BEQ instruction branches if the zero result flag (known as Z) is set.
  Every branch instruction has an opposite branch instruction. The BEQ
  instruction has an opposite instruction BNE, which means Branch on result
  Not Equal to zero (i.e., Z not set).
    The index registers have a number of associated instructions which
  modify their contents. For example, the INX instruction INcrements the X
  index register. If the X register contained $FF before it was incremented
  (the maximum number the X register can contain), it will "wrap around"
  back to zero. If you wanted a program to continue to do something until
  you had performed the increment of the X index that pushed it around to
  zero, you could use the BNE instruction to continue "looping" around,
  until X became zero.
    The reverse of INX, is DEX, which is DEcrement the X index register. If
  the X index register is zero, DEX wraps around to $FF. Similarly, there
  are INY and DEY for the Y index register.

  226   BASIC TO MACHINE LANGUAGE

    But what if a program didn't want to wait until X or Y had reached (or
  not reached) zero? Well there are comparison instructions, CPX and CPY,
  which allow the machine language programmer to test the index registers
  with specific values, or even the contents of memory locations. If you
  wanted to see if the X register contained $40, you would use the
  instruction:

    CPX #$40         - compare X with the "value" $40.
    BEQ              - branch to somewhere else in the
    (some other        program, if this condition is "true."
     part of the
     program)

  The compare, and branch instructions play a major part in any machine
  language program.
    The operand specified in a branch instruction when using 64MON is the
  address of the part of the program that the branch goes to when the
  proper conditions are met. However, the operand is only an offset, which
  gets you from where the program currently is to the address specified.
  This offset is just one byte, and therefore the range that a branch
  instruction can branch to is limited. It can branch from 128 bytes back-
  ward, to 127 bytes forward.

  +-----------------------------------------------------------------------+
  | NOTE: This is a total range of 255 bytes which is, of course, the     |
  | maximum range of values one byte can contain.                         |
  +-----------------------------------------------------------------------+

    64MON will tell you if you "branch out of range" by refusing to "as-
  semble" that particular instruction. But don't worry about that now be-
  cause it's unlikely that you will have such branches for quite a while.
  The branch is a "quick" instruction by machine language standards because
  of the "offset" principle as opposed to an absolute address. 64MON allows
  you to type in an absolute address, and it calculates the correct offset.
  This is just one of the "comforts" of using an assembler.

  +-----------------------------------------------------------------------+
  | NOTE: It is NOT possible to cover every single branch instruction. For|
  | further information, refer to the Bibliography section in Appendix F. |
  +-----------------------------------------------------------------------+

                                            BASIC TO MACHINE LANGUAGE   227

  SUBROUTINES

    In machine language (in the same way as using BASIC), you can call
  subroutines. The instruction to call a subroutine is JSR (Jump to Sub-
  Routine), followed by the specified absolute address.
    Incorporated in the operating system, there is a machine language
  subroutine that will PRINT a character to the screen. The CBM ASCII code
  of the character should be in the accumulator before calling the
  subroutine. The address of this subroutine is $FFD2.
    Therefore, to print "Hi" to the screen, the following program should be
  entered:

    .A 1400 LDA #$48     - load the CBM ASCII code of "H"
    .A 1402 JSR $FFD2    -  print it
    .A 1405 LDA #$49     - load the CBM ASCII code of "I"
    .A 1407 JSR $FFD2    -  print that too
    .A 140A LDA #$0D     - print a carriage return as well
    .A 140C JSR $FFD2
    .A 140F BRK          - return to 64MON
    .G 1400              - will print "HI" and return to 64MON

    The "PRINT a character" routine we have just used is part of the KERNAL
  jump table. The instruction similar to GOTO in BASIC is JMP, which means
  JUMP to the specified absolute address. The KERNAL is a long list of
  "standardized" subroutines that control ALL input and output of the
  Commodore 64. Each entry in the KERNAL JMPs to a subroutine in the
  operating system. This "jump table" is found between memory locations
  $FF84 to $FFF5 in the operating system. A full explanation of the KERNAL
  is available in the "KERNAL Reference Section" of this manual. However,
  certain routines are used here to show how easy and effective the KERNAL
  is.
    Let's now use the new principles you've just learned in another pro-
  gram. It will help you to put the instructions into context:

  228   BASIC TO MACHINE LANGUAGE

    This program. will display the alphabet using a KERNAL routine. The
  only new instruction introduced here is TXA Transfer the contents of the
  X index register, into the Accumulator.

    .A 1400 LDX #$41     - X = CBM ASCII of "A"
    .A 1402 TXA          - A = X
    .A 1403 JSR $FFD2    - print character
    .A 1406 INX          - bump count
    .A 1407 CPX #$5B     - have we gone past "Z"?
    .A 1409 BNE $1402    - no, go back and do more
    .A 140B BRK          - yes, return to 64MON

    To see the Commodore 64 print the alphabet, type the familiar command:

    .G 1400

    The comments that are beside the program, explain the program flow and
  logic. If you are writing a program, write it on paper first, and then
  test it in small parts if possible.

  USEFUL TIPS FOR THE BEGINNER

    One of the best ways to learn machine language is to look at other
  peoples' machine language programs. These are published all the time in
  magazines and newsletters. Look at them even if the article is for a
  different computer, which also uses the 6510 (or 6502) microprocessor.
  You should make sure that you thoroughly understand the code that you
  look at. This will require perseveres I ce, especially when you see a new
  technique that you have never come across before. This can be infuriat-
  ing, but if patience prevails, you will be the victor.
    Having looked at other machine language programs, you MUST write your
  own. These may be utilities for your BASIC programs, or they may be an
  all machine language program.

                                            BASIC TO MACHINE LANGUAGE   229

    You should also use the utilities that are available, either IN your
  computer, or in a program, that aid you in writing, editing, or tracking
  down errors in a machine language program. An example would be the
  KERNAL, which allows you to check the keyboard, print text, control
  peripheral devices like disk drives, printers, modems, etc., manage
  memory and the screen. It is extremely powerful and it is advised
  strongly that it is used (refer to KERNAL section, Page 268).
    Advantages of writing programs in machine language:

    1. Speed - Machine language is hundreds, and in some cases thousands of
       times faster than a high level language such as BASIC.

    2. Tightness - A machine language program can be made totally
       "watertight," i.e., the user can be made to do ONLY what the program
        allows, and no more. With a high level language, you are relying on
        the user not "crashing" the BASIC interpreter by entering, for
        example, a zero which later causes a:

  ?DIVISION BY ZERO ERROR IN LINE 830

  READY.

  In essence, the computer can only be maximized by the machine language
  programmer.

  APPROACHING A LARGE TASK

    When approaching a large task in machine language, a certain amount of
  subconscious thought has usually taken place. You think about how certain
  processes are carried out in machine language. When the task is started,
  it is usually a good idea to write it out on paper. Use block diagrams of
  memory usage, functional modules of code required, and a program flow.
  Let's say that you wanted to write a roulette game in machine language.
  You could outline it something like this:

  230   BASIC TO MACHINE LANGUAGE

    o Display title
    o Ask if player requires instructions
    o YES - display them-Go to START
    o NO - Go to START
    o START Initialize everything
    o MAIN display roulette table
    o Take in bets
    o Spin wheel
    o Slow wheel to stop
    o Check bets with result
    o Inform player
    o Player any money left?
    o YES - Go to MAIN
    o NO - Inform user!, and go to START

    This is the main outline. As each module is approached, you can break
  it down further. If you look at a large indigestable problem as something
  that can be broken down into small enough pieces to be eaten, then you'll
  be able to approach something that seems impossible, and have it all fall
  into place.
    This process only improves with practice, so KEEP TRYING.

                                            BASIC TO MACHINE LANGUAGE   231

  +------------------------------------------------------------------------
  |
  |      MCS6510 MICROPROCESSOR INSTRUCTION SET - ALPHABETIC SEQUENCE
  |
  +------------------------------------------------------------------------
  |
  |     ADC   Add Memory to Accumulator with Carry
  |     AND   "AND" Memory with Accumulator
  |     ASL   Shift Left One Bit (Memory or Accumulator)
  |
  |     BCC   Branch on Carry Clear
  |     BCS   Branch on Carry Set
  |     BEQ   Branch on Result Zero
  |     BIT   Test Bits in Memory with Accumulator
  |     BMI   Branch on Result Minus
  |     BNE   Branch on Result not Zero
  |     BPL   Branch on Result Plus
  |     BRK   Force Break
  |     BVC   Branch on Overflow Clear
  |     BVS   Branch on Overflow Set
  |
  |     CLC   Clear Carry Flag
  |     CLD   Clear Decimal Mode
  |     CLI   Clear interrupt Disable Bit
  |     CLV   Clear Overflow Flag
  |     CMP   Compare Memory and Accumulator
  |     CPX   Compare Memory and Index X
  |     CPY   Compare Memory and Index Y
  |
  |     DEC   Decrement Memory by One
  |     DEX   Decrement Index X by One
  |     DEY   Decrement Index Y by One
  |
  |     EOR   "Exclusive-Or" Memory with Accumulator
  |
  |     INC   Increment Memory by One
  |     INX   Increment Index X by One
  |     INY   Increment Index Y by One
  |
  |     JMP   Jump to New Location
  |
  +------------------------------------------------------------------------

  232   BASIC TO MACHINE LANGUAGE

  ------------------------------------------------------------------------+
                                                                          |
         MCS6510 MICROPROCESSOR INSTRUCTION SET - ALPHABETIC SEQUENCE     |
                                                                          |
  ------------------------------------------------------------------------+
                                                                          |
        JSR   Jump to New Location Saving Return Address                  |
                                                                          |
        LDA   Load Accumulator with Memory                                |
        LDX   Load Index X with Memory                                    |
        LDY   Load Index Y with Memory                                    |
        LSR   Shift Right One Bit (Memory or Accumulator)                 |
                                                                          |
        NOP   No Operation                                                |
                                                                          |
        ORA   "OR" Memory with Accumulator                                |
                                                                          |
        PHA   Push Accumulator on Stack                                   |
        PHP   Push Processor Status on Stack                              |
        PLA   Pull Accumulator from Stack                                 |
        PLP   Pull Processor Status from Stack                            |
                                                                          |
        ROL   Rotate One Bit Left (Memory or Accumulator)                 |
        ROR   Rotate One Bit Right (Memory or Accumulator)                |
        RTI   Return from Interrupt                                       |
        RTS   Return from Subroutine                                      |
                                                                          |
        SBC   Subtract Memory from Accumulator with Borrow                |
        SEC   Set Carry Flag                                              |
        SED   Set Decimal Mode                                            |
        SEI   Set Interrupt Disable Status                                |
        STA   Store Accumulator in Memory                                 |
        STX   Store Index X in Memory                                     |
        STY   Store Index Y in Memory                                     |
                                                                          |
        TAX   Transfer Accumulator to Index X                             |
        TAY   Transfer Accumulator to Index Y                             |
        TSX   Transfer Stack Pointer to Index X                           |
        TXA   Transfer Index X to Accumulator                             |
        TXS   Transfer Index X to Stack Pointer                           |
        TYA   Transfer Index Y to Accumulator                             |
  ------------------------------------------------------------------------+

                                            BASIC TO MACHINE LANGUAGE   233

                The following notation applies to this summary:

     A       Accumulator                  EOR     Logical Exclusive Or

     X, Y    Index Registers              fromS   Transfer from Stack

     M       Memory                       toS     Transfer to Stack

     P       Processor Status Register    ->      Transfer to

     S       Stack Pointer                <-      Transfer from

     /       Change                       V       Logical OR

     _       No Change                    PC      Program Counter

     +       Add                          PCH     Program Counter High

     /\      Logical AND                  PCL     Program Counter Low

     -       Subtract                     OPER    OPERAND

                                          #       IMMEDIATE ADDRESSING MODE

  Note: At the top of each table is located in parentheses a reference
        number (Ref: XX) which directs the user to that Section in the
        MCS6500 Microcomputer Family Programming Manual in which the
        instruction is defined and discussed.

  234   BASIC TO MACHINE LANGUAGE

  ADC               Add memory to accumulator with carry                ADC

  Operation:  A + M + C -> A, C                         N Z C I D V
                                                        / / / _ _ /
                                (Ref: 2.2.1)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Immediate     |   ADC #Oper           |    69   |    2    |    2     |
  |  Zero Page     |   ADC Oper            |    65   |    2    |    3     |
  |  Zero Page,X   |   ADC Oper,X          |    75   |    2    |    4     |
  |  Absolute      |   ADC Oper            |    60   |    3    |    4     |
  |  Absolute,X    |   ADC Oper,X          |    70   |    3    |    4*    |
  |  Absolute,Y    |   ADC Oper,Y          |    79   |    3    |    4*    |
  |  (Indirect,X)  |   ADC (Oper,X)        |    61   |    2    |    6     |
  |  (Indirect),Y  |   ADC (Oper),Y        |    71   |    2    |    5*    |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 if page boundary is crossed.

  AND                  "AND" memory with accumulator                    AND

  Operation:  A /\ M -> A                               N Z C I D V
                                                        / / _ _ _ _
                               (Ref: 2.2.3.0)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Immediate     |   AND #Oper           |    29   |    2    |    2     |
  |  Zero Page     |   AND Oper            |    25   |    2    |    3     |
  |  Zero Page,X   |   AND Oper,X          |    35   |    2    |    4     |
  |  Absolute      |   AND Oper            |    2D   |    3    |    4     |
  |  Absolute,X    |   AND Oper,X          |    3D   |    3    |    4*    |
  |  Absolute,Y    |   AND Oper,Y          |    39   |    3    |    4*    |
  |  (Indirect,X)  |   AND (Oper,X)        |    21   |    2    |    6     |
  |  (Indirect,Y)  |   AND (Oper),Y        |    31   |    2    |    5     |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 if page boundary is crossed.

                                            BASIC TO MACHINE LANGUAGE   235

  ASL          ASL Shift Left One Bit (Memory or Accumulator)           ASL
                   +-+-+-+-+-+-+-+-+
  Operation:  C <- |7|6|5|4|3|2|1|0| <- 0
                   +-+-+-+-+-+-+-+-+                    N Z C I D V
                                                        / / / _ _ _
                                 (Ref: 10.2)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Accumulator   |   ASL A               |    0A   |    1    |    2     |
  |  Zero Page     |   ASL Oper            |    06   |    2    |    5     |
  |  Zero Page,X   |   ASL Oper,X          |    16   |    2    |    6     |
  |  Absolute      |   ASL Oper            |    0E   |    3    |    6     |
  |  Absolute, X   |   ASL Oper,X          |    1E   |    3    |    7     |
  +----------------+-----------------------+---------+---------+----------+

  BCC                     BCC Branch on Carry Clear                     BCC
                                                        N Z C I D V
  Operation:  Branch on C = 0                           _ _ _ _ _ _
                               (Ref: 4.1.1.3)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Relative      |   BCC Oper            |    90   |    2    |    2*    |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 if branch occurs to same page.
  * Add 2 if branch occurs to different page.

  BCS                      BCS Branch on carry set                      BCS

  Operation:  Branch on C = 1                           N Z C I D V
                                                        _ _ _ _ _ _
                               (Ref: 4.1.1.4)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Relative      |   BCS Oper            |    B0   |    2    |    2*    |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 if branch occurs to same  page.
  * Add 2 if branch occurs to next  page.

  236   BASIC TO MACHINE LANGUAGE

  BEQ                    BEQ Branch on result zero                      BEQ
                                                        N Z C I D V
  Operation:  Branch on Z = 1                           _ _ _ _ _ _
                               (Ref: 4.1.1.5)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Relative      |   BEQ Oper            |    F0   |    2    |    2*    |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 if branch occurs to same  page.
  * Add 2 if branch occurs to next  page.

  BIT             BIT Test bits in memory with accumulator              BIT

  Operation:  A /\ M, M7 -> N, M6 -> V

  Bit 6 and 7 are transferred to the status register.   N Z C I D V
  If the result of A /\ M is zero then Z = 1, otherwise M7/ _ _ _ M6
  Z = 0
                               (Ref: 4.2.1.1)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Zero Page     |   BIT Oper            |    24   |    2    |    3     |
  |  Absolute      |   BIT Oper            |    2C   |    3    |    4     |
  +----------------+-----------------------+---------+---------+----------+

  BMI                    BMI Branch on result minus                     BMI

  Operation:  Branch on N = 1                           N Z C I D V
                                                        _ _ _ _ _ _
                               (Ref: 4.1.1.1)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Relative      |   BMI Oper            |    30   |    2    |    2*    |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 if branch occurs to same page.
  * Add 1 if branch occurs to different page.

                                            BASIC TO MACHINE LANGUAGE   237

  BNE                   BNE Branch on result not zero                   BNE

  Operation:  Branch on Z = 0                           N Z C I D V
                                                        _ _ _ _ _ _
                               (Ref: 4.1.1.6)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Relative      |   BMI Oper            |    D0   |    2    |    2*    |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 if branch occurs to same page.
  * Add 2 if branch occurs to different page.

  BPL                     BPL Branch on result plus                     BPL

  Operation:  Branch on N = 0                           N Z C I D V
                                                        _ _ _ _ _ _
                               (Ref: 4.1.1.2)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Relative      |   BPL Oper            |    10   |    2    |    2*    |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 if branch occurs to same page.
  * Add 2 if branch occurs to different page.

  BRK                          BRK Force Break                          BRK

  Operation:  Forced Interrupt PC + 2 toS P toS         N Z C I D V
                                                        _ _ _ 1 _ _
                                 (Ref: 9.11)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   BRK                 |    00   |    1    |    7     |
  +----------------+-----------------------+---------+---------+----------+
  1. A BRK command cannot be masked by setting I.

  238   BASIC TO MACHINE LANGUAGE

  BVC                   BVC Branch on overflow clear                    BVC

  Operation:  Branch on V = 0                           N Z C I D V
                                                        _ _ _ _ _ _
                               (Ref: 4.1.1.8)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Relative      |   BVC Oper            |    50   |    2    |    2*    |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 if branch occurs to same page.
  * Add 2 if branch occurs to different page.

  BVS                    BVS Branch on overflow set                     BVS

  Operation:  Branch on V = 1                           N Z C I D V
                                                        _ _ _ _ _ _
                               (Ref: 4.1.1.7)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Relative      |   BVS Oper            |    70   |    2    |    2*    |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 if branch occurs to same page.
  * Add 2 if branch occurs to different page.

  CLC                       CLC Clear carry flag                        CLC

  Operation:  0 -> C                                    N Z C I D V
                                                        _ _ 0 _ _ _
                                (Ref: 3.0.2)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   CLC                 |    18   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

                                            BASIC TO MACHINE LANGUAGE   239

  CLD                      CLD Clear decimal mode                       CLD

  Operation:  0 -> D                                    N A C I D V
                                                        _ _ _ _ 0 _
                                (Ref: 3.3.2)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   CLD                 |    D8   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

  CLI                  CLI Clear interrupt disable bit                  CLI

  Operation: 0 -> I                                     N Z C I D V
                                                        _ _ _ 0 _ _
                                (Ref: 3.2.2)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   CLI                 |    58   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

  CLV                      CLV Clear overflow flag                      CLV

  Operation: 0 -> V                                     N Z C I D V
                                                        _ _ _ _ _ 0
                                (Ref: 3.6.1)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   CLV                 |    B8   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

  240   BASIC TO MACHINE LANGUAGE

  CMP                CMP Compare memory and accumulator                 CMP

  Operation:  A - M                                     N Z C I D V
                                                        / / / _ _ _
                                (Ref: 4.2.1)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Immediate     |   CMP #Oper           |    C9   |    2    |    2     |
  |  Zero Page     |   CMP Oper            |    C5   |    2    |    3     |
  |  Zero Page,X   |   CMP Oper,X          |    D5   |    2    |    4     |
  |  Absolute      |   CMP Oper            |    CD   |    3    |    4     |
  |  Absolute,X    |   CMP Oper,X          |    DD   |    3    |    4*    |
  |  Absolute,Y    |   CMP Oper,Y          |    D9   |    3    |    4*    |
  |  (Indirect,X)  |   CMP (Oper,X)        |    C1   |    2    |    6     |
  |  (Indirect),Y  |   CMP (Oper),Y        |    D1   |    2    |    5*    |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 if page boundary is crossed.

  CPX                  CPX Compare Memory and Index X                   CPX
                                                        N Z C I D V
  Operation:  X - M                                     / / / _ _ _
                                 (Ref: 7.8)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Immediate     |   CPX *Oper           |    E0   |    2    |    2     |
  |  Zero Page     |   CPX Oper            |    E4   |    2    |    3     |
  |  Absolute      |   CPX Oper            |    EC   |    3    |    4     |
  +----------------+-----------------------+---------+---------+----------+

  CPY                  CPY Compare memory and index Y                   CPY
                                                        N Z C I D V
  Operation:  Y - M                                     / / / _ _ _
                                 (Ref: 7.9)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Immediate     |   CPY *Oper           |    C0   |    2    |    2     |
  |  Zero Page     |   CPY Oper            |    C4   |    2    |    3     |
  |  Absolute      |   CPY Oper            |    CC   |    3    |    4     |
  +----------------+-----------------------+---------+---------+----------+

                                            BASIC TO MACHINE LANGUAGE   241

  DEC                   DEC Decrement memory by one                     DEC

  Operation:  M - 1 -> M                                N Z C I D V
                                                        / / _ _ _ _
                                 (Ref: 10.7)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Zero Page     |   DEC Oper            |    C6   |    2    |    5     |
  |  Zero Page,X   |   DEC Oper,X          |    D6   |    2    |    6     |
  |  Absolute      |   DEC Oper            |    CE   |    3    |    6     |
  |  Absolute,X    |   DEC Oper,X          |    DE   |    3    |    7     |
  +----------------+-----------------------+---------+---------+----------+

  DEX                   DEX Decrement index X by one                    DEX

  Operation:  X - 1 -> X                                N Z C I D V
                                                        / / _ _ _ _
                                 (Ref: 7.6)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   DEX                 |    CA   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

  DEY                   DEY Decrement index Y by one                    DEY

  Operation:  X - 1 -> Y                                N Z C I D V
                                                        / / _ _ _ _
                                 (Ref: 7.7)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   DEY                 |    88   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

  242   BASIC TO MACHINE LANGUAGE

  EOR            EOR "Exclusive-Or" memory with accumulator             EOR

  Operation:  A EOR M -> A                              N Z C I D V
                                                        / / _ _ _ _
                               (Ref: 2.2.3.2)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Immediate     |   EOR #Oper           |    49   |    2    |    2     |
  |  Zero Page     |   EOR Oper            |    45   |    2    |    3     |
  |  Zero Page,X   |   EOR Oper,X          |    55   |    2    |    4     |
  |  Absolute      |   EOR Oper            |    40   |    3    |    4     |
  |  Absolute,X    |   EOR Oper,X          |    50   |    3    |    4*    |
  |  Absolute,Y    |   EOR Oper,Y          |    59   |    3    |    4*    |
  |  (Indirect,X)  |   EOR (Oper,X)        |    41   |    2    |    6     |
  |  (Indirect),Y  |   EOR (Oper),Y        |    51   |    2    |    5*    |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 if page boundary is crossed.

  INC                    INC Increment memory by one                    INC
                                                        N Z C I D V
  Operation:  M + 1 -> M                                / / _ _ _ _
                                 (Ref: 10.6)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Zero Page     |   INC Oper            |    E6   |    2    |    5     |
  |  Zero Page,X   |   INC Oper,X          |    F6   |    2    |    6     |
  |  Absolute      |   INC Oper            |    EE   |    3    |    6     |
  |  Absolute,X    |   INC Oper,X          |    FE   |    3    |    7     |
  +----------------+-----------------------+---------+---------+----------+

  INX                    INX Increment Index X by one                   INX
                                                        N Z C I D V
  Operation:  X + 1 -> X                                / / _ _ _ _
                                 (Ref: 7.4)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   INX                 |    E8   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

                                            BASIC TO MACHINE LANGUAGE   243

  INY                    INY Increment Index Y by one                   INY

  Operation:  X + 1 -> X                                N Z C I D V
                                                        / / _ _ _ _
                                 (Ref: 7.5)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   INY                 |    C8   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

  JMP                     JMP Jump to new location                      JMP

  Operation:  (PC + 1) -> PCL                           N Z C I D V
              (PC + 2) -> PCH   (Ref: 4.0.2)            _ _ _ _ _ _
                                (Ref: 9.8.1)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Absolute      |   JMP Oper            |    4C   |    3    |    3     |
  |  Indirect      |   JMP (Oper)          |    6C   |    3    |    5     |
  +----------------+-----------------------+---------+---------+----------+

  JSR          JSR Jump to new location saving return address           JSR

  Operation:  PC + 2 toS, (PC + 1) -> PCL               N Z C I D V
                          (PC + 2) -> PCH               _ _ _ _ _ _
                                 (Ref: 8.1)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Absolute      |   JSR Oper            |    20   |    3    |    6     |
  +----------------+-----------------------+---------+---------+----------+

  244   BASIC TO MACHINE LANGUAGE

  LDA                  LDA Load accumulator with memory                 LDA

  Operation:  M -> A                                    N Z C I D V
                                                        / / _ _ _ _
                                (Ref: 2.1.1)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Immediate     |   LDA #Oper           |    A9   |    2    |    2     |
  |  Zero Page     |   LDA Oper            |    A5   |    2    |    3     |
  |  Zero Page,X   |   LDA Oper,X          |    B5   |    2    |    4     |
  |  Absolute      |   LDA Oper            |    AD   |    3    |    4     |
  |  Absolute,X    |   LDA Oper,X          |    BD   |    3    |    4*    |
  |  Absolute,Y    |   LDA Oper,Y          |    B9   |    3    |    4*    |
  |  (Indirect,X)  |   LDA (Oper,X)        |    A1   |    2    |    6     |
  |  (Indirect),Y  |   LDA (Oper),Y        |    B1   |    2    |    5*    |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 if page boundary is crossed.

  LDX                   LDX Load index X with memory                    LDX

  Operation:  M -> X                                    N Z C I D V
                                                        / / _ _ _ _
                                 (Ref: 7.0)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Immediate     |   LDX #Oper           |    A2   |    2    |    2     |
  |  Zero Page     |   LDX Oper            |    A6   |    2    |    3     |
  |  Zero Page,Y   |   LDX Oper,Y          |    B6   |    2    |    4     |
  |  Absolute      |   LDX Oper            |    AE   |    3    |    4     |
  |  Absolute,Y    |   LDX Oper,Y          |    BE   |    3    |    4*    |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 when page boundary is crossed.

                                            BASIC TO MACHINE LANGUAGE   245

  LDY                   LDY Load index Y with memory                    LDY
                                                        N Z C I D V
  Operation:  M -> Y                                    / / _ _ _ _
                                 (Ref: 7.1)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Immediate     |   LDY #Oper           |    A0   |    2    |    2     |
  |  Zero Page     |   LDY Oper            |    A4   |    2    |    3     |
  |  Zero Page,X   |   LDY Oper,X          |    B4   |    2    |    4     |
  |  Absolute      |   LDY Oper            |    AC   |    3    |    4     |
  |  Absolute,X    |   LDY Oper,X          |    BC   |    3    |    4*    |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 when page boundary is crossed.

  LSR          LSR Shift right one bit (memory or accumulator)          LSR

                   +-+-+-+-+-+-+-+-+
  Operation:  0 -> |7|6|5|4|3|2|1|0| -> C               N Z C I D V
                   +-+-+-+-+-+-+-+-+                    0 / / _ _ _
                                 (Ref: 10.1)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Accumulator   |   LSR A               |    4A   |    1    |    2     |
  |  Zero Page     |   LSR Oper            |    46   |    2    |    5     |
  |  Zero Page,X   |   LSR Oper,X          |    56   |    2    |    6     |
  |  Absolute      |   LSR Oper            |    4E   |    3    |    6     |
  |  Absolute,X    |   LSR Oper,X          |    5E   |    3    |    7     |
  +----------------+-----------------------+---------+---------+----------+

  NOP                         NOP No operation                          NOP
                                                        N Z C I D V
  Operation:  No Operation (2 cycles)                   _ _ _ _ _ _

  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   NOP                 |    EA   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

  246   BASIC TO MACHINE LANGUAGE

  ORA                 ORA "OR" memory with accumulator                  ORA

  Operation: A V M -> A                                 N Z C I D V
                                                        / / _ _ _ _
                               (Ref: 2.2.3.1)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Immediate     |   ORA #Oper           |    09   |    2    |    2     |
  |  Zero Page     |   ORA Oper            |    05   |    2    |    3     |
  |  Zero Page,X   |   ORA Oper,X          |    15   |    2    |    4     |
  |  Absolute      |   ORA Oper            |    0D   |    3    |    4     |
  |  Absolute,X    |   ORA Oper,X          |    10   |    3    |    4*    |
  |  Absolute,Y    |   ORA Oper,Y          |    19   |    3    |    4*    |
  |  (Indirect,X)  |   ORA (Oper,X)        |    01   |    2    |    6     |
  |  (Indirect),Y  |   ORA (Oper),Y        |    11   |    2    |    5     |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 on page crossing

  PHA                   PHA Push accumulator on stack                   PHA

  Operation:  A toS                                     N Z C I D V
                                                        _ _ _ _ _ _
                                 (Ref: 8.5)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   PHA                 |    48   |    1    |    3     |
  +----------------+-----------------------+---------+---------+----------+

  PHP                 PHP Push processor status on stack                PHP

  Operation:  P toS                                     N Z C I D V
                                                        _ _ _ _ _ _
                                 (Ref: 8.11)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   PHP                 |    08   |    1    |    3     |
  +----------------+-----------------------+---------+---------+----------+

                                            BASIC TO MACHINE LANGUAGE   247

  PLA                 PLA Pull accumulator from stack                   PLA

  Operation:  A fromS                                   N Z C I D V
                                                        _ _ _ _ _ _
                                 (Ref: 8.6)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   PLA                 |    68   |    1    |    4     |
  +----------------+-----------------------+---------+---------+----------+

  PLP               PLP Pull processor status from stack                PLA

  Operation:  P fromS                                   N Z C I D V
                                                         From Stack
                                 (Ref: 8.12)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   PLP                 |    28   |    1    |    4     |
  +----------------+-----------------------+---------+---------+----------+

  ROL          ROL Rotate one bit left (memory or accumulator)          ROL

               +------------------------------+
               |         M or A               |
               |   +-+-+-+-+-+-+-+-+    +-+   |
  Operation:   +-< |7|6|5|4|3|2|1|0| <- |C| <-+         N Z C I D V
                   +-+-+-+-+-+-+-+-+    +-+             / / / _ _ _
                                 (Ref: 10.3)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Accumulator   |   ROL A               |    2A   |    1    |    2     |
  |  Zero Page     |   ROL Oper            |    26   |    2    |    5     |
  |  Zero Page,X   |   ROL Oper,X          |    36   |    2    |    6     |
  |  Absolute      |   ROL Oper            |    2E   |    3    |    6     |
  |  Absolute,X    |   ROL Oper,X          |    3E   |    3    |    7     |
  +----------------+-----------------------+---------+---------+----------+

  248   BASIC TO MACHINE LANGUAGE

  ROR          ROR Rotate one bit right (memory or accumulator)         ROR

               +------------------------------+
               |                              |
               |   +-+    +-+-+-+-+-+-+-+-+   |
  Operation:   +-> |C| -> |7|6|5|4|3|2|1|0| >-+         N Z C I D V
                   +-+    +-+-+-+-+-+-+-+-+             / / / _ _ _
                                 (Ref: 10.4)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Accumulator   |   ROR A               |    6A   |    1    |    2     |
  |  Zero Page     |   ROR Oper            |    66   |    2    |    5     |
  |  Zero Page,X   |   ROR Oper,X          |    76   |    2    |    6     |
  |  Absolute      |   ROR Oper            |    6E   |    3    |    6     |
  |  Absolute,X    |   ROR Oper,X          |    7E   |    3    |    7     |
  +----------------+-----------------------+---------+---------+----------+

    Note: ROR instruction is available on MCS650X microprocessors after
          June, 1976.

  RTI                    RTI Return from interrupt                      RTI
                                                        N Z C I D V
  Operation:  P fromS PC fromS                           From Stack
                                 (Ref: 9.6)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   RTI                 |    4D   |    1    |    6     |
  +----------------+-----------------------+---------+---------+----------+

  RTS                    RTS Return from subroutine                     RTS
                                                        N Z C I D V
  Operation:  PC fromS, PC + 1 -> PC                    _ _ _ _ _ _
                                 (Ref: 8.2)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   RTS                 |    60   |    1    |    6     |
  +----------------+-----------------------+---------+---------+----------+

                                            BASIC TO MACHINE LANGUAGE   249

  SBC          SBC Subtract memory from accumulator with borrow         SBC
                      -
  Operation:  A - M - C -> A                            N Z C I D V
         -                                              / / / _ _ /
    Note:C = Borrow             (Ref: 2.2.2)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Immediate     |   SBC #Oper           |    E9   |    2    |    2     |
  |  Zero Page     |   SBC Oper            |    E5   |    2    |    3     |
  |  Zero Page,X   |   SBC Oper,X          |    F5   |    2    |    4     |
  |  Absolute      |   SBC Oper            |    ED   |    3    |    4     |
  |  Absolute,X    |   SBC Oper,X          |    FD   |    3    |    4*    |
  |  Absolute,Y    |   SBC Oper,Y          |    F9   |    3    |    4*    |
  |  (Indirect,X)  |   SBC (Oper,X)        |    E1   |    2    |    6     |
  |  (Indirect),Y  |   SBC (Oper),Y        |    F1   |    2    |    5     |
  +----------------+-----------------------+---------+---------+----------+
  * Add 1 when page boundary is crossed.

  SEC                        SEC Set carry flag                         SEC

  Operation:  1 -> C                                    N Z C I D V
                                                        _ _ 1 _ _ _
                                (Ref: 3.0.1)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   SEC                 |    38   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

  SED                       SED Set decimal mode                        SED
                                                        N Z C I D V
  Operation:  1 -> D                                    _ _ _ _ 1 _
                                (Ref: 3.3.1)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   SED                 |    F8   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

  250   BASIC TO MACHINE LANGUAGE

  SEI                 SEI Set interrupt disable status                  SED
                                                        N Z C I D V
  Operation:  1 -> I                                    _ _ _ 1 _ _
                                (Ref: 3.2.1)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   SEI                 |    78   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

  STA                  STA Store accumulator in memory                  STA

  Operation:  A -> M                                    N Z C I D V
                                                        _ _ _ _ _ _
                                (Ref: 2.1.2)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Zero Page     |   STA Oper            |    85   |    2    |    3     |
  |  Zero Page,X   |   STA Oper,X          |    95   |    2    |    4     |
  |  Absolute      |   STA Oper            |    80   |    3    |    4     |
  |  Absolute,X    |   STA Oper,X          |    90   |    3    |    5     |
  |  Absolute,Y    |   STA Oper, Y         |    99   |    3    |    5     |
  |  (Indirect,X)  |   STA (Oper,X)        |    81   |    2    |    6     |
  |  (Indirect),Y  |   STA (Oper),Y        |    91   |    2    |    6     |
  +----------------+-----------------------+---------+---------+----------+

  STX                    STX Store index X in memory                    STX

  Operation: X -> M                                     N Z C I D V
                                                        _ _ _ _ _ _
                                 (Ref: 7.2)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Zero Page     |   STX Oper            |    86   |    2    |    3     |
  |  Zero Page,Y   |   STX Oper,Y          |    96   |    2    |    4     |
  |  Absolute      |   STX Oper            |    8E   |    3    |    4     |
  +----------------+-----------------------+---------+---------+----------+

                                            BASIC TO MACHINE LANGUAGE   251

  STY                    STY Store index Y in memory                    STY

  Operation: Y -> M                                     N Z C I D V
                                                        _ _ _ _ _ _
                                 (Ref: 7.3)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Zero Page     |   STY Oper            |    84   |    2    |    3     |
  |  Zero Page,X   |   STY Oper,X          |    94   |    2    |    4     |
  |  Absolute      |   STY Oper            |    8C   |    3    |    4     |
  +----------------+-----------------------+---------+---------+----------+

  TAX                TAX Transfer accumulator to index X                TAX

  Operation:  A -> X                                    N Z C I D V
                                                        / / _ _ _ _
                                 (Ref: 7.11)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   TAX                 |    AA   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

  TAY                TAY Transfer accumulator to index Y                TAY

  Operation:  A -> Y                                    N Z C I D V
                                                        / / _ _ _ _
                                 (Ref: 7.13)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   TAY                 |    A8   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

  252   BASIC TO MACHINE LANGUAGE

  TSX              TSX Transfer stack pointer to index X                TSX

  Operation:  S -> X                                    N Z C I D V
                                                        / / _ _ _ _
                                 (Ref: 8.9)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   TSX                 |    BA   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

  TXA                TXA Transfer index X to accumulator                TXA
                                                        N Z C I D V
  Operation:  X -> A                                    / / _ _ _ _
                                 (Ref: 7.12)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   TXA                 |    8A   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

  TXS              TXS Transfer index X to stack pointer                TXS
                                                        N Z C I D V
  Operation:  X -> S                                    _ _ _ _ _ _
                                 (Ref: 8.8)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   TXS                 |    9A   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

  TYA                TYA Transfer index Y to accumulator                TYA

  Operation:  Y -> A                                    N Z C I D V
                                                        / / _ _ _ _
                                 (Ref: 7.14)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Implied       |   TYA                 |    98   |    1    |    2     |
  +----------------+-----------------------+---------+---------+----------+

                                            BASIC TO MACHINE LANGUAGE   253

  +------------------------------------------------------------------------
  | INSTRUCTION ADDRESSING MODES AND RELATED EXECUTION TIMES
  | (in clock cycles)
  +------------------------------------------------------------------------

                  A   A   A   B   B   B   B   B   B   B   B   B   B   C
                  D   N   S   C   C   E   I   M   N   P   R   V   V   L
                  C   D   L   C   S   Q   T   I   E   L   K   C   S   C
  Accumulator  |  .   .   2   .   .   .   .   .   .   .   .   .   .   .
  Immediate    |  2   2       .   .   .   .   .   .   .   .   .   .   .
  Zero Page    |  3   3   5   .   .   .   3   .   .   .   .   .   .   .
  Zero Page,X  |  4   4   6   .   .   .   .   .   .   .   .   .   .   .
  Zero Page,Y  |  .   .   .   .   .   .   .   .   .   .   .   .   .   .
  Absolute     |  4   4   6   .   .   .   4   .   .   .   .   .   .   .
  Absolute,X   |  4*  4*  7   .   .   .   .   .   .   .   .   .   .   .
  Absolute,Y   |  4*  4*  .   .   .   .   .   .   .   .   .   .   .   .
  Implied      |  .   .   .   .   .   .   .   .   .   .   .   .   .   2
  Relative     |  .   .   .   2** 2** 2** .   2** 2** 2** 7   2** 2** .
  (Indirect,X) |  6   6   .   .   .   .   .   .   .   .   .   .   .   .
  (Indirect),Y |  5*  5*  .   .   .   .   .   .   .   .   .   .   .   .
  Abs. Indirect|  .   .   .   .   .   .   .   .   .   .   .   .   .   .
               +-----------------------------------------------------------
                  C   C   C   C   C   C   D   D   D   E   I   I   I   J
                  L   L   L   M   P   P   E   E   E   O   N   N   N   M
                  D   I   V   P   X   Y   C   X   Y   R   C   X   Y   P
  Accumulator  |  .   .   .   .   .   .   .   .   .   .   .   .   .   .
  Immediate    |  .   .   .   2   2   2   .   .   .   2   .   .   .   .
  Zero Page    |  .   .   .   3   3   3   5   .   .   3   5   .   .   .
  Zero Page,X  |  .   .   .   4   .   .   6   .   .   4   6   .   .   .
  Zero Page,Y  |  .   .   .   .   .   .   .   .   .   .   .   .   .   .
  Absolute     |  .   .   .   4   4   4   6   .   .   4   6   .   .   3
  Absolute,X   |  .   .   .   4*  .   .   7   .   .   4*  7   .   .   .
  Absolute,Y   |  .   .   .   4*  .   .   .   .   .   4*  .   .   .   .
  Implied      |  2   2   2   .   .   .   .   2   2   .   .   2   2   .
  Relative     |  .   .   .   .   .   .   .   .   .   .   .   .   .   .
  (Indirect,X) |  .   .   .   6   .   .   .   .   .   6   .   .   .   .
  (Indirect),Y |  .   .   .   5*  .   .   .   .   .   5*  .   .   .   .
  Abs. Indirect|  .   .   .   .   .   .   .   .   .   .   .   .   .   5
               +-----------------------------------------------------------
     *  Add one cycle if indexing across page boundary
     ** Add one cycle if branch is taken, Add one additional if branching
        operation crosses page boundary

  254   BASIC TO MACHINE LANGUAGE

  ------------------------------------------------------------------------+
    INSTRUCTION ADDRESSING MODES AND RELATED EXECUTION TIMES              |
    (in clock cycles)                                                     |
  ------------------------------------------------------------------------+

                  J   L   L   L   L   N   O   P   P   P   P   R   R   R
                  S   D   D   D   S   O   R   H   H   L   L   O   O   T
                  R   A   X   Y   R   P   A   A   P   A   P   L   R   I
  Accumulator  |  .   .   .   .   2   .   .   .   .   .   .   2   2   .
  Immediate    |  .   2   2   2   .   .   2   .   .   .   .   .   .   .
  Zero Page    |  .   3   3   3   5   .   3   .   .   .   .   5   5   .
  Zero Page,X  |  .   4   .   4   6   .   4   .   .   .   .   6   6   .
  Zero Page,Y  |  .   .   4   .   .   .   .   .   .   .   .   .   .   .
  Absolute     |  6   4   4   4   6   .   4   .   .   .   .   6   6   .
  Absolute,X   |  .   4*  .   4*  7   .   4*  .   .   .   .   7   7   .
  Absolute,Y   |  .   4*  4*  .   .   .   4*  .   .   .   .   .   .   .
  Implied      |  .   .   .   .   .   2   .   3   3   4   4   .   .   6
  Relative     |  .   .   .   .   .   .   .   .   .   .   .   .   .   .
  (Indirect,X) |  .   6   .   .   .   .   6   .   .   .   .   .   .   .
  (Indirect),Y |  .   5*  .   .   .   .   5*  .   .   .   .   .   .   .
  Abs. Indirect|  .   .   .   .   .   .   .   .   .   .   .   .   .   .
               +-----------------------------------------------------------
                  R   S   S   S   S   S   S   S   T   T   T   T   T   T
                  T   B   E   E   E   T   T   T   A   A   S   X   X   Y
                  S   C   C   D   I   A   X   Y   X   Y   X   A   S   A
  Accumulator  |  .   .   .   .   .   .   .   .   .   .   .   .   .   .
  Immediate    |  .   2   .   .   .   .   .   .   .   .   .   .   .   .
  Zero Page    |  .   3   .   .   .   3   3   3   .   .   .   .   .   .
  Zero Page,X  |  .   4   .   .   .   4   .   4   .   .   .   .   .   .
  Zero Page,Y  |  .   .   .   .   .   .   4   .   .   .   .   .   .   .
  Absolute     |  .   4   .   .   .   4   4   4   .   .   .   .   .   .
  Absolute,X   |  .   4*  .   .   .   5   .   .   .   .   .   .   .   .
  Absolute,Y   |  .   4*  .   .   .   5   .   .   .   .   .   .   .   .
  Implied      |  6   .   2   2   2   .   .   .   2   2   2   2   2   2
  Relative     |  .   .   .   .   .   .   .   .   .   .   .   .   .   .
  (Indirect,X) |  .   6   .   .   .   6   .   .   .   .   .   .   .   .
  (Indirect),Y |  .   5*  .   .   .   6   .   .   .   .   .   .   .   .
  Abs. Indirect|  .   .   .   .   .   .   .   .   .   .   .   .   .   .
               +-----------------------------------------------------------
     *  Add one cycle if indexing across page boundary
     ** Add one cycle if branch is taken, Add one additional if branching
        operation crosses page boundary

                                              BASIC TO MACHINE LANGUAGE 255

        00 - BRK                        20 - JSR
        01 - ORA - (Indirect,X)         21 - AND - (Indirect,X)
        02 - Future Expansion           22 - Future Expansion
        03 - Future Expansion           23 - Future Expansion
        04 - Future Expansion           24 - BIT - Zero Page
        05 - ORA - Zero Page            25 - AND - Zero Page
        06 - ASL - Zero Page            26 - ROL - Zero Page
        07 - Future Expansion           27 - Future Expansion
        08 - PHP                        28 - PLP
        09 - ORA - Immediate            29 - AND - Immediate
        0A - ASL - Accumulator          2A - ROL - Accumulator
        0B - Future Expansion           2B - Future Expansion
        0C - Future Expansion           2C - BIT - Absolute
        0D - ORA - Absolute             2D - AND - Absolute
        0E - ASL - Absolute             2E - ROL - Absolute
        0F - Future Expansion           2F - Future Expansion
        10 - BPL                        30 - BMI
        11 - ORA - (Indirect),Y         31 - AND - (Indirect),Y
        12 - Future Expansion           32 - Future Expansion
        13 - Future Expansion           33 - Future Expansion
        14 - Future Expansion           34 - Future Expansion
        15 - ORA - Zero Page,X          35 - AND - Zero Page,X
        16 - ASL - Zero Page,X          36 - ROL - Zero Page,X
        17 - Future Expansion           37 - Future Expansion
        18 - CLC                        38 - SEC
        19 - ORA - Absolute,Y           39 - AND - Absolute,Y
        1A - Future Expansion           3A - Future Expansion
        1B - Future Expansion           3B - Future Expansion
        1C - Future Expansion           3C - Future Expansion
        1D - ORA - Absolute,X           3D - AND - Absolute,X
        1E - ASL - Absolute,X           3E - ROL - Absolute,X
        1F - Future Expansion           3F - Future Expansion

  256   BASIC TO MACHINE LANGUAGE

        40 - RTI                        60 - RTS
        41 - EOR - (Indirect,X)         61 - ADC - (Indirect,X)
        42 - Future Expansion           62 - Future Expansion
        43 - Future Expansion           63 - Future Expansion
        44 - Future Expansion           64 - Future Expansion
        45 - EOR - Zero Page            65 - ADC - Zero Page
        46 - LSR - Zero Page            66 - ROR - Zero Page
        47 - Future Expansion           67 - Future Expansion
        48 - PHA                        68 - PLA
        49 - EOR - Immediate            69 - ADC - Immediate
        4A - LSR - Accumulator          6A - ROR - Accumulator
        4B - Future Expansion           6B - Future Expansion
        4C - JMP - Absolute             6C - JMP - Indirect
        4D - EOR - Absolute             6D - ADC - Absolute
        4E - LSR - Absolute             6E - ROR - Absolute
        4F - Future Expansion           6F - Future Expansion
        50 - BVC                        70 - BVS
        51 - EOR - (Indirect),Y         71 - ADC - (Indirect),Y
        52 - Future Expansion           72 - Future Expansion
        53 - Future Expansion           73 - Future Expansion
        54 - Future Expansion           74 - Future Expansion
        55 - EOR - Zero Page,X          75 - ADC - Zero Page,X
        56 - LSR - Zero Page,X          76 - ROR - Zero Page,X
        57 - Future Expansion           77 - Future Expansion
        58 - CLI                        78 - SEI
        59 - EOR - Absolute,Y           79 - ADC - Absolute,Y
        5A - Future Expansion           7A - Future Expansion
        5B - Future Expansion           7B - Future Expansion
        5C - Future Expansion           7C - Future Expansion
        50 - EOR - Absolute,X           70 - ADC - Absolute,X
        5E - LSR - Absolute,X           7E - ROR - Absolute,X
        5F - Future Expansion           7F - Future Expansion

                                            BASIC TO MACHINE LANGUAGE   257

        80 - Future Expansion           A0 - LDY - Immediate
        81 - STA - (Indirect,X)         A1 - LDA - (Indirect,X)
        82 - Future Expansion           A2 - LDX - Immediate
        83 - Future Expansion           A3 - Future Expansion
        84 - STY - Zero Page            A4 - LDY - Zero Page
        85 - STA - Zero Page            A5 - LDA - Zero Page
        86 - STX - Zero Page            A6 - LDX - Zero Page
        87 - Future Expansion           A7 - Future Expansion
        88 - DEY                        A8 - TAY
        89 - Future Expansion           A9 - LDA - Immediate
        8A - TXA                        AA - TAX
        8B - Future Expansion           AB - Future Expansion
        8C - STY - Absolute             AC - LDY - Absolute
        80 - STA - Absolute             AD - LDA - Absolute
        8E - STX - Absolute             AE - LDX - Absolute
        8F - Future Expansion           AF - Future Expansion
        90 - BCC                        B0 - BCS
        91 - STA - (Indirect),Y         B1 - LDA - (Indirect),Y
        92 - Future Expansion           B2 - Future Expansion
        93 - Future Expansion           B3 - Future Expansion
        94 - STY - Zero Page,X          B4 - LDY - Zero Page,X
        95 - STA - Zero Page,X          BS - LDA - Zero Page,X
        96 - STX - Zero Page,Y          B6 - LDX - Zero Page,Y
        97 - Future Expansion           B7 - Future Expansion
        98 - TYA                        B8 - CLV
        99 - STA - Absolute,Y           B9 - LDA - Absolute,Y
        9A - TXS                        BA - TSX
        9B - Future Expansion           BB - Future Expansion
        9C - Future Expansion           BC - LDY - Absolute,X
        90 - STA - Absolute,X           BD - LDA - Absolute,X
        9E - Future Expansion           BE - LDX - Absolute,Y
        9F - Future Expansion           BF - Future Expansion

  258   BASIC TO MACHINE LANGUAGE

        C0 - Cpy - Immediate            E0 - CPX - Immediate
        C1 - CMP - (Indirect,X)         E1 - SBC - (Indirect,X)
        C2 - Future Expansion           E2 - Future Expansion
        C3 - Future Expansion           E3 - Future Expansion
        C4 - CPY - Zero Page            E4 - CPX - Zero Page
        C5 - CMP - Zero Page            E5 - SBC - Zero Page
        C6 - DEC - Zero Page            E6 - INC - Zero Page
        C7 - Future Expansion           E7 - Future Expansion
        C8 - INY                        E8 - INX
        C9 - CMP - Immediate            E9 - SBC - Immediate
        CA - DEX                        EA - NOP
        CB - Future Expansion           EB - Future Expansion
        CC - CPY - Absolute             EC - CPX - Absolute
        CD - CMP - Absolute             ED - SBC - Absolute
        CE - DEC - Absolute             EE - INC - Absolute
        CF - Future Expansion           EF - Future Expansion
        D0 - BNE                        F0 - BEQ
        D1 - CMP   (Indirect@,Y         F1 - SBC - (Indirect),Y
        D2 - Future Expansion           F2 - Future Expansion
        D3 - Future Expansion           F3 - Future Expansion
        D4 - Future Expansion           F4 - Future Expansion
        D5 - CMP - Zero Page,X          F5 - SBC - Zero Page,X
        D6 - DEC - Zero Page,X          F6 - INC - Zero Page,X
        D7 - Future Expansion           F7 - Future Expansion
        D8 - CLD                        F8 - SED
        D9 - CMP - Absolute,Y           F9 - SBC - Absolute,Y
        DA - Future Expansion           FA - Future Expansion
        DB - Future Expansion           FB - Future Expansion
        DC - Future Expansion           FC - Future Expansion
        DD - CMP - Absolute,X           FD - SBC - Absolute,X
        DE - DEC - Absolute,X           FE - INC - Absolute,X
        DF - Future Expansion           FF - Future Expansion

                                            BASIC TO MACHINE LANGUAGE   259

  MEMORY MANAGEMENT ON THE
  COMMODORE 64

    The Commodore 64 has 64K bytes of RAM. It also has 20K bytes of ROM,
  containing BASIC, the operating system, and the standard character set.
  It also accesses input/output devices as a 4K chunk of memory. How is
  this all possible on a computer with a 16-bit address bus, that is
  normally only capable of addressing 64K?
    The secret is in the 6510 processor chip itself. On the chip is an
  input/output port. This port is used to control whether RAM or ROM or I/O
  will appear in certain portions of the system's memory. The port is also
  used to control the Datassette(TM), so it is important to affect only the
  proper bits.
    The 6510 input/output port appears at location 1. The data direction
  register for this port appears at location 0. The port is controlled like
  any of the other input/output ports in the system... the data direction
  controls whether a given bit will be an input or an output, and the
  actual data transfer occurs through the port itself. The lines in the
  6510 control port are defined as follows:

  +---------+---+------------+--------------------------------------------+
  |  NAME   |BIT| DIRECTION  |                 DESCRIPTION                |
  +---------+---+------------+--------------------------------------------+
  |  LORAM  | 0 |   OUTPUT   | Control for RAM/ROM at $A000-$BFFF         |
  |  HIRAM  | 1 |   OUTPUT   | Control for RAM/ROM at $E000-$FFFF         |
  |  CHAREN | 2 |   OUTPUT   | Control for I/O/ROM at $D000-$DFFF         |
  |         | 3 |   OUTPUT   | Cassette write line                        |
  |         | 4 |   INPUT    | Cassette switch sense (0=play button down) |
  |         | 5 |   OUTPUT   | Cassette motor control (0=motor spins)     |
  +---------+---+------------+--------------------------------------------+

    The proper value for the data direction register is as follows:

                              BITS 5 4 3 2 1 0
                              ----------------
                                   1 0 1 1 1 1

  (where 1 is an output, and 0 is an input).

  260   BASIC TO MACHINE LANGUAGE

    This gives a value of 47 decimal. The Commodore 64 automatically sets
  the data direction register to this value.
    The control lines, in general, perform the function given in their de-
  scriptions. However, a combination of control lines are occasionally used
  to get a particular memory configuration.
    LORAM (bit 0) can generally be thought of as a control line which banks
  the 8K byte BASIC ROM in and out of the microprocessor address space.
  Normally, this line is HIGH for BASIC operation. If this line is
  programmed LOW, the BASIC ROM will disappear from the memory map and be
  replaced by 8K bytes of RAM from $A000-$BFFF.
    HIRAM (bit 1) can generally be thought of as a control line which banks
  the 8K byte KERNAL ROM in and out of the microprocessor address space.
  Normally, this line is HIGH for BASIC operation. If this line is
  programmed LOW, the KERNAL ROM will disappear from the memory map and be
  replaced by 8K bytes of RAM from $E000-$FFFF.
    CHAREN (bit 2) is used only to bank the 4K byte character generator ROM
  in or out of the microprocessor address space. From the processor point
  of view, the character ROM occupies the same address space as the I/O
  devices ($D000-$DFFF). When the CHAREN line is set to 1 (as is normal),
  the I/O devices appear in the microprocessor address space, and the
  character ROM is not accessable. When the CHAREN bit is cleared to 0, the
  character ROM appears in the processor address space, and the I/O devices
  are not accessable. (The microprocessor only needs to access the
  character ROM when downloading the character set from ROM to RAM. Special
  care is needed for this... see the section on PROGRAMMABLE CHARACTERS in
  the GRAPHICS chapter). CHAREN can be overridden by other control lines in
  certain memory configurations. CHAREN will have no effect on any memory
  configuration without I/O devices. RAM will appear from $D000-$DFFF
  instead.

  +-----------------------------------------------------------------------+
  | NOTE: In any memory map containing ROM, a WRITE (a POKE) to a ROM     |
  | location will store data in the RAM "under" the ROM. Writing to a ROM |
  | location stores data in the "hidden" RAM. For example, this allows a  |
  | hi-resolution screen to be kept underneath a ROM, and be changed      |
  | without having to bank the screen back into the processor address     |
  | space. Of course a READ of a ROM location will return the contents of |
  | the ROM, not the "hidden" RAM.                                        |
  +-----------------------------------------------------------------------+

                                            BASIC TO MACHINE LANGUAGE   261

  COMMODORE 64 FUNDAMENTAL MEMORY MAP

                                 +----------------------------+
                                 |       8K KERNAL ROM        |
                      E000-FFFF  |           OR RAM           |
                                 +----------------------------+
                      D000-DFFF  | 4K I/O OR RAM OR CHAR. ROM |
                                 +----------------------------+
                      C000-CFFF  |           4K RAM           |
                                 +----------------------------+
                                 |    8K BASIC ROM OR RAM     |
                      A000-BFFF  |       OR ROM PLUG-IN       |
                                 +----------------------------+
                                 |            8K RAM          |
                      8000-9FFF  |       OR ROM PLUG-IN       |
                                 +----------------------------+
                                 |                            |
                                 |                            |
                                 |          16 K RAM          |
                      4000-7FFF  |                            |
                                 +----------------------------+
                                 |                            |
                                 |                            |
                                 |          16 K RAM          |
                      0000-3FFF  |                            |
                                 +----------------------------+

  I/O BREAKDOWN

    D000-D3FF   VIC (Video Controller)                     1 K Bytes
    D400-D7FF   SID (Sound Synthesizer)                    1 K Bytes
    D800-DBFF   Color RAM                                  1 K Nybbles
    DC00-DCFF   CIA1 (Keyboard)                            256 Bytes
    DD00-DDFF   CIA2 (Serial Bus, User Port/RS-232)        256 Bytes
    DE00-DEFF   Open I/O slot #l (CP/M Enable)             256 Bytes
    DF00-DFFF   Open I/O slot #2 (Disk)                    256 Bytes

  262   BASIC TO MACHINE LANGUAGE

    The two open I/O slots are for general purpose user I/O, special pur-
  pose I/O cartridges (such as IEEE), and have been tentatively designated
  for enabling the Z-80 cartridge (CP/M option) and for interfacing to a
  low-cost high-speed disk system.
    The system provides for "auto-start" of the program in a Commodore 64
  Expansion Cartridge. The cartridge program is started if the first nine
  bytes of the cartridge ROM starting at location 32768 ($8000) contain
  specific data. The first two bytes must hold the Cold Start vector to be
  used by the cartridge program. The next two bytes at 32770 ($8002) must
  be the Warm Start vector used by the cartridge program. The next three
  bytes must be the letters, CBM, with bit 7 set in each letter. The last
  two bytes must be the digits "80" in PET ASCII.

  COMMODORE 64 MEMORY MAPS

    The following table lists the various memory configurations available
  on the COMMODORE 64, the states of the control lines which select each
  memory map, and the intended use of each map.
    The leftmost column of the table contains addresses in hexadecimal
  notation. The columns aside it introduce all possible memory
  configurations. The default mode is on the left, and the absolutely most
  rarely used Ultimax game console configuration is on the right. Each
  memory configuration column has one or more four-digit binary numbers as
  a title. The bits, from left to right, represent the state of the /LORAM,
  /HIRAM, /GAME and /EXROM lines, respectively. The bits whose state does
  not matter are marked with "X". For instance, when the Ultimax video game
  configuration is active (the /GAME line is shorted to ground, /EXROM kept
  high), the /LORAM and /HIRAM lines have no effect.

                                            BASIC TO MACHINE LANGUAGE   263

           LHGE   LHGE   LHGE   LHGE   LHGE   LHGE   LHGE   LHGE   LHGE

           1111   101X   1000   011X   001X   1110   0100   1100   XX01
  10000  default                00X0                             Ultimax
  -------------------------------------------------------------------------
   F000
          Kernal  RAM    RAM   Kernal  RAM   Kernal Kernal Kernal ROMH(*
   E000
  -------------------------------------------------------------------------
   D000    IO/C   IO/C  IO/RAM  IO/C   RAM    IO/C   IO/C   IO/C   I/O
  -------------------------------------------------------------------------
   C000    RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM     -
  -------------------------------------------------------------------------
   B000
          BASIC   RAM    RAM    RAM    RAM   BASIC   ROMH   ROMH    -
   A000
  -------------------------------------------------------------------------
   9000
           RAM    RAM    RAM    RAM    RAM    ROML   RAM    ROML  ROML(*
   8000
  -------------------------------------------------------------------------
   7000

   6000
           RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM     -
   5000

   4000
  -------------------------------------------------------------------------
   3000

   2000    RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM     -

   1000
  -------------------------------------------------------------------------
   0000    RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM
  -------------------------------------------------------------------------

     NOTE: (1)    (2)    (3)    (4)    (5)    (6)    (7)    (8)    (9)

    *) Internal memory does not respond to write accesses to these areas.

  264   BASIC TO MACHINE LANGUAGE

    Legend: Kernal      E000-FFFF       Kernal ROM.

	    IO/C        D000-DFFF       I/O address space or Character
					generator ROM, selected by -CHAREN.
					If the CHAREN bit is clear,
					the character generator ROM is
					chosen. If it is set, the
					I/O chips are accessible.

	    IO/RAM      D000-DFFF       I/O address space or RAM,
					selected by -CHAREN.
					If the CHAREN bit is clear,
					the character generator ROM is
					chosen. If it is set, the
					internal RAM is accessible.

	    I/O         D000-DFFF       I/O address space.
					The -CHAREN line has no effect.

	    BASIC       A000-BFFF       BASIC ROM.

	    ROMH        A000-BFFF or    External ROM with the -ROMH line
			E000-FFFF       connected to its -CS line.

	    ROML        8000-9FFF       External ROM with the -ROML line
					connected to its -CS line.

	    RAM         various ranges  Commodore 64's internal RAM.

	    -           1000-7FFF and   Open address space.
			A000-CFFF       The Commodore 64's memory chips
					do not detect any memory accesses
					to this area except the VIC-II's
					DMA and memory refreshes.

                                            BASIC TO MACHINE LANGUAGE   265

        (1)   This is the default BASIC memory map which provides
              BASIC 2.0 and 38K contiguous bytes of user RAM.

        (2)   This map provides 60K bytes of RAM and I/O devices.
              The user must write his own I/O driver routines.

        (3)   The same as 2, but the character ROM is not
              accessible by the CPU in this map.

        (4)   This map is intended for use with softload languages
              (including CP/M), providing 52K contiguous bytes of
              user RAM, I/O devices, and I/O driver routines.

        (5)   This map gives access to all 64K bytes of RAM. The
              I/O devices must be banked back into the processor's
              address space for any I/O operation.

        (6)   This is the standard configuration for a BASIC system
              with a BASIC expansion ROM. This map provides 32K
              contiguous bytes of user RAM and up to 8K bytes of
              BASIC "enhancement".

        (7)   This map provides 40K contiguous bytes of user RAM
              and up to 8K bytes of plug-in ROM for special ROM-
              based applications which don't require BASIC.

        (8)   This map provides 32K contiguous bytes of user RAM
              and up to 16K bytes of plug-in ROM for special
              applications which don't require BASIC (word
              processors, other languages, etc.).

        (9)   This is the ULTIMAX video game memory map. Note that
              the 2K byte "expansion RAM" for the ULTIMAX, if
              required, is accessed out of the COMMODORE 64 and
              any RAM in the cartridge is ignored.

  266   BASIC TO MACHINE LANGUAGE

                                            BASIC TO MACHINE LANGUAGE   267

  THE KERNAL

    One of the problems facing programmers in the microcomputer field is
  the question of what to do when changes are made to the operating system
  of the computer by the company. Machine language programs which took much
  time to develop might no longer work, forcing major revisions in the
  program. To alleviate this problem, Commodore has developed a method of
  protecting software writers called the KERNAL.
    Essentially, the KERNAL is a standardized JUMP TABLE to the input,
  output, and memory management routines in the operating system. The
  locations of each routine in ROM may change as the system is upgraded.
  But the KERNAL jump table will always be changed to match. If your
  machine language routines only use the system ROM routines through the
  KERNAL, it will take much less work to modify them, should that need ever
  arise.
    The KERNAL is the operating system of the Commodore 64 computer. All
  input, output, and memory management is controlled by the KERNAL.
    To simplify the machine language programs you write, and to make sure
  that future versions of the Commodore 64 operating system don't make your
  machine language programs obsolete, the KERNAL contains a jump table for
  you to use. By taking advantage of the 39 input/output routines and other
  utilities available to you from the table, not only do you save time, you
  also make it easier to translate your programs from one Commodore
  computer to another.
    The jump table is located on the last page of memory, in read-only
  memory (ROM).
    To use the KERNAL jump table, first you set up the parameters that the
  KERNAL routine needs to work. Then JSR (Jump to SubRoutine) to the proper
  place in the KERNAL jump table. After performing its function, the KERNAL
  transfers control back to your machine language program. Depending on
  which KERNAL routine you are using, certain registers may pass parameters
  back to your program. The particular registers for each KERNAL routine
  may be found in the individual descriptions of the KERNAL subroutines.

  268   BASIC TO MACHINE LANGUAGE

    A good question at this point is why use the jump table at all? Why not
  just JSR directly to the KERNAL subroutine involved? The jump table is
  used so that if the KERNAL or BASIC is changed, your machine language
  programs will still work. In future operating systems the routines may
  have their memory locations moved around to a different position in the
  memory map... but the jump table will still work correctly!

  KERNAL POWER-UP ACTIVITIES

  1) On power-up, the KERNAL first resets the stack pointer, and clears
     decimal mode.
  2) The KERNAL then checks for the presence of an autostart ROM cartridge
     at location $8000 HEX (32768 decimal). If this is present, normal
     initialization is suspended, and control is transferred to the car-
     tridge code. If an autostart ROM is not present, normal system ini-
     tialization continues.
  3) Next, the KERNAL initializes all INPUT/OUTPUT devices. The serial bus
     is initialized. Both 6526 CIA chips are set to the proper values for
     keyboard scanning, and the 60-Hz timer is activated. The SID chip is
     cleared. The BASIC memory map is selected and the cassette motor is
     switched off.
  4) Next, the KERNAL performs a RAM test, setting the top and bottom of
     memory pointers. Also, page zero is initialized, and the tape buffer
     is set up.
       The RAM TEST routine is a nondestructive test starting at location
     $0300 and working upward. Once the test has found the first non-RAM
     location, the top of RAM has its pointer set. The bottom of memory is
     always set to $0800, and the screen setup is always set at $0400.
  5) Finally, the KERNAL performs these other activities. I/O vectors are
     set to default values. The indirect jump table in low memory is estab-
     lished. The screen is then cleared, and all screen editor variables
     reset. Then the indirect at $A000 is used to start BASIC.

                                            BASIC TO MACHINE LANGUAGE   269

  HOW TO USE THE KERNAL

    When writing machine language programs it is often convenient to use
  the routines which are already part of the operating system for input/
  output, access to the system clock, memory management, and other similar
  operations. It is an unnecessary duplication of effort to write these
  routines over and over again, so easy access to the operating system
  helps speed machine language programming.
    As mentioned before, the KERNAL is a jump table. This is just a col-
  lection of JMP instructions to many operating system routines.
    To use a KERNAL routine you must first make all of the preparations
  that the routine demands. If one routine says that you must call another
  KERNAL routine first, then that routine must be called. If the routine
  expects you to put a number in the accumulator, then that number must be
  there. Otherwise your routines have little chance of working the way you
  expect them to work.
    After all preparations are made, you must call the routine by means of
  the JSR instruction. All KERNAL routines you can access are structured as
  SUBROUTINES, and must end with an RTS instruction. When the KERNAL
  routine has finished its task, control is returned to your program at the
  instruction after the JSR.
    Many of the KERNAL routines return error codes in the status word or
  the accumulator if you have problems in the routine. Good programming
  practice and the success of your machine language programs demand that
  you handle this properly. If you ignore an error return, the rest of your
  program might "bomb."
    That's all there is to do when you're using the KERNAL. Just these
  three simple steps:

    1) Set up
    2) Call the routine
    3) Error handling

  270   BASIC TO MACHINE LANGUAGE

    The following conventions are used in describing the KERNAL routines:

  - FUNCTION NAME: Name of the KERNAL routine.

  - CALL ADDRESS: This is the call address of the KERNAL routine, given in
    hexadecimal.

  - COMMUNICATION REGISTERS: Registers listed under this heading are used
    to pass parameters to and from the KERNAL routines.

  - PREPARATORY ROUTINES: Certain KERNAL routines require that data be set
    up before they can operate. The routines needed are listed here.

  - ERROR RETURNS: A return from a KERNAL routine with the CARRY set
    indicates that an error was encountered in processing. The accumulator
    will contain the number of the error.

  - STACK REQUIREMENTS: This is the actual number of stack bytes used by
    the KERNAL routine.

  - REGISTERS AFFECTED: All registers used by the KERNAL routine are listed
    here.

  - DESCRIPTION: A short tutorial on the function of the KERNAL routine is
    given here.

    The list of the KERNAL routines follows.

                                            BASIC TO MACHINE LANGUAGE   271

                       USER CALLABLE KERNAL ROUTINES
  +--------+-------------------+------------------------------------------+
  |        |      ADDRESS      |                                          |
  |  NAME  +---------+---------+                 FUNCTION                 |
  |        |   HEX   | DECIMAL |                                          |
  +--------+---------+---------+------------------------------------------+
  | ACPTR  |  $FFA5  |  65445  |  Input byte from serial port             |
  | CHKIN  |  $FFC6  |  65478  |  Open channel for input                  |
  | CHKOUT |  $FFC9  |  65481  |  Open channel for output                 |
  | CHRIN  |  $FFCF  |  65487  |  Input character from channel            |
  | CHROUT |  $FFD2  |  65490  |  Output character to channel             |
  | CIOUT  |  $FFA8  |  65448  |  Output byte to serial port              |
  | CINT   |  $FF81  |  65409  |  Initialize screen editor                |
  | CLALL  |  $FFE7  |  65511  |  Close all channels and files            |
  | CLOSE  |  $FFC3  |  65475  |  Close a specified logical file          |
  | CLRCHN |  $FFCC  |  65484  |  Close input and output channels         |
  | GETIN  |  $FFE4  |  65508  |  Get character from keyboard queue       |
  |        |         |         |  (keyboard buffer)                       |
  | IOBASE |  $FFF3  |  65523  |  Returns base address of I/O devices     |
  | IOINIT |  $FF84  |  65412  |  Initialize input/output                 |
  | LISTEN |  $FFB1  |  65457  |  Command devices on the serial bus to    |
  |        |         |         |  LISTEN                                  |
  | LOAD   |  $FFD5  |  65493  |  Load RAM from a device                  |
  | MEMBOT |  $FF9C  |  65436  |  Read/set the bottom of memory           |
  | MEMTOP |  $FF99  |  65433  |  Read/set the top of memory              |
  | OPEN   |  $FFC0  |  65472  |  Open a logical file                     |
  +--------+---------+---------+------------------------------------------+

  272   BASIC TO MACHINE LANGUAGE

  +--------+-------------------+------------------------------------------+
  |        |      ADDRESS      |                                          |
  |  NAME  +---------+---------+                 FUNCTION                 |
  |        |   HEX   | DECIMAL |                                          |
  +--------+---------+---------+------------------------------------------+
  | PLOT   |  $FFF0  |  65520  |  Read/set X,Y cursor position            |
  | RAMTAS |  $FF87  |  65415  |  Initialize RAM, allocate tape buffer,   |
  |        |         |         |  set screen $0400                        |
  | RDTIM  |  $FFDE  |  65502  |  Read real time clock                    |
  | READST |  $FFB7  |  65463  |  Read I/O status word                    |
  | RESTOR |  $FF8A  |  65418  |  Restore default I/O vectors             |
  | SAVE   |  $FFD8  |  65496  |  Save RAM to device                      |
  | SCNKEY |  $FF9F  |  65439  |  Scan keyboard                           |
  | SCREEN |  $FFED  |  65517  |  Return X,Y organization of screen       |
  | SECOND |  $FF93  |  65427  |  Send secondary address after LISTEN     |
  | SETLFS |  $FFBA  |  65466  |  Set logical, first, and second addresses|
  | SETMSG |  $FF90  |  65424  |  Control KERNAL messages                 |
  | SETNAM |  $FFBD  |  65469  |  Set file name                           |
  | SETTIM |  $FFDB  |  65499  |  Set real time clock                     |
  | SETTMO |  $FFA2  |  65442  |  Set timeout on serial bus               |
  | STOP   |  $FFE1  |  65505  |  Scan stop key                           |
  | TALK   |  $FFB4  |  65460  |  Command serial bus device to TALK       |
  | TKSA   |  $FF96  |  65430  |  Send secondary address after TALK       |
  | UDTIM  |  $FFEA  |  65514  |  Increment real time clock               |
  | UNLSN  |  $FFAE  |  65454  |  Command serial bus to UNLISTEN          |
  | UNTLK  |  $FFAB  |  65451  |  Command serial bus to UNTALK            |
  | VECTOR |  $FF8D  |  65421  |  Read/set vectored I/O                   |
  +--------+---------+---------+------------------------------------------+

                                            BASIC TO MACHINE LANGUAGE   273

  B-1. Function Name: ACPTR

    Purpose: Get data from the serial bus
    Call address: $FFA5 (hex) 65445 (decimal)
    Communication registers: A
    Preparatory routines: TALK, TKSA
    Error returns: See READST
    Stack requirements: 13
    Registers affected: A, X

    Description: This is the routine to use when you want to get informa-
  tion from a device on the serial bus, like a disk. This routine gets a
  byte of data off the serial bus using full handshaking. The data is
  returned in the accumulator. To prepare for this routine the TALK routine
  must be called first to command the device on the serial bus to send data
  through the bus. If the input device needs a secondary command, it must
  be sent by using the TKSA KERNAL routine before calling this routine.
  Errors are returned in the status word. The READST routine is used to
  read the status word.

  How to Use:

    0) Command a device on the serial bus to prepare to send data to
       the Commodore 64. (Use the TALK and TKSA KERNAL routines.)
    1) Call this routine (using JSR).
    2) Store or otherwise use the data.

  EXAMPLE:

    ;GET A BYTE FROM THE BUS
    JSR ACPTR
    STA DATA

  274   BASIC TO MACHINE LANGUAGE

  B-2. Function Name: CHKIN

    Purpose: Open a channel for input
    Call address: $FFC6 (hex) 65478 (decimal)
    Communication registers: X
    Preparatory routines: (OPEN)
    Error returns:
    Stack requirements: None
    Registers affected: A, X

    Description: Any logical file that has already been opened by the
  KERNAL OPEN routine can be defined as an input channel by this routine.
  Naturally, the device on the channel must be an input device. Otherwise
  an error will occur, and the routine will abort.
    If you are getting data from anywhere other than the keyboard, this
  routine must be called before using either the CHRIN or the GETIN KERNAL
  routines for data input. If you want to use the input from the keyboard,
  and no other input channels are opened, then the calls to this routine,
  and to the OPEN routine are not needed.
    When this routine is used with a device on the serial bus, it auto-
  matically sends the talk address (and the secondary address if one was
  specified by the OPEN routine) over the bus.

  How to Use:

    0) OPEN the logical file (if necessary; see description above).
    1) Load the X register with number of the logical file to be used.
    2) Call this routine (using a JSR command).

  Possible errors are:

    #3: File not open
    #5: Device not present
    #6: File not an input file

  EXAMPLE:

    ;PREPARE FOR INPUT FROM LOGICAL FILE 2
    LDX #2
    JSR CHKIN

                                            BASIC TO MACHINE LANGUAGE   275

  B-3. Function Name: CHKOUT

    Purpose: Open a channel for output
    Call address: $FFC9 (hex) 65481 (decimal)
    Communication registers: X
    Preparatory routines: (OPEN)
    Error returns: 0,3,5,7 (See READST)
    Stack requirements: 4+
    Registers affected: A, X

    Description: Any logical file number that has been created by the
  KERNAL routine OPEN can be defined as an output channel. Of course, the
  device you intend opening a channel to must be an output device.
  Otherwise an error will occur, and the routine will be aborted.
    This routine must be called before any data is sent to any output
  device unless you want to use the Commodore 64 screen as your output
  device. If screen output is desired, and there are no other output chan-
  nels already defined, then calls to this routine, and to the OPEN routine
  are not needed.
    When used to open a channel to a device on the serial bus, this routine
  will automatically send the LISTEN address specified by the OPEN routine
  (and a secondary address if there was one).

  How to Use:
  +-----------------------------------------------------------------------+
  | REMEMBER: this routine is NOT NEEDED to send data to the screen.      |
  +-----------------------------------------------------------------------+
    0) Use the KERNAL OPEN routine to specify a logical file number, a
       LISTEN address, and a secondary address (if needed).
    1) Load the X register with the logical file number used in the open
       statement.
    2) Call this routine (by using the JSR instruction).

  EXAMPLE:

    LDX #3        ;DEFINE LOGICAL FILE 3 AS AN OUTPUT CHANNEL
    JSR CHKOUT

    Possible errors are:
    #3: File not open
    #5: Device not present
    #7: Not an output file

  276   BASIC TO MACHINE LANGUAGE

  B-4. Function Name: CHRIN

    Purpose: Get a character from the input channel
    Call address: $FFCF (hex) 65487 (decimal)
    Communication registers: A
    Preparatory routines: (OPEN, CHKIN)
    Error returns: 0 (See READST)
    Stack requirements: 7+
    Registers affected: A, X

    Description: This routine gets a byte of data from a channel already
  set up as the input channel by the KERNAL routine CHKIN. If the CHKIN has
  NOT been used to define another input channel, then all your data is
  expected from the keyboard. The data byte is returned in the accumulator.
  The channel remains open after the call.
    Input from the keyboard is handled in a special way. First, the cursor
  is turned on, and blinks until a carriage return is typed on the
  keyboard. All characters on the line (up to 88 characters) are stored in
  the BASIC input buffer. These characters can be retrieved one at a time
  by calling this routine once for each character. When the carriage return
  is retrieved, the entire line has been processed. The next time this
  routine is called, the whole process begins again, i.e., by flashing the
  cursor.

  How to Use:

  FROM THE KEYBOARD

    1) Retrieve a byte of data by calling this routine.
    2) Store the data byte.
    3) Check if it is the last data byte (is it a CR?)
    4) If not, go to step 1.

  EXAMPLE:

       LDY $#00      ;PREPARE THE Y REGISTER TO STORE THE DATA
   RD  JSR CHRIN
       STA DATA,Y    ;STORE THE YTH DATA BYTE IN THE YTH
                     ;LOCATION IN THE DATA AREA.
       INY
       CMP #CR       ;IS IT A CARRIAGE RETURN?
       BNE RD        ;NO, GET ANOTHER DATA BYTE

                                            BASIC TO MACHINE LANGUAGE   277

  EXAMPLE:

    JSR CHRIN
    STA DATA

  FROM OTHER DEVICES

    0) Use the KERNAL OPEN and CHKIN routines.
    1) Call this routine (using a JSR instruction).
    2) Store the data.

  EXAMPLE:

    JSR CHRIN
    STA DATA

  B-5. Function Name: CHROUT

    Purpose: Output a character
    Call address: $FFD2 (hex) 65490 (decimal)
    Communication registers: A
    Preparatory routines: (CHKOUT,OPEN)
    Error returns: 0 (See READST)
    Stack requirements: 8+
    Registers affected: A

    Description: This routine outputs a character to an already opened
  channel. Use the KERNAL OPEN and CHKOUT routines to set up the output
  channel before calling this routine, If this call is omitted, data is
  sent to the default output device (number 3, the screen). The data byte
  to be output is loaded into the accumulator, and this routine is called.
  The data is then sent to the specified output device. The channel is left
  open after the call.

  +-----------------------------------------------------------------------+
  | NOTE: Care must be taken when using this routine to send data to a    |
  | specific serial device since data will be sent to all open output     |
  | channels on the bus. Unless this is desired, all open output channels |
  | on the serial bus other than the intended destination channel must be |
  | closed by a call to the KERNAL CLRCHN routine.                        |
  +-----------------------------------------------------------------------+

  278   BASIC TO MACHINE LANGUAGE

  How to Use:

    0) Use the CHKOUT KERNAL routine if needed, (see description above).
    1) Load the data to be output into the accumulator.
    2) Call this routine.

  EXAMPLE:

    ;DUPLICATE THE BASIC INSTRUCTION CMD 4,"A";
    LDX #4          ;LOGICAL FILE #4
    JSR CHKOUT      ;OPEN CHANNEL OUT
    LDA #'A
    JSR CHROUT      ;SEND CHARACTER

  B-6. Function Name: CIOUT

    Purpose: Transmit a byte over the serial bus
    Call address: $FFA8 (hex) 65448 (decimal)
    Communication registers: A
    Preparatory routines: LISTEN, [SECOND]
    Error returns: See READST
    Stack requirements: 5
    Registers affected: None

    Description: This routine is used to send information to devices on the
  serial bus. A call to this routine will put a data byte onto the serial
  bus using full serial handshaking. Before this routine is called, the
  LISTEN KERNAL routine must be used to command a device on the serial bus
  to get ready to receive data. (If a device needs a secondary address, it
  must also be sent by using the SECOND KERNAL routine.) The accumulator is
  loaded with a byte to handshake as data on the serial bus. A device must
  be listening or the status word will return a timeout. This routine
  always buffers one character. (The routine holds the previous character
  to be sent back.) So when a call to the KERNAL UNLSN routine is made to
  end the data transmission, the buffered character is sent with an End Or
  Identify (EOI) set. Then the UNLSN command is sent to the device.

                                            BASIC TO MACHINE LANGUAGE   279

  How to Use:

    0) Use the LISTEN KERNAL routine (and the SECOND routine if needed).
    1) Load the accumulator with a byte of data.
    2) Call this routine to send the data byte.

  EXAMPLE:

    LDA #'X       ;SEND AN X TO THE SERIAL BUS
    JSR CIOUT

  B-7. Function Name: CINT

    Purpose: Initialize screen editor & 6567 video chip
    Call address: $FF81 (hex) 65409 (decimal)
    Communication registers: None
    Preparatory routines: None
    Error returns: None
    Stack requirements: 4
    Registers affected: A, X, Y

    Description: This routine sets up the 6567 video controller chip in the
  Commodore 64 for normal operation. The KERNAL screen editor is also
  initialized. This routine should be called by a Commodore 64 program
  cartridge.

  How to Use:

    1) Call this routine.

  EXAMPLE:

    JSR CINT
    JMP RUN       ;BEGIN EXECUTION

  280   BASIC TO MACHINE LANGUAGE

  B-8. Function Name: CLALL

    Purpose: Close all files
    Call address: $FFE7 (hex) 65511 (decimal)
    Communication registers: None
    Preparatory routines: None
    Error returns: None
    Stack requirements: 11
    Registers affected: A, X

    Description: This routine closes all open files. When this routine is
  called, the pointers into the open file table are reset, closing all
  files. Also, the CLRCHN routine is automatically called to reset the I/O
  channels.

  How to Use:

    1) Call this routine.

  EXAMPLE:

    JSR CLALL   ;CLOSE ALL FILES AND SELECT DEFAULT I/O CHANNELS
    JMP RUN     ;BEGIN EXECUTION

  B-9. Function Name: CLOSE

    Purpose: Close a logical file
    Call address: $FFC3 (hex) 65475 (decimal)
    Communication registers: A
    Preparatory routines: None
    Error returns: 0,240 (See READST)
    Stack requirements: 2+
    Registers affected: A, X, Y

    Description: This routine is used to close a logical file after all I/O
  operations have been completed on that file. This routine is called after
  the accumulator is loaded with the logical file number to be closed (the
  same number used when the file was opened using the OPEN routine).

                                            BASIC TO MACHINE LANGUAGE   281

  How to Use:

    1) Load the accumulator with the number of the logical file to be
       closed.
    2) Call this routine.

  EXAMPLE:

    ;CLOSE 15
    LDA #15
    JSR CLOSE

  B-10. Function Name: CLRCHN

    Purpose: Clear I/O channels
    Call address: $FFCC (hex) 65484 (decimal)
    Communication registers: None
    Preparatory routines: None
    Error returns:
    Stack requirements: 9
    Registers affected: A, X

    Description: This routine is called to clear all open channels and re-
  store the I/O channels to their original default values. It is usually
  called after opening other I/O channels (like a tape or disk drive) and
  using them for input/output operations. The default input device is 0
  (keyboard). The default output device is 3 (the Commodore 64 screen).
    If one of the channels to be closed is to the serial port, an UNTALK
  signal is sent first to clear the input channel or an UNLISTEN is sent to
  clear the output channel. By not calling this routine (and leaving lis-
  tener(s) active on the serial bus) several devices can receive the same
  data from the Commodore 64 at the same time. One way to take advantage
  of this would be to command the printer to TALK and the disk to LISTEN.
  This would allow direct printing of a disk file.
    This routine is automatically called when the KERNAL CLALL routine is
  executed.

  How to Use:
    1) Call this routine using the JSR instruction.

  EXAMPLE:
    JSR CLRCHN

  282   BASIC TO MACHINE LANGUAGE

  B-11. Function Name: GETIN

    Purpose: Get a character
    Call address: $FFE4 (hex) 65508 (decimal)
    Communication registers: A
    Preparatory routines: CHKIN, OPEN
    Error returns: See READST
    Stack requirements: 7+
    Registers affected: A (X, Y)

    Description: If the channel is the keyboard, this subroutine removes
  one character from the keyboard queue and returns it as an ASCII value in
  the accumulator. If the queue is empty, the value returned in the
  accumulator will be zero. Characters are put into the queue automatically
  by an interrupt driven keyboard scan routine which calls the SCNKEY
  routine. The keyboard buffer can hold up to ten characters. After the
  buffer is filled, additional characters are ignored until at least one
  character has been removed from the queue. If the channel is RS-232, then
  only the A register is used and a single character is returned. See
  READST to check validity. If the channel is serial, cassette, or screen,
  call BASIN routine.

  How to Use:

    1) Call this routine using a JSR instruction.
    2) Check for a zero in the accumulator (empty buffer).
    3) Process the data.

  EXAMPLE:

         ;WAIT FOR A CHARACTER
    WAIT JSR GETIN
         CMP #0
         BEQ WAIT

                                            BASIC TO MACHINE LANGUAGE   283

  B-12. Function Name: IOBASE

    Purpose: Define I/O memory page
    Call address: $FFF3 (hex) 65523 (decimal)
    Communication registers: X, Y
    Preparatory routines: None
    Error returns:
    Stack requirements: 2
    Registers affected: X, Y

    Description: This routine sets the X and Y registers to the address of
  the memory section where the memory mapped 110 devices are located. This
  address can then be used with an offset to access the memory mapped I/O
  devices in the Commodore 64. The offset is the number of locations from
  the beginning of the page on which the I/O register you want is located.
  The X register contains the low order address byte, while the Y register
  contains the high order address byte.
    This routine exists to provide compatibility between the Commodore 64,
  VIC-20, and future models of the Commodore 64. If the J/0 locations for
  a machine language program are set by a call to this routine, they should
  still remain compatible with future versions of the Commodore 64, the
  KERNAL and BASIC.

  How to Use:

    1) Call this routine by using the JSR instruction.
    2) Store the X and the Y registers in consecutive locations.
    3) Load the Y register with the offset.
    4) Access that I/O location.

  EXAMPLE:

    ;SET THE DATA DIRECTION REGISTER OF THE USER PORT TO 0 (INPUT)
    JSR IOBASE
    STX POINT       ;SET BASE REGISTERS
    STY POINT+1
    LDY #2
    LDA #0          ;OFFSET FOR DDR OF THE USER PORT
    STA (POINT),Y   ;SET DDR TO 0

  284   BASIC TO MACHINE LANGUAGE

  B-13. Function Name: IOINIT

    Purpose: Initialize I/O devices
    Call Address: $FF84 (hex) 65412 (decimal)
    Communication registers: None
    Preparatory routines: None
    Error returns:
    Stack requirements: None
    Registers affected: A, X, Y

    Description: This routine initializes all input/output devices and
  routines. It is normally called as part of the initialization procedure
  of a Commodore 64 program cartridge.

  EXAMPLE:
    JSR IOINIT

  B-14. Function Name: LISTEN

    Purpose: Command a device on the serial bus to listen
    Call Address: $FFB1 (hex) 65457 (decimal)
    Communication registers: A
    Preparatory routines: None
    Error returns: See READST
    Stack requirements: None
    Registers affected: A

    Description: This routine will command a device on the serial bus to
  receive data. The accumulator must be loaded with a device number between
  0 and 31 before calling the routine. LISTEN will OR the number bit by bit
  to convert to a listen address, then transmits this data as a command on
  the serial bus. The specified device will then go into listen mode, and
  be ready to accept information.

  How to Use:
    1) Load the accumulator with the number of the device to command
       to LISTEN.
    2) Call this routine using the JSR instruction.

  EXAMPLE:
    ;COMMAND DEVICE #8 TO LISTEN
    LDA #8
    JSR LISTEN
                                            BASIC TO MACHINE LANGUAGE   285

  B-15. Function Name: LOAD

    Purpose: Load RAM from device
    Call address: $FFD5 (hex) 65493 (decimal)
    Communication registers: A, X, Y
    Preparatory routines: SETLFS, SETNAM
    Error returns: 0,4,5,8,9, READST
    Stack requirements: None
    Registers affected: A, X, Y

    Description: This routine LOADs data bytes from any input device di-
  rectly into the memory of the Commodore 64. It can also be used for a
  verify operation, comparing data from a device with the data already in
  memory, while leaving the data stored in RAM unchanged.
    The accumulator (.A) must be set to 0 for a LOAD operation, or 1 for a
  verify, If the input device is OPENed with a secondary address (SA) of 0
  the header information from the device is ignored. In this case, the X
  and Y registers must contain the starting address for the load. If the
  device is addressed with a secondary address of 1, then the data is
  loaded into memory starting at the location specified by the header. This
  routine returns the address of the highest RAM location loaded.
    Before this routine can be called, the KERNAL SETLFS, and SETNAM
  routines must be called.

  +-----------------------------------------------------------------------+
  | NOTE: You can NOT LOAD from the keyboard (0), RS-232 (2), or the      |
  | screen (3).                                                           |
  +-----------------------------------------------------------------------+

  How to Use:

    0) Call the SETLFS, and SETNAM routines. If a relocated load is de-
       sired, use the SETLFS routine to send a secondary address of 0.
    1) Set the A register to 0 for load, 1 for verify.
    2) If a relocated load is desired, the X and Y registers must be set
       to the start address for the load.
    3) Call the routine using the JSR instruction.

  286   BASIC TO MACHINE LANGUAGE

  EXAMPLE:

          ;LOAD   A FILE FROM TAPE

           LDA #DEVICE1        ;SET DEVICE NUMBER
           LDX #FILENO         ;SET LOGICAL FILE NUMBER
           LDY CMD1            ;SET SECONDARY ADDRESS
           JSR SETLFS
           LDA #NAME1-NAME     ;LOAD A WITH NUMBER OF
                               ;CHARACTERS IN FILE NAME
           LDX #<NAME          ;LOAD X AND Y WITH ADDRESS OF
           LDY #>NAME          ;FILE NAME
           JSR SETNAM
           LDA #0              ;SET FLAG FOR A LOAD
           LDX #$FF            ;ALTERNATE START
           LDY #$FF
           JSR LOAD
           STX VARTAB          ;END OF LOAD
           STY VARTA B+1
           JMP START
   NAME    .BYT 'FILE NAME'
   NAME1                       ;

  B-16. Function Name: MEMBOT

    Purpose: Set bottom of memory
    Call address: $FF9C (hex) 65436 (decimal)
    Communication registers: X, Y
    Preparatory routines: None
    Error returns: None
    Stack requirements: None
    Registers affected: X, Y

    Description: This routine is used to set the bottom of the memory. If
  the accumulator carry bit is set when this routine is called, a pointer
  to the lowest byte of RAM is returned in the X and Y registers. On the
  unexpanded Commodore 64 the initial value of this pointer is $0800
  (2048 in decimal). If the accumulator carry bit is clear (-O) when this
  routine is called, the values of the X and Y registers are transferred to
  the low and high bytes, respectively, of the pointer to the beginning of
  RAM.

                                            BASIC TO MACHINE LANGUAGE   287

  How to Use:
  TO READ THE BOTTOM OF RAM
    1) Set the carry.
    2) Call this routine.

  TO SET THE BOTTOM OF MEMORY
    1) Clear the carry.
    2) Call this routine.

  EXAMPLE:

    ;MOVE BOTTOM OF MEMORY UP 1 PAGE
    SEC         ;READ MEMORY BOTTOM
    JSR MEMBOT
    INY
    CLC         ;SET MEMORY BOTTOM TO NEW VALUE
    JSR MEMBOT

  B-17. Function Name: MEMTOP

    Purpose: Set the top of RAM
    Call address: $FF99 (hex) 65433 (decimal)
    Communication registers: X, Y
    Preparatory routines: None
    Error returns: None
    Stack requirements: 2
    Registers affected: X, Y

    Description: This routine is used to set the top of RAM. When this
  routine is called with the carry bit of the accumulator set, the pointer
  to the top of RAM will be loaded into the X and Y registers. When this
  routine is called with the accumulator carry bit clear, the contents of
  the X and Y registers are loaded in the top of memory pointer, changing
  the top of memory.

  EXAMPLE:
    ;DEALLOCATE THE RS-232 BUFFER
    SEC
    JSR MEMTOP   ;READ TOP OF MEMORY
    DEX
    CLC
    JSR MEMTOP   ;SET NEW TOP OF MEMORY

  288   BASIC TO MACHINE LANGUAGE

  B-18. Function Name: OPEN

    Purpose: Open a logical file
    Call address: $FFC0 (hex) 65472 (decimal)
    Communication registers: None
    Preparatory routines: SETLFS, SETNAM
    Error returns: 1,2,4,5,6,240, READST
    Stack requirements: None
    Registers affected: A, X, Y

    Description: This routine is used to OPEN a logical file. Once the
  logical file is set up, it can be used for input/output operations. Most
  of the I/O KERNAL routines call on this routine to create the logical
  files to operate on. No arguments need to be set up to use this routine,
  but both the SETLFS and SETNAM KERNAL routines must be called before
  using this routine.

  How to Use:

    0) Use the SETLFS routine.
    1) Use the SETNAM routine.
    2) Call this routine.

  EXAMPLE:

    This is an implementation of the BASIC statement: OPEN 15,8,15,"I/O"

          LDA #NAME2-NAME    ;LENGTH OF FILE NAME FOR SETLFS
          LDY #>NAME         ;ADDRESS OF FILE NAME
          LDX #<NAME
          JSR SETNAM
          LDA #15
          LDX #8
          LDY #15
          JSR SETLFS
          JSR OPEN
    NAME  .BYT 'I/O'
    NAME2

                                            BASIC TO MACHINE LANGUAGE   289

  B-19. Function Name: PLOT

    Purpose: Set cursor location
    Call address: $FFF0 (hex) 65520 (decimal)
    Communication registers: A, X, Y
    Preparatory routines: None
    Error returns: None
    Stack requirements: 2
    Registers affected: A, X, Y

    Description: A call to this routine with the accumulator carry flag
  set loads the current position of the cursor on the screen (in X,Y
  coordinates) into the Y and X registers. Y is the column number of the
  cursor location (6-39), and X is the row number of the location of the
  cursor (0-24). A call with the carry bit clear moves the cursor to X,Y
  as determined by the Y and X registers.

  How to Use:

  READING CURSOR LOCATION

    1) Set the carry flag.
    2) Call this routine.
    3) Get the X and Y position from the Y and X registers, respectively.

  SETTING CURSOR LOCATION

    1) Clear carry flag.
    2) Set the Y and X registers to the desired cursor location.
    3) Call this routine.

  EXAMPLE:

    ;MOVE THE CURSOR TO ROW 10, COLUMN 5 (5,10)
    LDX #10
    LDY #5
    CLC
    JSR PLOT

  290   BASIC TO MACHINE LANGUAGE

  B.20. Function Name: RAMTAS

    Purpose: Perform RAM test
    Call address: $FF87 (hex) 65415 (decimal)
    Communication registers: A, X, Y
    Preparatory routines: None
    Error returns: None
    Stack requirements: 2
    Registers affected: A, X, Y

    Description: This routine is used to test RAM and set the top and
  bottom of memory pointers accordingly. It also clears locations $0000 to
  $0101 and $0200 to $03FF. It also allocates the cassette buffer, and sets
  the screen base to $0400. Normally, this routine is called as part of the
  initialization process of a Commodore 64 program cartridge.

  EXAMPLE:
    JSR RAMTAS

  B-21. Function Name: RDTIM

    Purpose: Read system clock
    Call address: $FFDE (hex) 65502 (decimal)
    Communication registers: A, X, Y
    Preparatory routines: None
    Error returns: None
    Stack requirements: 2
    Registers affected: A, X, Y

    Description: This routine is used to read the system clock. The clock's
  resolution is a 60th of a second. Three bytes are returned by the
  routine. The accumulator contains the most significant byte, the X index
  register contains the next most significant byte, and the Y index
  register contains the least significant byte.

  EXAMPLE:

    JSR RDTIM
    STY TIME
    STX TIME+1
    STA TIME+2
    ...
    TIME *=*+3
                                            BASIC TO MACHINE LANGUAGE   291

  B-22. Function Name: READST

    Purpose: Read status word
    Call address: $FFB7 (hex) 65463 (decimal)
    Communication registers: A
    Preparatory routines: None
    Error returns: None
    Stack requirements: 2
    Registers affected: A

    Description: This routine returns the current status of the I/O devices
  in the accumulator. The routine is usually called after new communication
  to an I/O device. The routine gives you information about device status,
  or errors that have occurred during the I/O operation.
    The bits returned in the accumulator contain the following information:
  (see table below)

  +---------+------------+---------------+------------+-------------------+
  |  ST Bit | ST Numeric |    Cassette   |   Serial   |    Tape Verify    |
  | Position|    Value   |      Read     |  Bus R/W   |      + Load       |
  +---------+------------+---------------+------------+-------------------+
  |    0    |      1     |               |  time out  |                   |
  |         |            |               |  write     |                   |
  +---------+------------+---------------+------------+-------------------+
  |    1    |      2     |               |  time out  |                   |
  |         |            |               |    read    |                   |
  +---------+------------+---------------+------------+-------------------+
  |    2    |      4     |  short block  |            |    short block    |
  +---------+------------+---------------+------------+-------------------+
  |    3    |      8     |   long block  |            |    long block     |
  +---------+------------+---------------+------------+-------------------+
  |    4    |     16     | unrecoverable |            |   any mismatch    |
  |         |            |   read error  |            |                   |
  +---------+------------+---------------+------------+-------------------+
  |    5    |     32     |    checksum   |            |     checksum      |
  |         |            |     error     |            |       error       |
  +---------+------------+---------------+------------+-------------------+
  |    6    |     64     |  end of file  |  EOI line  |                   |
  +---------+------------+---------------+------------+-------------------+
  |    7    |   -128     |  end of tape  | device not |    end of tape    |
  |         |            |               |   present  |                   |
  +---------+------------+---------------+------------+-------------------+

  292   BASIC TO MACHINE LANGUAGE

  How to Use:

    1) Call this routine.
    2) Decode the information in the A register as it refers to your pro-
       gram.

  EXAMPLE:

    ;CHECK FOR END OF FILE DURING READ
    JSR READST
    AND #64                       ;CHECK EOF BIT (EOF=END OF FILE)
    BNE EOF                       ;BRANCH ON EOF

  B-23. Function Name: RESTOR

    Purpose: Restore default system and interrupt vectors
    Call address: $FF8A (hex) 65418 (decimal)
    Preparatory routines: None
    Error returns: None
    Stack requirements: 2
    Registers affected: A, X, Y

    Description: This routine restores the default values of all system
  vectors used in KERNAL and BASIC routines and interrupts. (See the Memory
  Map for the default vector contents). The KERNAL VECTOR routine is used
  to read and alter individual system vectors.

  How to Use:
    1) Call this routine.

  EXAMPLE:
    JSR RESTOR

  B-24. Function Name: SAVE

    Purpose: Save memory to a device
    Call address: $FFD8 (hex) 65496 (decimal)
    Communication registers: A, X, Y
    Preparatory routines: SETLFS, SETNAM
    Error returns: 5,8,9, READST
    Stack requirements: None
    Registers affected: A, X, Y

                                            BASIC TO MACHINE LANGUAGE   293

    Description: This routine saves a section of memory. Memory is saved
  from an indirect address on page 0 specified by the accumulator to the
  address stored in the X and Y registers. It is then sent to a logical
  file on an input/output device. The SETLFS and SETNAM routines must be
  used before calling this routine. However, a file name is not required to
  SAVE to device 1 (the Datassette(TM) recorder). Any attempt to save to
  other devices without using a file name results in an error.

  +-----------------------------------------------------------------------+
  | NOTE: Device 0 (the keyboard), device 2 (RS-232), and device 3 (the   |
  | screen) cannot be SAVEd to. If the attempt is made, an error occurs,  |
  | and the SAVE is stopped.                                              |
  +-----------------------------------------------------------------------+

  How to Use:

    0) Use the SETLFS routine and the SETNAM routine (unless a SAVE with no
       file name is desired on "a save to the tape recorder"),
    1) Load two consecutive locations on page 0 with a pointer to the start
       of your save (in standard 6502 low byte first, high byte next
       format).
    2) Load the accumulator with the single byte page zero offset to the
       pointer.
    3) Load the X and Y registers with the low byte and high byte re-
       spectively of the location of the end of the save.
    4) Call this routine.

  EXAMPLE:

    LDA #1              ;DEVICE = 1:CASSETTE
    JSR SETLFS
    LDA #0              ;NO FILE NAME
    JSR SETNAM
    LDA PROG            ;LOAD START ADDRESS OF SAVE
    STA TXTTAB          ;(LOW BYTE)
    LDA PROG+1
    STA TXTTA B+1       ;(HIGH BYTE)
    LDX VARTAB          ;LOAD X WITH LOW BYTE OF END OF SAVE
    LDY VARTAB+1        ;LOAD Y WITH HIGH BYTE
    LDA #<TXTTAB        ;LOAD ACCUMULATOR WITH PAGE 0 OFFSET
    JSR SAVE

  294   BASIC TO MACHINE LANGUAGE

  B-25. Function Name: SCNKEY

    Purpose: Scan the keyboard
    Call address: $FF9F (hex) 65439 (decimal)
    Communication registers: None
    Preparatory routines: IOINIT
    Error returns: None
    Stack requirements: 5
    Registers affected: A, X, Y

    Description: This routine scans the Commodore 64 keyboard and checks
  for pressed keys. It is the same routine called by the interrupt handler.
  If a key is down, its ASCII value is placed in the keyboard queue. This
  routine is called only if the normal IRQ interrupt is bypassed.

  How to Use:

  1) Call this routine.

  EXAMPLE:

    GET  JSR SCNKEY      ;SCAN KEYBOARD
         JSR GETIN       ;GET CHARACTER
         CMP #0          ;IS IT NULL?
         BEQ GET         ;YES... SCAN AGAIN
         JSR CHROUT      ;PRINT IT

  B-26. Function Name: SCREEN

    Purpose: Return screen format
    Call address: $FFED (hex) 65517 (decimal)
    Communication registers: X, Y
    Preparatory routines: None
    Stack requirements: 2
    Registers affected: X, Y

    Description: This routine returns the format of the screen, e.g., 40
  columns in X and 25 lines in Y. The routine can be used to determine what
  machine a program is running on. This function has been implemented on
  the Commodore 64 to help upward compatibility of your programs.

                                            BASIC TO MACHINE LANGUAGE   295

  How to Use:

    1) Call this routine.

  EXAMPLE:

    JSR SCREEN
    STX MAXCOL
    STY MAXROW

  B-27. Function Name: SECOND

    Purpose: Send secondary address for LISTEN
    Call address: $FF93 (hex) 65427 (decimal)
    Communication registers: A
    Preparatory routines: LISTEN
    Error returns: See READST
    Stack requirements: 8
    Registers affected: A

    Description: This routine is used to send a secondary address to an
  I/O device after a call to the LISTEN routine is made, and the device is
  commanded to LISTEN. The routine canNOT be used to send a secondary
  address after a call to the TALK routine.
    A secondary address is usually used to give setup information to a
  device before I/O operations begin.
    When a secondary address is to be sent to a device on the serial bus,
  the address must first be ORed with $60.

  How to Use:

    1) load the accumulator with the secondary address to be sent.
    2) Call this routine.

  EXAMPLE:

    ;ADDRESS DEVICE #8 WITH COMMAND (SECONDARY ADDRESS) #15
    LDA #8
    JSR LISTEN
    LDA #15
    JSR SECOND

  296   BASIC TO MACHINE LANGUAGE

  B-28. Function Name: SETLFS

    Purpose: Set up a logical file
    Call address: $FFBA (hex) 65466 (decimal)
    Communication registers: A, X, Y
    Preparatory routines: None
    Error returns: None
    Stack requirements: 2
    Registers affected: None

    Description: This routine sets the logical file number, device address,
  and secondary address (command number) for other KERNAL routines.
    The logical file number is used by the system as a key to the file
  table created by the OPEN file routine. Device addresses can range from 0
  to 31. The following codes are used by the Commodore 64 to stand for the
  CBM devices listed below:

                  ADDRESS          DEVICE

                     0            Keyboard
                     1            Datassette(TM)
                     2            RS-232C device
                     3            CRT display
                     4            Serial bus printer
                     8            CBM serial bus disk drive

    Device numbers 4 or greater automatically refer to devices on the
  serial bus.
    A command to the device is sent as a secondary address on the serial
  bus after the device number is sent during the serial attention
  handshaking sequence. If no secondary address is to be sent, the Y index
  register should be set to 255.

  How to Use:

    1) Load the accumulator with the logical file number.
    2) Load the X index register with the device number.
    3) Load the Y index register with the command.

                                            BASIC TO MACHINE LANGUAGE   297

  EXAMPLE:

    FOR LOGICAL FILE 32, DEVICE #4, AND NO COMMAND:
    LDA #32
    LDX #4
    LDY #255
    JSR SETLFS

  B-29. Function Name: SETMSG

    Purpose: Control system message output
    Call address: $FF90 (hex) 65424 (decimal)
    Communication registers: A
    Preparatory routines: None
    Error returns: None
    Stack requirements: 2
    Registers affected: A

    Description: This routine controls the printing of error and control
  messages by the KERNAL. Either print error messages or print control mes-
  sages can be selected by setting the accumulator when the routine is
  called. FILE NOT FOUND is an example of an error message. PRESS PLAY ON
  CASSETTE is an example of a control message.
    Bits 6 and 7 of this value determine where the message will come from.
  If bit 7 is 1, one of the error messages from the KERNAL is printed. If
  bit 6 is set, control messages are printed.

  How to Use:

    1) Set accumulator to desired value.
    2) Call this routine.

  EXAMPLE:

    LDA #$40
    JSR SETMSG          ;TURN ON CONTROL MESSAGES
    LDA #$80
    JSR SETMSG          ;TURN ON ERROR MESSAGES
    LDA #0
    JSR SETMSG          ;TURN OFF ALL KERNAL MESSAGES

  298   BASIC TO MACHINE LANGUAGE

  B-30. Function Name: SETNAM

    Purpose: Set file name
    Call address: $FFBD (hex) 65469 (decimal)
    Communication registers: A, X, Y
    Preparatory routines:
    Stack requirements: 2
    Registers affected:

    Description: This routine is used to set up the file name for the OPEN,
  SAVE, or LOAD routines. The accumulator must be loaded with the length of
  the file name. The X and Y registers must be loaded with the address of
  the file name, in standard 6502 low-byte/high-byte format. The address
  can be any valid memory address in the system where a string of
  characters for the file name is stored. If no file name is desired, the
  accumulator must be set to 0, representing a zero file length. The X and
  Y registers can be set to any memory address in that case.

  How to Use:

    1) Load the accumulator with the length of the file name.
    2) Load the X index register with the low order address of the file
       name.
    3) Load the Y index register with the high order address.
    4) Call this routine.

  EXAMPLE:

    LDA #NAME2-NAME     ;LOAD LENGTH OF FILE NAME
    LDX #<NAME          ;LOAD ADDRESS OF FILE NAME
    LDY #>NAME
    JSR SETNAM

  B-31. Function Name: SETTIM

    Purpose: Set the system clock
    Call address: $FFDB (hex) 65499 (decimal)
    Communication registers: A, X, Y
    Preparatory routines: None
    Error returns: None
    Stack requirements: 2
    Registers affected: None

                                            BASIC TO MACHINE LANGUAGE   299

    Description: A system clock is maintained by an interrupt routine that
  updates the clock every 1/60th of a second (one "jiffy"). The clock is
  three bytes long, which gives it the capability to count up to 5,184,000
  jiffies (24 hours). At that point the clock resets to zero. Before
  calling this routine to set the clock, the accumulator must contain the
  most significant byte, the X index register the next most significant
  byte, and the Y index register the least significant byte of the initial
  time setting (in jiffies).

  How to Use:
    1) Load the accumulator with the MSB of the 3-byte number to set the
       clock.
    2) Load the X register with the next byte.
    3) Load the Y register with the LSB.
    4) Call this routine.

  EXAMPLE:
   ;SET THE CLOCK TO 10 MINUTES = 3600 JIFFIES
   LDA #0               ;MOST SIGNIFICANT
   LDX #>3600
   LDY #<3600           ;LEAST SIGNIFICANT
   JSR SETTIM

  B-32. Function  Name: SETTMO

    Purpose: Set IEEE bus card timeout flag
    Call address: $FFA2 (hex) 65442 (decimal)
    Communication registers: A
    Preparatory routines: None
    Error returns: None
    Stack requirements: 2
    Registers affected: None
  +-----------------------------------------------------------------------+
  | NOTE: This routine is used ONLY with an IEEE add-on card!             |
  +-----------------------------------------------------------------------+
    Description: This routine sets the timeout flag for the IEEE bus. When
  the timeout flag is set, the Commodore 64 will wait for a device on the
  IEEE port for 64 milliseconds. If the device does not respond to the
  Commodore 64's Data Address Valid (DAV) signal within that time the
  Commodore 64 will recognize an error condition and leave the handshake
  sequence. When this routine is called when the accumulator contains a 0
  in bit 7, timeouts are enabled. A 1 in bit 7 will disable the timeouts.

  300   BASIC TO MACHINE LANGUAGE

  +-----------------------------------------------------------------------+
  | NOTE: The Commodore 64 uses the timeout feature to communicate that a |
  | disk file is not found on an attempt to OPEN a file only with an IEEE |
  | card.                                                                 |
  +-----------------------------------------------------------------------+

  How to Use:

  TO SET THE TIMEOUT FLAG
    1) Set bit 7 of the accumulator to 0.
    2) Call this routine.

  TO RESET THE TIMEOUT FLAG
    1) Set bit 7 of the accumulator to 1.
    2) Call this routine.

  EXAMPLE:

    ;DISABLE TIMEOUT
    LDA #0
    JSR SETTMO

  B-33. Function Name: STOP

    Purpose: Check if <STOP> key is pressed
    Call address: $FFE1 (hex) 65505 (decimal)
    Communication registers: A
    Preparatory routines: None
    Error returns: None
    Stack requirements: None
    Registers affected: A, X

    Description: If the <STOP> key on the keyboard was pressed during a
  UDTIM call, this call returns the Z flag set. In addition, the channels
  will be reset to default values. All other flags remain unchanged. If the
  <STOP> key is not pressed then the accumulator will contain a byte
  representing the lost row of the keyboard scan. The user can also check
  for certain other keys this way.

  How to Use:
    0) UDTIM should be called before this routine.
    1) Call this routine.
    2) Test for the zero flag.
                                            BASIC TO MACHINE LANGUAGE   301

  EXAMPLE:

    JSR UDTIM   ;SCAN FOR STOP
    JSR STOP
    BNE *+5     ;KEY NOT DOWN
    JMP READY   ;=... STOP

  B-34. Function Name: TALK

    Purpose: Command a device on the serial bus to TALK
    Call address: $FFB4 (hex) 65460 (decimal)
    Communication registers: A
    Preparatory routines: None
    Error returns: See READST
    Stack requirements: 8
    Registers affected: A

    Description: To use this routine the accumulator must first be loaded
  with a device number between 0 and 31. When called, this routine then
  ORs bit by bit to convert this device number to a talk address. Then this
  data is transmitted as a command on the serial bus.

  How to Use:

    1) Load the accumulator with the device number.
    2) Call this routine.

  EXAMPLE:

    ;COMMAND DEVICE #4 TO TALK
    LDA #4
    JSR TALK

  B-35. Function Name: TKSA

    Purpose: Send a secondary address to a device commanded to TALK
    Call address: $FF96 (hex) 65430 (decimal)
    Communication registers: A
    Preparatory routines: TALK
    Error returns: See READST
    Stack requirements: 8
    Registers affected: A

  302   BASIC TO MACHINE LANGUAGE

    Description: This routine transmits a secondary address on the serial
  bus for a TALK device. This routine must be called with a number between
  0 and 31 in the accumulator. The routine sends this number as a secondary
  address command over the serial bus. This routine can only be called
  after a call to the TALK routine. It will not work after a LISTEN.

  How to Use:

    0) Use the TALK routine.
    1) Load the accumulator with the secondary address.
    2) Call this routine.

  EXAMPLE:

    ;TELL DEVICE #4 TO TALK WITH COMMAND #7
    LDA #4
    JSR TALK
    LDA #7
    JSR TALKSA

  B-36. Function Name: UDTIM

    Purpose: Update the system clock
    Call address: $FFEA (hex) 65514 (decimal)
    Communication registers: None
    Preparatory routines: None
    Error returns: None
    Stack requirements: 2
    Registers affected: A, X

    Description: This routine updates the system clock. Normally this
  routine is called by the normal KERNAL interrupt routine every 1/60th of
  a second. If the user program processes its own interrupts this routine
  must be called to update the time. In addition, the <STOP> key routine
  must be called, if the <STOP> key is to remain functional.

  How to Use:
    1) Call this routine.

  EXAMPLE:

    JSR UDTIM
                                            BASIC TO MACHINE LANGUAGE   303

  B-37. Function Name: UNLSN

    Purpose: Send an UNLISTEN command
    Call address: $FFAE (hex) 65454 (decimal)
    Communication registers: None
    Preparatory routines: None
    Error returns: See READST
    Stack requirements: 8
    Registers affected: A

    Description: This routine commands all devices on the serial bus to
  stop receiving data from the Commodore 64 (i.e., UNLISTEN). Calling this
  routine results in an UNLISTEN command being transmitted on the serial
  bus. Only devices previously commanded to listen are affected. This
  routine is normally used after the Commodore 64 is finished sending data
  to external devices. Sending the UNLISTEN commands the listening devices
  to get off the serial bus so it can be used for other purposes.

  How to Use:
    1) Call this routine.

  EXAMPLE:
    JSR UNLSN

  B-38. Function Name: UNTLK

    Purpose: Send an UNTALK command
    Call address: $FFAB (hex) 65451 (decimal)
    Communication registers: None
    Preparatory routines: None
    Error returns: See READST
    Stack requirements: 8
    Registers affected: A

    Description: This routine transmits an UNTALK command on the serial
  bus. All devices previously set to TALK will stop sending data when this
  command is received.

  How to Use:
    1) Call this routine.

  304 BASIC TO MACHINE LANGUAGE

  EXAMPLE:
    JSR UNTALK

  B-39. Function Name: VECTOR

    Purpose: Manage RAM vectors
    Call address: $FF8D (hex) 65421 (decimal)
    Communication registers: X, Y
    Preparatory routines: None
    Error returns: None
    Stack requirements: 2
    Registers affected: A, X, Y

    Description: This routine manages all system vector jump addresses
  stored in RAM. Calling this routine with the the accumulator carry bit
  set stores the current contents of the RAM vectors in a list pointed to
  by the X and Y registers. When this routine is called with the carry
  clear, the user list pointed to by the X and Y registers is transferred
  to the system RAM vectors. The RAM vectors are listed in the memory map.

  +-----------------------------------------------------------------------+
  | NOTE: This routine requires caution in its use. The best way to use it|
  | is to first read the entire vector contents into the user area, alter |
  | the desired vectors, and then copy the contents back to the system    |
  | vectors.                                                              |
  +-----------------------------------------------------------------------+

  How to Use:

  READ THE SYSTEM RAM VECTORS

    1) Set the carry.
    2) Set the X and y registers to the address to put the vectors.
    3) Call this routine.

  LOAD THE SYSTEM RAM VECTORS

    1) Clear the carry bit.
    2) Set the X and Y registers to the address of the vector list in RAM
       that must be loaded.
    3) Call this routine.
                                            BASIC TO MACHINE LANGUAGE   305

  EXAMPLE:
    ;CHANGE THE INPUT ROUTINES TO NEW SYSTEM
    LDX #<USER
    LDY #>USER
    SEC
    JSR VECTOR      ;READ OLD VECTORS
    LDA #<MYINP     ;CHANGE INPUT
    STA USER+10
    LDA #>MYINP
    STA USER+11
    LDX #<USER
    LDY #>USER
    CLC
    JSR VECTOR      ;ALTER SYSTEM
    ...
    USER *=*+26

  ERROR CODES

    The following is a list of error messages which can occur when using
  the KERNAL routines. If an error occurs during a KERNAL routine , the
  carry bit of the accumulator is set, and the number of the error message
  is returned in the accumulator.
  +-----------------------------------------------------------------------+
  | NOTE: Some KERNAL I/O routines do not use these codes for error       |
  | messages. Instead, errors are identified using the KERNAL READST      |
  | routine.                                                              |
  +-----------------------------------------------------------------------+
  +-------+---------------------------------------------------------------+
  | NUMBER|                          MEANING                              |
  +-------+---------------------------------------------------------------+
  |   0   |  Routine terminated by the <STOP> key                         |
  |   1   |  Too many open files                                          |
  |   2   |  File already open                                            |
  |   3   |  File not open                                                |
  |   4   |  File not found                                               |
  |   5   |  Device not present                                           |
  |   6   |  File is not an input file                                    |
  |   7   |  File is not an output file                                   |
  |   8   |  File name is missing                                         |
  |   9   |  Illegal device number                                        |
  |  240  |  Top-of-memory change RS-232 buffer allocation/deallocation   |
  +-------+---------------------------------------------------------------+
  306   BASIC TO MACHINE LANGUAGE

  USING MACHINE LANGUAGE FROM BASIC

    There are several methods of using BASIC and machine language on the
  Commodore 64, including special statements as part of CBM BASIC as well
  as key locations in the machine. There are five main ways to use machine
  language routines from BASIC on the Commodore 64. They are:

                1) The BASIC SYS statement
                2) The BASIC USR function
                3) Changing one of the RAM I/O vectors
                4) Changing one of the RAM interrupt vectors
                5) Changing the CHRGET routine

    1) The BASIC statement SYS X causes a JUMP to a machine language
       subroutine located at address X. The routine must end with an RTS
       (ReTurn from Subroutine) instruction. This will transfer control
       back to BASIC.
         Parameters are generally passed between the machine language
       routine and the BASIC program using the BASIC PEEK and POKE
       statements, and their machine language equivalents.
         The SYS command is the most useful method of combining BASIC with
       machine language. PEEKs and POKEs make multiple parameter passing
       easy. There can be many SYS statements in a program, each to a
       different (or even the same) machine language routine.

    2) The BASIC function USR(X) transfers control to the machine language
       subroutine located at the address stored in locations 785 and 786.
       (The address is stored in standard low-byte/high-byte format.) The
       value X is evaluated and passed to the machine language subroutine
       through floating point accumulator #1, located beginning at address
       $61 (see memory map for more details). A value may be returned back
       to the BASIC program by placing it in the floating point
       accumulator. The machine language routine must end with an RTS
       instruction to return to BASIC.
         This statement is different from the SYS, because you have to set
       up an indirect vector. Also different is the format through which
       the variable is passed (floating point format). The indirect vector
       must be changed if more than one machine language routine is used.

                                            BASIC TO MACHINE LANGUAGE   307

    3) Any of the inpUt/OUtPUT or BASIC internal routines accessed through
       the vector table located on page 3 (see ADDRESSING MODES, ZERO PAGE)
       can be replaced, or amended by user code. Each 2-byte vector
       consists of a low byte and a high byte address which is used by the
       operating system.
         The KERNAL VECTOR routine is the most reliable way to change any
       of the vectors, but a single vector can be changed by POKES. A new
       vector will point to a user prepared routine which is meant to
       replace or augment the standard system routine. When the appropriate
       BASIC command is executed, the user routine will be executed. If
       after executing the user routine, it is necessary to execute the
       normal system routine, the user program must JMP (JUMP) to the
       address formerly contained in the vector. If not, the routine must
       end with a RTS to transfer control back to BASIC.

    4) The HARDWARE INTERRUPT (IRQ) VECTOR can be changed. Every 1/60th of
       a second, the operating system transfers control to the routine
       specified by this vector. The KERNAL normally uses this for timing,
       keyboard scanning, etc. If this technique is used, you should always
       transfer control to the normal IRQ handling routine, unless the
       replacement routine is prepared to handle the CIA chip. (REMEMBER to
       end the routine with an RTI (ReTurn from Interrupt) if the CIA is
       handled by the routine).
         This method is useful for tasks which must happen concurrently
       with a BASIC program, but has the drawback of being more difficult.

  +-----------------------------------------------------------------------+
  | NOTE: ALWAYS DISABLE INTERRUPTS BEFORE CHANGING THIS VECTOR!          |
  +-----------------------------------------------------------------------+

    5) The CHRGET routine is used by BASIC to get each character/token.
       This makes it simple to add new BASIC commands. Naturally, each new
       command must be executed by a user written machine language
       subroutine. A common way to use this method is to specify a
       character (@ for example) which will occur before any of the new
       commands. The new CHRGET routine will search for the special
       character. If none is present, control is passed to the normal BASIC
       CHRGET routine. If the special character is present, the new command
       is interpreted and executed by your machine language program. This
       minimizes the extra execution time added by the need to search for
       additional commands. This technique is often called a wedge.

  308   BASIC TO MACHINE LANGUAGE

  WHERE TO PUT MACHINE LANGUAGE ROUTINES

    The best place for machine language routines on the Commodore 64 is
  from $C000-$CFFF, assuming the routines are smaller than 4K bytes long.
  This section of memory is not disturbed by BASIC.
    If for some reason it's not possible or desirable to put the machine
  language routine at $C000, for instance if the routine is larger than 4K
  bytes, it then becomes necessary to reserve an area at the top of memory
  from BASIC for the routine. The top of memory is normally $9FFF. The top
  of memory can be changed through the KERNAL routine MEMTOP, or by the
  following BASIC statements:

    10 POKE51,L:POKE52,H:POKE55,1:POKE56,H:CLR

  Where H and L are the high and low portions, respectively, of the new
  top of memory. For example, to reserve the area from $9000 to $9FFF for
  machine language, use the following:

    10 POKE5110:POKE52,144:POKE5510:POKE56,144:CLR

  HOW TO ENTER MACHINE LANGUAGE

    There are 3 common methods to add the machine language programs to a
  BASIC program. They are:

  1) DATA STATEMENTS:

    By READing DATA statements, and POKEing the values into memory at the
  start of the program, machine language routines can be added. This is the
  easiest method. No special methods are needed to save the two parts of
  the program, and it is fairly easy to debug. The drawbacks include taking
  up more memory space, and the wait while the program is POKED in.
  Therefore, this method is better for smaller routines.

  EXAMPLE:

  10 RESTORE:FORX=1T09:READA:POKE12*4096+X,A:NEXT
  .
  BASIC PROGRAM
  .
  1000 DATA 161,1,204,204,204,204,204,204,96

                                            BASIC TO MACHINE LANGUAGE   309

  2) MACHINE LANGUAGE MONITOR (64MON):

    This program allows you to enter a program in either HEX or SYMBOLIC
  codes, and save the portion of memory the program is in. Advantages of
  this method include easier entry of the machine language routines,
  debugging aids, and a much faster means of saving and loading. The
  drawback to this method is that it generally requires the BASIC program
  to load the machine language routine from tape or disk when it is
  started. (For more details on 64MON see the machine language section.)

  EXAMPLE:

    The following is an example of a BASIC program using a machine language
  routine prepared by 64MON. The routine is stored on tape:

    10 IF FLAG=L THEN 20
    15 FLAG=1:LOAD"MACHINE LANGUAGE ROUTINE NAME",1,1
    20
    .
    .
    REST OF BASIC PROGRAM

  3) EDITOR/ASSEMBLER PACKAGE:

    Advantages are similar to using a machine language monitor, but
  programs are even easier to enter. Disadvantages are also similar to the
  use of a machine language monitor.

  COMMODORE 64 MEMORY MAP

             HEX        DECIMAL
   LABEL   ADDRESS      LOCATION               DESCRIPTION
  -------------------------------------------------------------------------

  D6510   0000            0        6510 On-Chip Data-Direction Register
  R6510   0001            1        6510 On-Chip 8-Bit Input/Output Register
          0002            2        Unused
  ADRAY1  0003-0004       3-4      Jump Vector: Convert Floating-Integer

  310   BASIC TO MACHINE LANGUAGE

             HEX        DECIMAL
   LABEL   ADDRESS      LOCATION               DESCRIPTION
  -------------------------------------------------------------------------

  ADRAY2  0005-0006       5-6      Jump Vector: Convert Integer--Floating
  CHARAC  0007            7        Search Character
  ENDCHR  0008            8        Flag: Scan for Quote at End of String
  TRMPOS  0009            9        Screen Column From Last TAB
  VERCK   000A           10        Flag: 0 = Load, 1 = Verify
  COUNT   000B           11        Input Buffer Pointer / No. of Subscripts
  DIMFLG  000C           12        Flag: Default Array DiMension
  VALTYP  000D           13        Data Type: $FF = String, $00 = Numeric
  INTFLG  000E           14        Data Type: $80 = Integer, $00 = Floating
  GARBFL  000F           15        Flag: DATA scan/LIST quote/Garbage Coll
  SUBFLG  0010           16        Flag: Subscript Ref / User Function Call
  INPFLG  0011           17        Flag: $00 = INPUT, $40 = GET, $98 = READ
  TANSGN  0012           18        Flag TAN sign / Comparison Result
          0013           19        Flag: INPUT Prompt
  LINNUM  0014-0015      20-21     Temp: Integer Value
  TEMPPT  0016           22        Pointer Temporary String
  LASTPT  0017-0018      23-24     Last Temp String Address
  TEMPST  0019-0021      25-33     Stack for Temporary Strings
  INDEX   0022-0025      34-37     Utility Pointer Area

  INDEX1  0022-0023      34-35     First Utility Pointer.
  INDEX2  0024-0025      36-37     Second Utility Pointer.

  RESHO   0026-002A      38-42     Floating-Point Product of Multiply
  TXTTAB  002B-002C      43-44     Pointer: Start of BASIC Text
  VARTAB  002D-002E      45-46     Pointer: Start of BASIC Variables
  ARYTAB  002F-0030      47-48     Pointer: Start of BASIC Arrays
  STREND  0031-0032      49-50     Pointer End of BASIC Arrays (+1)
  FRETOP  0033-0034      51-52     Pointer: Bottom of String Storage
  FRESPC  0035-0036      53-54     Utility String Pointer
  MEMSIZ  0037-0038      55-56     Pointer: Highest Address Used by BASIC
  CURLIN  0039-003A      57-58     Current BASIC Line Number
  OLDLIN  003B-003C      59-60     Previous BASIC Line Number
  OLDTXT  003D-003E      61-62     Pointer: BASIC Statement for CONT
  DATLIN  003F-0040      63-64     Current DATA Line Number
  DATPTR  0041-0042      65-66     Pointer: Current DATA Item Address
  INPPTR  0043-0044      67-68     Vector: INPUT Routine
  VARNAM  0045-0046      69-70     Current BASIC Variable Name

                                            BASIC TO MACHINE LANGUAGE   311

             HEX        DECIMAL
   LABEL   ADDRESS      LOCATION               DESCRIPTION
  -------------------------------------------------------------------------

  VARPNT  0047-0048      71-72     Pointer: Current BASIC Variable Data
  FORPNT  0049-004A      73-74     Pointer: Index Variable for FOR/NEXT
          004B-0060      75-96     Temp Pointer / Data Area

  VARTXT  004B-004C      75-76     Temporary storage for TXTPTR during
                                     READ, INPUT and GET.
  OPMASK  004D           77        Mask used during FRMEVL.
  TEMPF3  004E-0052      78-82     Temporary storage for FLPT value.
  FOUR6   0053           83        Length of String Variable during Garbage
                                     collection.
  JMPER   0054-0056      84-86     Jump Vector used in Function Evaluation-
                                     JMP followed by Address ($4C,$LB,$MB).
  TEMPF1  0057-005B      87-91     Temporary storage for FLPT value.
  TEMPF2  005C-0060      92-96     Temporary storage for FLPT value.
  FACEXP  0061           97        Floating-Point Accumulator #1: Exponent
  FACHO   0062-0065      98-101    Floating Accum. #1: Mantissa
  FACSGN  0066          102        Floating Accum. #1: Sign
  SGNFLG  0067          103        Pointer: Series Evaluation Constant
  BITS    0068          104        Floating Accum. #1: Overflow Digit
  ARGEXP  0069          105        Floating-Point Accumulator #2: Exponent
  ARGHO   006A-006D     106-109    Floating Accum. #2: Mantissa
  ARGSGN  006E          110        Floating Accum. #2: Sign
  ARISGN  006F          111        Sign Comparison Result: Accum. # 1 vs #2
  FACOV   0070          112        Floating Accum. #1. Low-Order (Rounding)
  FBUFPT  0071-0072     113-114    Pointer: Cassette Buffer
  CHRGET  0073-008A     115-138    Subroutine: Get Next Byte of BASIC Text

  CHRGOT  0079          121        Entry to Get Same Byte of Text Again
  TXTPTR  007A-007B     122-123    Pointer: Current Byte of BASIC Text

  RNDX    008B-008F     139-143    Floating RND Function Seed Value
  STATUS  0090          144        Kernal I/O Status Word: ST
  STKEY   0091          145        Flag: STOP key / RVS key
  SVXT    0092          146        Timing Constant for Tape
  VERCK   0093          147        Flag: 0 = Load, 1 = Verify
  C3PO    0094          148        Flag: Serial Bus-Output Char. Buffered
  BSOUR   0095          149        Buffered Character for Serial Bus
  SYNO    0096          150        Cassette Sync No.

  312   BASIC TO MACHINE LANGUAGE

             HEX        DECIMAL
   LABEL   ADDRESS      LOCATION               DESCRIPTION
  -------------------------------------------------------------------------

          0097          151        Temp Data Area
  LDTND   0098          152        No. of Open Files / Index to File Table
  DFLTN   0099          153        Default Input Device (0)
  DFLTO   009A          154        Default Output (CMD) Device (3)
  PRTY    009B          155        Tape Character Parity
  DPSW    009C          156        Flag: Tape Byte-Received
  MSGFLG  009D          157        Flag: $80 = Direct Mode, $00 = Program
  PTR1    009E          158        Tape Pass 1 Error Log
  PTR2    009F          159        Tape Pass 2 Error Log
  TIME    00A0-00A2     160-162    Real-Time Jiffy Clock (approx) 1/60 Sec
          00A3-00A4     163-164    Temp Data Area
  CNTDN   00A5          165        Cassette Sync Countdown
  BUFPNT  00A6          166        Pointer: Tape I/O Buffer
  INBIT   00A7          167        RS-232 Input Bits / Cassette Temp
  BITCI   00A8          168        RS-232 Input Bit Count / Cassette Temp
  RINONE  00A9          169        RS-232 Flag: Check for Start Bit
  RIDATA  00AA          170        RS-232 Input Byte Buffer/Cassette Temp
  RIPRTY  00AB          171        RS-232 Input Parity / Cassette Short Cnt
  SAL     00AC-00AD     172-173    Pointer: Tape Buffer/ Screen Scrolling
  EAL     00AE-00AF     174-175    Tape End Addresses/End of Program
  CMP0    00B0-00B1     176-177    Tape Timing Constants
  TAPE1   00B2-00B3     178-179    Pointer: Start of Tape Buffer
  BITTS   00B4          180        RS-232 Out Bit Count / Cassette Temp
  NXTBIT  00B5          181        RS-232 Next Bit to Send/ Tape EOT Flag
  RODATA  00B6          182        RS-232 Out Byte Buffer
  FNLEN   00B7          183        Length of Current File Name
  LA      00B8          184        Current Logical File Number
  SA      00B9          185        Current Secondary Address
  FA      00BA          186        Current Device Number
  FNADR   00BB-00BC     187-188    Pointer: Current File Name
  ROPRTY  00BD          189        RS-232 Out Parity / Cassette Temp
  FSBLK   00BE          190        Cassette Read / Write Block Count
  MYCH    00BF          191        Serial Word Buffer
  CAS1    00C0          192        Tape Motor Interlock
  STAL    00C1-00C2     193-194    I/O Start Address
  MEMUSS  00C3-00C4     195-196    Tape Load Temps
  LSTX    00C5          197        Current Key Pressed: CHR$(n) 0 = No Key
  NDX     00C6          198        No. of Chars. in Keyboard Buffer (Queue)

                                            BASIC TO MACHINE LANGUAGE   313

             HEX        DECIMAL
   LABEL   ADDRESS      LOCATION               DESCRIPTION
  -------------------------------------------------------------------------

  RVS     00C7          199        Flag: Reverse Chars. - 1=Yes, 0=No Used
  INDX    00C8          200        Pointer: End of Logical Line for INPUT
  LXSP    00C9-00CA     201-202    Cursor X-Y Pos. at Start of INPUT
  SFDX    00CB          203        Flag: Print Shifted Chars.
  BLNSW   00CC          204        Cursor Blink enable: 0 = Flash Cursor
  BLNCT   00CD          205        Timer: Countdown to Toggle Cursor
  GDBLN   00CE          206        Character Under Cursor
  BLNON   00CF          207        Flag: Last Cursor Blink On/Off
  CRSW    00D0          208        Flag: INPUT or GET from Keyboard
  PNT     00D1-00D2     209-210    Pointer: Current Screen Line Address
  PNTR    00D3          211        Cursor Column on Current Line
  QTSW    00D4          212        Flag: Editor in Quote Mode, $00 = NO
  LNMX    00D5          213        Physical Screen Line Length
  TBLX    00D6          214        Current Cursor Physical Line Number
          00D7          215        Temp Data Area
  INSRT   00D8          216        Flag: Insert Mode, >0 = # INSTs
  LDTB1   00D9-00F2     217-242    Screen Line Link Table / Editor Temps
  USER    00F3-00F4     243-244    Pointer: Current Screen Color RAM loc.
  KEYTAB  00F5-00F6     245-246    Vector Keyboard Decode Table
  RIBUF   00F7-00F8     247-248    RS-232 Input Buffer Pointer
  ROBUF   00F9-00FA     249-250    RS-232 Output Buffer  Pointer
  FREKZP  00FB-00FE     251-254    Free 0-Page Space for User Programs
  BASZPT  00FF          255        BASIC Temp Data Area
          0100-01FF     256-511    Micro-Processor System Stack Area

          0100-010A     256-266    Floating to String Work Area
  BAD     0100-013E     256-318    Tape Input Error Log

  BUF     0200-02S8     512-600    System INPUT Buffer
  LAT     0259-0262     601-610    KERNAL Table: Active Logical File No's.
  FAT     0263-026C     611-620    KERNAL Table: Device No. for Each File
  SAT     026D-0276     621-630    KERNAL Table: Second Address Each File
  KEYD    0277-0280     631-640    Keyboard Buffer Queue (FIFO)
  MEMSTR  0281-0282     641-642    Pointer: Bottom of Memory for O.S.
  MEMSIZ  0283-0284     643-644    Pointer: Top of Memory for O.S.
  TIMOUT  0285          645        Flag: Kernal Variable for IEEE Timeout
  COLOR   0286          646        Current Character Color Code
  GDCOL   0287          647        Background Color Under Cursor

  314   BASIC TO MACHINE LANGUAGE

             HEX        DECIMAL
   LABEL   ADDRESS      LOCATION               DESCRIPTION
  -------------------------------------------------------------------------

  HIBASE  0288          648        Top of Screen Memory (Page)
  XMAX    0289          649        Size of Keyboard Buffer
  RPTFLG  028A          650        Flag: REPEAT Key Used, $80 = Repeat
  KOUNT   028B          651        Repeat Speed Counter
  DELAY   028C          652        Repeat Delay Counter
  SHFLAG  028D          653        Flag: Keyboard SHIFT Key/CTRL Key/C= Key
  LSTSHF  028E          654        Last Keyboard Shift Pattern
  KEYLOG  028F-0290     655-656    Vector: Keyboard Table Setup
  MODE    0291          657        Flag: $00=Disable SHIFT Keys, $80=Enable
  AUTODN  0292          658        Flag: Auto Scroll Down, 0 = ON
  M51CTR  0293          659        RS-232: 6551 Control Register Image
  MS1CDR  0294          660        RS-232: 6551 Command Register Image
  M51AJB  0295-0296     661-662    RS-232 Non-Standard BPS (Time/2-100) USA
  RSSTAT  0297          663        RS-232: 6551 Status Register Image
  BITNUM  0298          664        RS-232 Number of Bits Left to Send
  BAUDOF  0299-029A     665-666    RS-232 Baud Rate: Full Bit Time (us)
  RIDBE   029B          667        RS-232 Index to End of Input Buffer
  RIDBS   029C          668        RS-232 Start of Input Buffer (Page)
  RODBS   029D          669        RS-232 Start of Output Buffer (Page)
  RODBE   029E          670        RS-232 Index to End of Output Buffer
  IRQTMP  029F-02A0     671-672    Holds IRQ Vector During Tape I/O
  ENABL   02A1          673        RS-232 Enables
          02A2          674        TOD Sense During Cassette I/O
          02A3          675        Temp Storage For Cassette Read
          02A4          676        Temp D1 IRQ Indicator For Cassette Read
          02A5          677        Temp For Line Index
          02A6          678        PAL/NTSC Flag, 0= NTSC, 1 = PAL
          02A7-02FF     679-767    Unused
  IERROR  0300-0301     768-769    Vector: Print BASIC Error Message
  IMAIN   0302-0303     770-771    Vector: BASIC Warm Start
  ICRNCH  0304-0305     772-773    Vector: Tokenize BASIC Text
  IQPLOP  0306-0307     774-775    Vector: BASIC Text LIST
  IGONE   0308-0309     776-777    Vector: BASIC Char. Dispatch
  IEVAL   030A-030B     778-779    Vector: BASIC Token Evaluation
  SAREG   030C          780        Storage for 6502 .A Register
  SXREG   030D          781        Storage for 5502 .X Register
  SYREG   030E          782        Storage for 6502 .Y Register
  SPREG   030F          783        Storage for 6502 .SP Register

                                            BASIC TO MACHINE LANGUAGE   315

             HEX        DECIMAL
   LABEL   ADDRESS      LOCATION               DESCRIPTION
  -------------------------------------------------------------------------

  USRPOK  0310          784        USR Function Jump Instr (4C)
  USRADD  0311-0312     785-786    USR Address Low Byte / High Byte
          0313          787        Unused
  CINV    0314-0315     788-789    Vector: Hardware Interrupt
  CBINV   0316-0317     790-791    Vector: BRK Instr. Interrupt
  NMINV   0318-0319     792-793    Vector: Non-Maskable Interrupt
  IOPEN   031A-031B     794-795    KERNAL OPEN Routine Vector
  ICLOSE  031C-031D     796-797    KERNAL CLOSE Routine Vector
  ICHKIN  031E-031F     798-799    KERNAL CHKIN Routine
  ICKOUT  0320-0321     800-801    KERNAL CHKOUT Routine
  ICLRCH  0322-0323     802-803    KERNAL CLRCHN Routine Vector
  IBASIN  0324-0325     804-805    KERNAL CHRIN Routine
  IBSOUT  0326-0327     806-807    KERNAL CHROUT Routine
  ISTOP   0328-0329     808-809    KERNAL STOP Routine Vector
  IGETIN  032A-032B     810-811    KERNAL GETIN Routine
  ICLALL  032C-032D     812-813    KERNAL CLALL Routine Vector
  USRCMD  032E-032F     814-815    User-Defined Vector
  ILOAD   0330-0331     813-817    KERNAL LOAD Routine
  ISAVE   0332-0333     818-819    KERNAL SAVE Routine Vector
          0334-033B     820-827    Unused
  TBUFFR  033C-03FB     828-1019   Tape I/O Buffer
          03FC-03FF    1020-1023   Unused
  VICSCN  0400-07FF    1024-2047   1024 Byte Screen Memory Area

          0400-07E7    1024-2023   Video Matrix: 25 Lines X 40 Columns
          07F8-07FF    2040-2047   Sprite Data Pointers

          0800-9FFF   2048-40959   Normal BASIC Program Space
          8000-9FFF  32768-40959   VSP Cartridge ROM - 8192 Bytes
          A000-BFFF  40960-49151   BASIC ROM - 8192 Bytes (or 8K RAM)
          C000-CFFF  49152-53247   RAM - 4096 Bytes
          D000-DFFF  53248-57343   Input/Output Devices and
                                     Color RAM or Character Generator ROM
                                     or RAM - 4096 Bytes
          E000-FFFF  57344-65535   KERNAL ROM - 8192 Bytes (or 8K RAM)

  316   BASIC TO MACHINE LANGUAGE

  COMMODORE 64 INPUT/OUTPUT ASSIGNMENTS

   HEX      DECIMAL        BITS                 DESCRIPTION
  -------------------------------------------------------------------------

  0000           0          7-0    MOS 6510 Data Direction
                                     Register (xx101111)
                                     Bit= 1: Output, Bit=0:
                                     Input, x=Don't Care

  0001           1                 MOS 6510 Micro-Processor
                                     On-Chip I/O Port
                            0      /LORAM Signal (0=Switch BASIC ROM Out)
                            1      /HIRAM Signal (0=Switch Kernal ROM Out)
                            2      /CHAREN Signal (0=Switch Char. ROM In)
                            3      Cassette Data Output Line
                            4      Cassette Switch Sense: 1 = Switch Closed
                            5      Cassette Motor Control 0 = ON, 1 = OFF
                            6-7    Undefined

  D000-D02E  53248-54271           MOS 6566 VIDEO INTERFACE CONTROLLER
                                   (VIC)

  D000       53248                 Sprite 0 X Pos
  D001       53249                 Sprite 0 Y Pos
  D002       53250                 Sprite 1 X Pos
  D003       53251                 Sprite 1 Y Pos
  D004       53252                 Sprite 2 X Pos
  D005       53253                 Sprite 2 Y Pos
  D006       53254                 Sprite 3 X Pos
  D007       53255                 Sprite 3 Y Pos
  D008       53256                 Sprite 4 X Pos
  D009       53257                 Sprite 4 Y Pos
  D00A       53258                 Sprite 5 X Pos
  D00B       53259                 Sprite 5 Y Pos
  D00C       53260                 Sprite 6 X Pos
  D00D       53261                 Sprite 6 Y Pos
  D00E       53262                 Sprite 7 X Pos
  D00F       53263                 Sprite 7 Y Pos

                                            BASIC TO MACHINE LANGUAGE   317

   HEX      DECIMAL        BITS                 DESCRIPTION
  -------------------------------------------------------------------------

  D010       53264                 Sprites 0-7 X Pos (msb of X coord.)
  D011       53265                 VIC Control Register
                            7      Raster Compare: (Bit 8) See 53266
                            6      Extended Color Text Mode 1 = Enable
                            5      Bit Map Mode. 1 = Enable
                            4      Blank Screen to Border Color: 0 = Blank
                            3      Select 24/25 Row Text Display: 1=25 Rows
                            2-0    Smooth Scroll to Y Dot-Position (0-7)

  D012       53266                 Read Raster/Write Raster Value for
                                     Compare IRQ
  D013       53267                 Light-Pen Latch X Pos
  D014       53268                 Light-Pen Latch Y Pos
  D015       53269                 Sprite display Enable: 1 = Enable
  D016       53270                 VIC Control Register
                            7-6    Unused
                            5      ALWAYS SET THIS BIT TO 0 !
                            4      Multi-Color Mode: 1 = Enable (Text or
                                     Bit-Map)
                            3      Select 38/40 Column Text Display:
                                     1 = 40 Cols
                            2-0    Smooth Scroll to X Pos

  D017       53271                 Sprites 0-7 Expand 2x Vertical (Y)
  D018       53272                 VIC Memory Control Register
                            7-4    Video Matrix Base Address (inside VIC)
                            3-1    Character Dot-Data Base Address (inside
                                     VIC)
                            0      Select upper/lower Character Set

  D019       53273                 VIC Interrupt Flag Register (Bit = 1:
                                     IRQ Occurred)
                            7      Set on Any Enabled VIC IRQ Condition
                            3      Light-Pen Triggered IRQ Flag
                            2      Sprite to Sprite Collision IRQ Flag
                            1      Sprite to Background Collision IRQ Flag
                            0      Raster Compare IRQ Flag

  318   BASIC TO MACHINE LANGUAGE

   HEX      DECIMAL        BITS                 DESCRIPTION
  -------------------------------------------------------------------------

  D01A       53274                 IRQ Mask Register: 1 = Interrupt Enabled
  D01B       53275                 Sprite to Background Display Priority:
                                     1 = Sprite
  D01C       53276                 Sprites 0-7 Multi-Color Mode Select:
                                     1 = M.C.M.
  D01D       53277                 Sprites 0-7 Expand 2x Horizontal (X)
  D01E       53278                 Sprite to Sprite Collision Detect
  D01F       53279                 Sprite to Background Collision Detect
  D020       53280                 Border Color
  D021       53281                 Background Color 0
  D022       53282                 Background Color 1
  D023       53283                 Background Color 2
  D024       53284                 Background Color 3
  D025       53285                 Sprite Multi-Color Register 0
  D026       53286                 Sprite Multi-Color Register 1
  D027       53287                 Sprite 0 Color
  D028       53288                 Sprite 1 Color
  D029       53289                 Sprite 2 Color
  D02A       53290                 Sprite 3 Color
  D02B       53291                 Sprite 4 Color
  D02C       53292                 Sprite 5 Color
  D02D       53293                 Sprite 6 Color
  D02E       53294                 Sprite 7 Color

  D400-D7FF  54272-55295     MOS 6581 SOUND INTERFACE DEVICE (SID)

  D400       54272                 Voice 1: Frequency Control - Low-Byte
  D401       54273                 Voice 1: Frequency Control - High-Byte
  D402       54274                 Voice 1: Pulse Waveform Width - Low-Byte
  D403       54275          7-4    Unused
                            3-0    Voice 1: Pulse Waveform Width - High-
                                     Nybble

  D404       54276                 Voice 1: Control Register
                            7      Select Random Noise Waveform, 1 = On
                            6      Select Pulse Waveform, 1 = On
                            5      Select Sawtooth Waveform, 1 = On
                            4      Select Triangle Waveform, 1 = On

                                            BASIC TO MACHINE LANGUAGE   319

   HEX      DECIMAL        BITS                 DESCRIPTION
  -------------------------------------------------------------------------

                            3      Test Bit: 1 = Disable Oscillator 1
                            2      Ring Modulate Osc. 1 with Osc. 3 Output,
                                     1 = On
                            1      Synchronize Osc.1 with Osc.3 Frequency,
                                     1 = On
                            0      Gate Bit: 1 = Start Att/Dec/Sus,
                                             0 = Start Release

  D405       54277                 Envelope Generator 1: Attack/Decay Cycle
                                     Control
                            7-4    Select Attack Cycle Duration: 0-15
                            3-0    Select Decay Cycle Duration: 0-15

  D406       54278                 Envelope Generator 1: Sustain/Release
                                     Cycle Control
                            7-4    Select Sustain Cycle Duration: 0-15
                            3-0    Select Release Cycle Duration: 0-15

  D407       54279                 Voice 2: Frequency Control - Low-Byte
  D408       54280                 Voice 2: Frequency Control - High-Byte
  D409       54281                 Voice 2: Pulse Waveform Width - Low-Byte
  D40A       54282          7-4    Unused
                            3-0    Voice 2: Pulse Waveform Width - High-
                                     Nybble

  D40B       54283                 Voice 2: Control Register
                            7      Select Random Noise Waveform, 1 = On
                            6      Select Pulse Waveform, 1 = On
                            5      Select Sawtooth Waveform, 1 = On
                            4      Select Triangle Waveform, 1 = On
                            3      Test Bit: 1 = Disable Oscillator 1
                            2      Ring Modulate Osc. 2 with Osc. 1 Output,
                                     1 = On
                            1      Synchronize Osc.2 with Osc. 1 Frequency,
                                     1 = On
                            0      Gate Bit: 1 = Start Att/Dec/Sus,
                                             0 = Start Release

  320   BASIC TO MACHINE LANGUAGE

   HEX      DECIMAL        BITS                 DESCRIPTION
  -------------------------------------------------------------------------

  D40C       54284                 Envelope Generator 2: Attack / Decay
                                     Cycle Control
                            7-4    Select Attack Cycle Duration: 0-15
                            3-0    Select Decay Cycle Duration: 0-15

  D40D       54285                 Envelope Generator 2: Sustain / Release
                                     Cycle Control
                            7-4    Select Sustain Cycle Duration: 0-15
                            3-0    Select Release Cycle Duration: 0-15

  D40E       54286                 Voice 3: Frequency Control - Low-Byte
  D40F       54287                 Voice 3: Frequency Control - High-Byte
  D410       54288                 Voice 3: Pulse Waveform Width - Low-Byte
  D411       54289          7-4    Unused
                            3-0    Voice 3: Pulse Waveform Width - High-
                                     Nybble

  D412       54290                 Voice 3: Control Register
                            7      Select Random Noise Waveform, 1 = On
                            6      Select Pulse Waveform, 1 = On
                            5      Select Sawtooth Waveform, 1 = On
                            4      Select Triangle Waveform, 1 = On
                            3      Test Bit: 1 = Disable Oscillator 1
                            2      Ring Modulate Osc. 3 with Osc. 2 Output,
                                     1 = On
                            1      Synchronize Osc. 3 with Osc.2 Frequency,
                                     1 = On
                            0      Gate Bit: 1 = Start Att/Dec/Sus,
                                             0 = Start Release

  D413       54291                 Envelope Generator 3: Attack/Decay Cycle
                                     Control
                            7-4    Select Attack Cycle Duration: 0-15
                            3-0    Select Decay Cycle Duration: 0-15

  D414       54285                 Envelope Generator 3: Sustain / Release
                                     Cycle Control
                            7-4    Select Sustain Cycle Duration: 0-15
                            3-0    Select Release Cycle Duration: 0-15

                                            BASIC TO MACHINE LANGUAGE   321

   HEX      DECIMAL        BITS                 DESCRIPTION
  -------------------------------------------------------------------------

  D415       54293                 Filter Cutoff Frequency: Low-Nybble
                                     (Bits 2-0)
  D416       54294                 Filter Cutoff Frequency: High-Byte
  D417       54295                 Filter Resonance Control / Voice Input
                                     Control
                            7-4    Select Filter Resonance: 0-15
                            3      Filter External Input: 1 = Yes, 0 = No
                            2      Filter Voice 3 Output: 1 = Yes, 0 = No
                                   Filter Voice 2 Output: 1 = Yes, 0 = No
                            0      Filter Voice 1 Output: 1 = Yes, 0 = No

  D418       54296                 Select Filter Mode and Volume
                            7      Cut-Off Voice 3 Output: 1 = Off, 0 = On
                            6      Select Filter High-Pass Mode: 1 = On
                            5      Select Filter Band-Pass Mode: 1 = On
                            4      Select Filter Low-Pass Mode: 1 = On
                            3-0    Select Output Volume: 0-15

  D419       54297                 Analog/Digital Converter: Game Paddle 1
                                     (0-255)
  D41A       54298                 Analog/Digital Converter: Game Paddle 2
                                     (0-255)
  D41B       54299                 Oscillator 3 Random Number Generator
  D41C       54230                 Envelope Generator 3 Output
  D500-D7FF  54528-55295           SID IMAGES
  D800-DBFF  55296-56319           Color RAM (Nybbles)

  DC00-DCFF  56320-56575           MOS 6526 Complex Interface Adapter
                                     (CIA) #1

  DC00       56320                 Data Port A (Keyboard, Joystick,
                                     Paddles, Light-Pen)
                            7-0    Write Keyboard Column Values for
                                     Keyboard Scan
                            7-6    Read Paddles on Port A / B (01 = Port A,
                                     10 = Port B)
                            4      Joystick A Fire Button: 1 = Fire
                            3-2    Paddle Fire Buttons
                            3-0     Joystick A Direction (0-15)

  322   BASIC TO MACHINE LANGUAGE

   HEX      DECIMAL        BITS                 DESCRIPTION
  -------------------------------------------------------------------------

  DC01       56321                 Data Port B (Keyboard, Joystick,
                                     Paddles): Game Port 1
                            7-0    Read Keyboard Row Values for Keyboard
                                     Scan
                            7      Timer B Toggle/Pulse Output
                            6      Timer A: Toggle/Pulse Output
                            4      Joystick 1 Fire Button: 1 = Fire
                            3-2    Paddle Fire Buttons
                            3-0    Joystick 1 Direction

  DC02       56322                 Data Direction Register - Port A (56320)
  DC03       56323                 Data Direction Register - Port B (56321)
  DC04       56324                 Timer A: Low-Byte
  DC05       56325                 Timer A: High-Byte
  DC06       56326                 Timer B: Low-Byte
  DC07       56327                 Timer B: High-Byte

  DC08       56328                 Time-of-Day Clock: 1/10 Seconds
  DC09       56329                 Time-of-Day Clock: Seconds
  DC0A       56330                 Time-of-Day Clock: Minutes
  DC0B       56331                 Time-of-Day Clock: Hours + AM/PM Flag
                                     (Bit 7)
  DC0C       56332                 Synchronous Serial I/O Data Buffer
  DC0D       56333                 CIA Interrupt Control Register
                                     (Read IRQs/Write Mask)
                            7      IRQ Flag (1 = IRQ Occurred) / Set-
                                     Clear Flag
                            4      FLAG1 IRQ (Cassette Read / Serial Bus
                                     SRQ Input)
                            3      Serial Port Interrupt
                            2      Time-of-Day Clock Alarm Interrupt
                            1      Timer B Interrupt
                            0      Timer A Interrupt

                                            BASIC TO MACHINE LANGUAGE   323

   HEX      DECIMAL        BITS                 DESCRIPTION
  -------------------------------------------------------------------------

  DC0E       56334                 CIA Control Register A
                            7      Time-of-Day Clock Frequency: 1 = 50 Hz,
                                     0 = 60 Hz
                            6      Serial Port I/O Mode Output, 0 = Input

                            5      Timer A Counts: 1 = CNT Signals,
                                     0 = System 02 Clock
                            4      Force Load Timer A: 1 = Yes
                            3      Timer A Run Mode: 1 = One-Shot,
                                     0 = Continuous
                            2      Timer A Output Mode to PB6: 1 = Toggle,
                                     0 = Pulse
                            1      Timer A Output on PB6: 1 = Yes, 0 = No
                            0      Start/Stop Timer A: 1 = Start, 0 = Stop

  DC0F       56335                 CIA Control Register B
                            7      Set Alarm/TOD-Clock: 1 = Alarm,
                                     0 = Clock
                            6-5    Timer B Mode Select:
                                     00 = Count System 02 Clock Pulses
                                     01 = Count Positive CNT Transitions
                                     10 = Count Timer A Underflow Pulses
                                     11 = Count Timer A Underflows While
                                       CNT Positive
                            4-0    Same as CIA Control Reg. A - for Timer B

  DD00-DDFF  56576-56831           MOS 6526 Complex Interface Adapter
                                     (CIA) #2

  DD00       56576                 Data Port A (Serial Bus, RS-232, VIC
                                     Memory Control)
                            7      Serial Bus Data Input
                            6      Serial Bus Clock Pulse Input
                            5      Serial Bus Data Output
                            4      Serial Bus Clock Pulse Output
                            3      Serial Bus ATN Signal Output
                            2      RS-232 Data Output (User Port)
                            1-0    VIC Chip System Memory Bank Select
                                     (Default = 11)

  324   BASIC TO MACHINE LANGUAGE

   HEX      DECIMAL        BITS                 DESCRIPTION
  -------------------------------------------------------------------------

  DD01       56577                 Data Port B (User Port, RS-232)
                            7      User / RS-232 Data Set Ready
                            6      User / RS-232 Clear to Send
                            5      User
                            4      User / RS-232 Carrier Detect
                            3      User / RS-232 Ring Indicator
                            2      User / RS-232 Data Terminal Ready
                            1      User / RS-232 Request to Send
                            0      User / RS-232 Received Data

  DD02       56578                 Data Direction Register - Port A
  DD03       56579                 Data Direction Register - Port B
  DD04       56580                 Timer A: Low-Byte
  DD05       56581                 Timer A: High-Byte
  DD06       56582                 Timer B: Low-Byte
  DD07       56583                 Timer B: High-Byte
  DD08       56584                 Time-of-Day Clock: 1/10 Seconds
  DD09       56585                 Time-of-Day Clock: Seconds
  DD0A       56586                 Time-of-Day Clock: Minutes
  DD0B       56587                 Time-of-Day Clock: Hours + AM/PM Flag
                                     (Bit 7)
  DD0C       56588                 Synchronous Serial I/O Data Buffer
  DD0D       56589                 CIA Interrupt Control Register (Read
                                     NMls/Write Mask)
                            7        NMI Flag (1 = NMI Occurred) / Set-
                                       Clear Flag
                            4        FLAG1 NMI (User/RS-232 Received Data
                                       Input)
                            3        Serial Port Interrupt
                            1        Timer B Interrupt
                            0        Timer A Interrupt

  DD0E       56590                 CIA Control Register A
                            7      Time-of-Day Clock Frequency: 1 = 50 Hz,
                                     0 = 60 Hz
                            6      Serial Port I/O Mode Output, 0 = Input
                            5      Timer A Counts: 1 = CNT Signals,
                                     0 = System 02 Clock
                            4      Force Load Timer A: 1 = Yes

                                            BASIC TO MACHINE LANGUAGE   325

   HEX      DECIMAL        BITS                 DESCRIPTION
  -------------------------------------------------------------------------

                            3      Timer A Run Mode: 1 = One-Shot,
                                     0 = Continuous
                            2      Timer A Output Mode to PB6: 1 = Toggle,
                                     0 = Pulse
                            1      Timer A Output on PB6: 1 = Yes, 0 = No
                            0      Start/Stop Timer A: 1 = Start, 0 = Stop

  DD0F       56591                 CIA Control Register B
                            7      Set Alarm/TOD-Clock: 1=Alarm, 0=Clock
                            6-5    Timer B Mode Select:
                                     00 = Count System 02 Clock Pulses
                                     01 = Count Positive CNT Transitions
                                     10 = Count Timer A Underflow Pulses
                                     11 = Count Timer A Underflows While
                                       CNT Positive
                            4-0    Same as CIA Control Reg. A - for Timer B

  DE00-DEFF  56832-57087           Reserved for Future I/O Expansion
  DF00-DFFF  57088-57343           Reserved for Future I/O Expansion

  326   BASIC TO MACHINE LANGUAGE

                                                 CHAPTER 6

                                              INPUT/OUTPUT
                                                     GUIDE

                           o Introduction
                           o Output to the TV
                           o Output to Other Devices
                           o The Game Ports
                           o RS-232 Interface Description
                           o The User Port
                           o The Serial Bus
                           o The Expansion Port
                           o Z-80 Microprocessor Cartridge

                                     335

  INTRODUCTION

    Computers have three basic abilities: they can calculate, make deci-
  sions, and communicate. Calculation is probably the easiest to program.
  Most of the rules of mathematics are familiar to us. Decision making is
  not too difficult, since the rules of logic are relatively few, even if
  you don't know them too well yet.
    Communication is the most complex, because it involves the least
  exacting set of rules. This is not an oversight in the design of
  computers. The rules allow enough flexibility to communicate virtually
  anything, and in many possible ways. The only real rule is this: whatever
  sends information must present the information so that it can be
  understood by the receiver.

  OUTPUT TO THE TV

    The simplest form of output in BASIC is the PRINT statement. PRINT uses
  the TV screen as the output device, and your eyes are the input device
  because they use the information on the screen.
    When PRINTing on the screen, your main objective is to format the
  information on the screen so it's easy to read. You should try to think
  like a graphic artist, using colors, placement of letters, capital and
  lower case letters, as well as graphics to best communicate the
  information. Remember, no matter how smart your program, you want to be
  able to understand what the results mean to you.
    The PRINT statement uses certain character codes as "commands" to the
  cursor. The <CRSR> key doesn't actually display anything, it just makes
  the cursor change position. Other commands change colors, clear the
  screen, and insert or delete spaces. The <RETURN> key has a character
  code number (CHR$) of 13. A complete table of these codes is contained in
  Appendix C.
    There are two functions in the BASIC language that work with the PRINT
  statement. TAB positions the,cursor on the given position from the left
  edge of the screen, SPC moves the cursor right a given number of spaces
  from the current position.
    Punctuation marks in the PRINT statement serve to separate and format
  information. The semicolon (;) separates 2 items without any spaces in
  between. If it is the last thing on a line, the cursor remains after the
  last thing PRINTed instead of going down to the next line. It suppresses

  336   INPUT/OUTPUT GUIDE

  (replaces) the RETURN character that is normally PRINTed at the end of
  the line.
    The comma (,) separates items into columns. The Commodore 64 has 4
  columns of 10 characters each on the screen. When the computer PRINTs a
  comma, it moves the cursor right to the start of the next column. If it
  is past the last column of the line, it moves the cursor down to the next
  line. Like the semicolon, if it is the last item on a line the RETURN is
  suppressed.
    The quote marks ("") separate literal text from variables. The first
  quote mark on the line starts the literal area, and the next quote mark
  ends it. By the way, you don't have to have a final quote mark at the
  end of the line.
    The RETURN code (CHR$ code of 13) makes the cursor go to the next
  logical line on the screen. This is not always the very next line. When
  you type past the end of a line, that line is linked to the next line.
  The computer knows that both lines are really one long line. The links
  are held in the line link table (see the memory map for how this is set
  up).
    A logical line can be 1 or 2 screen lines long, depending on what was
  typed or PRINTed.  The logical line the cursor is on determines where the
  <RETURN> key sends it. The logical line at the top of the screen
  determines if the screen scrolls 1 or 2 lines at a time. There are other
  ways to use the TV as an output device. The chapter on graphics describes
  the commands to create objects that move across the screen. The VIC chip
  section tells how the screen and border colors and sizes are changed. And
  the sound chapter tells how the TV speaker creates music and special
  effects.

  OUTPUT TO OTHER DEVICES

    It is often necessary to send output to devices other than the screen,
  like a cassette deck, printer, disk drive, or modem. The OPEN statement
  in BASIC creates a "channel" to talk to one of these devices. Once the
  channel is OPEN, the PRINT# statement will send characters to that
  device.

  EXAMPLE of OPEN and PRINT# Statements:

    100 OPEN 4,4: PRINT# 4, "WRITING ON PRINTER"
    110 OPEN 3,8,3,"0:DISK-FILE,S,W":PRINT#3,"SEND TO DISK"
    120 OPEN 1,1,1,"TAPE-FILE": PRINT#1,"WRITE ON TAPE"
    130 OPEN 2,2,0,CHR$(10):PRINT#2,"SEND TO MODEM"

                                                   INPUT/OUTPUT GUIDE   337

    The OPEN statement is somewhat different for each device. The pa-
  rameters in the OPEN statement are shown in the table below for each
  device.

  TABLE of OPEN Statement Parameters:

    FORMAT: OPEN file#, device#, number, string

  +--------+---------+---------------------+------------------------------+
  | DEVICE | DEVICE# |       NUMBER        |            STRING            |
  +--------+---------+---------------------+------------------------------+
  |CASSETTE|    1    | 0 = Input           | File Name                    |
  |        |         | 1 = Output          |                              |
  |        |         | 2 = Output with EOT |                              |
  | MODEM  |    2    | 0                   | Control Registers            |
  | SCREEN |    3    | 0,1                 |                              |
  | PRINTER|  4 or 5 | 0 = Upper/Graphics  | Text Is PRINTed              |
  |        |         | 7 = Upper/Lower Case|                              |
  | DISK   | 8 to 11 | 2-14 = Data Channel | Drive #, File Name           |
  |        |         |                     | File Type, Read/Write        |
  |        |         | 15 = Command        | Command                      |
  |        |         |      Channel        |                              |
  +--------+---------+---------------------+------------------------------+

  OUTPUT TO PRINTER

    The printer is an output device similar to the screen. Your main con-
  cern when sending output to the printer is to create a format that is
  easy on the eyes. Your tools here include reversed, double-width, capital
  and lower case letters, as well as dot-programmable graphics.
    The SPC function works for the printer in the same way it works for the
  screen. However, the TAB function does not work correctly on the printer,
  because it calculates the current position on the line based on the
  cursor's position on the screen, not on the paper.
    The OPEN statement for the printer creates the channel for communi-
  cation. It also specifies which character set will be used, either upper
  case with graphics or upper and lower case.

  EXAMPLES of OPEN Statement for Printer:

    OPEN 1,4: REM UPPER CASE/GRAPHICS
    OPEN 1,4,7: REM UPPER AND LOWER CASE

  338   INPUT/OUTPUT GUIDE

    When working with one character set, individual lines can be PRINTed
  in the opposite character set. When in upper case with graphics, the
  cursor down character (CHR$(17)) switches the characters to the upper
  and lower case set. When in upper and lower case, the cursor up char-
  acter (CHR$(145)) allows upper case and graphics characters to be
  PRINTed.
    Other special functions in the printer are controlled through character
  codes. All these codes are simply PRINTed just like any other character.

  TABLE of Printer Control Character Codes:
  +----------+------------------------------------------------------------+
  | CHR$ CODE|                         PURPOSE                            |
  +----------+------------------------------------------------------------+
  |    10    |   Line feed                                                |
  |    13    |   RETURN (automatic line feed on CBM printers)             |
  |    14    |   Begin double-width character mode                        |
  |    15    |   End double-width character mode                          |
  |    18    |   Begin reverse character mode                             |
  |   146    |   End reverse character mode                               |
  |    17    |   Switch to upper/lower case character set                 |
  |   145    |   Switch to upper case/graphics character set              |
  |    16    |   Tab to position in next 2 characters                     |
  |    27    |   Move to specified dot position                           |
  |     8    |   Begin dot-programmable graphic mode                      |
  |    26    |   Repeat graphics data                                     |
  +----------+------------------------------------------------------------+
    See your Commodore printer's manual for details on using the command
  codes.

  OUTPUT TO MODEM

    The modem is a simple device that can translate character codes into
  audio pulses and vice-versa, so that computers can communicate over
  telephone lines. The OPEN statement for the modem sets up the parameters
  to match the speed and format of the other computer you are communicating
  with. Two characters can be sent in the string at the end
  of the OPEN statement.
    The bit positions of the first character code determine the baud rate,
  number of data bits, and number of stop bits. The second code is op-
  tional, and its bits specify the parity and duplex of the transmission.
  See the RS-232 section or your VICMODEM manual for specific details on
  this device.

                                                   INPUT/OUTPUT GUIDE   339

  EXAMPLE of OPEN Statement for Modem:

    OPEN 1,2,0,CHR$(6): REM 300 BAUD
    100 OPEN 2,2,0,CHR$(163) CHR$(112): REM 110 BAUD, ETC.

    Most computers use the American Standard Code for Information In-
  terchange, known as ASCII (pronounced ASK-KEY). This standard set of
  character codes is somewhat different from the codes used in the Com-
  modore 64. When communicating with other computers, the Commodore
  character codes must be translated into their ASCII counterparts. A table
  of standard ASCII codes is included in this book in Appendix C.
    Output to the modem is a fairly uncomplicated task, aside from the need
  for character translation. However, you must know the receiving device
  fairly well, especially when writing programs where your computer "talks"
  to another computer without human intervention. An example of this would
  be a terminal program that automatically types in your account number and
  secret password. To do this successfully, you must carefully count the
  number of characters and RETURN characters. Otherwise, the computer
  receiving the characters won't know what to do with them.

  WORKING WITH CASSETTE TAPE

    Cassette tapes have an almost unlimited capacity for data. The longer
  the tape, the more information it can store. However, tapes are limited
  in time. The more data on the tape, the longer the time it takes to find
  the information.
    The programmer must try to minimize the time factor when working with
  tape storage. One common practice is to read the entire cassette data
  file into RAM, then process it, and then re-write all the data on the
  tape. This allows you to sort, edit, and examine your data. However, this
  limits the size of your files to the amount of available RAM.
    If your data file is larger than the available RAM, it is probably time
  to switch to using the floppy disk. The disk can read data at any
  position on the disk, without needing to read through all the other data.
  You can write data over old data without disturbing the rest of the file.
  That's why the disk is used for all business applications like ledgers
  and mailing lists.
    The PRINT# statement formats data just like the PRINT statement does.
  All punctuation works the same. But remember, you're not working with the
  screen now. The formatting must be done with the INPUT# statement
  constantly in mind.

  340   INPUT/OUTPUT GUIDE

    Consider the statement PRINT# 1, A$, B$, C$. When used with the screen,
  the commas between the variables provide enough blank space between items
  to format them into columns ten characters wide. On cassette, anywhere
  from 1 to 10 spaces will be added, depending on th length of the strings.
  This wastes space on your tape.
    Even worse is what happens when the INPUT# statement tries to read
  these strings. The statement INPUT# 1, A$, B$, C$ will discover no data
  for B$ and C$. A$ will contain all three variables, plus the spaces be-
  tween them. What happens? Here's a look at the tape file:

    A$="DOG" B$="CAT" C$="TREE"
    PRINT# 1, A$, B$, C$

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
    D O G                 C  A  T                       T  R  E  E  RETURN

    The INPUT# statement works like the regular INPUT statement. When
  typing data into the INPUT statement, the data items are separated,
  either by hitting the <RETURN> key or using commas to separate them. The
  PRINT# statement puts a RETURN at the end of a line just like the PRINT
  statement. A$ fills up with all three values because there's no separator
  on the tape between them, only after all three.
    A proper separator would be a comma (,) or a RETURN on the tape. The
  RETURN code is automatically put at the end of a PRINT or PRINT#
  statement. One way to put the RETURN code between each item is to us only
  one item per PRINT# statement. A better way is to set a variable to the
  RETURN CHR$ code, which is CHR$(13), or use a comma. The statement for
  this is R$=",":PRINT#1, A$ R$ B$ R$ C$. Don't use commas or any other
  punctuation between the variable names, since the Commodore 64 can tell
  them apart and they'll only use up space in your program.
    A proper tape file looks like this:

    1 2 3 4 5 6 7 8 9 10 11 12 13

    D O G , C A T , T  R  E  E  RETURN

    The GET# statement will pick data from the tape one character at a
  time. It will receive each character, including the RETURN code and other
  punctuation. The CHR$(0) code is received as an empty string, not as a
  one character string with a code of 0. If you try to use the ASC function
  on an empty string, you get the error message ILLEGAL QUANTITY ERROR.

                                                   INPUT/OUTPUT GUIDE   341

    The line GET# 1, A$: A= ASC(A$) is commonly used in programs to examine
  tape data. To avoid error messages, the line should be modified to
  GET#1, A$: A=ASC(A$+CHR$(0)). The CHR$(0) at the end acts as insurance
  against empty strings, but doesn't affect the ASC function when there are
  other characters in A$.

  DATA STORAGE ON FLOPPY DISKETTES

    Diskettes allow 3 different forms of data storage. Sequential files are
  similar to those on tape, but several can can be used at the same time.
  Relative files let you organize the data into records, and then read and
  replace individual records within the file. Random files let you work
  with data anywhere on the disk. They are organized into 256 byte sections
  called blocks.
    The PRINT# statement's limitations are discussed in the section on
  cassette tape. The same limitations to format apply on the disk. RETURNs
  or commas are needed to separate your data. The CHR$(0) is still read by
  the GET# statement as an empty string.
    Relative and random files both make use of separate data and command
  "channels." Data written to the disk goes through the data channel, where
  it is stored in a temporary buffer in the disk's RAM. When the record or
  block is complete, a command is sent through the command channel that
  tells the drive where to put the data, and the entire buffer is written.
    Applications that require large amounts of data to be processed are
  best stored in relative disk files. These will use the least amount of
  time and provide the best flexibility for the programmer. Your disk drive
  manual gives a complete programming guide to use of disk files.

  342   INPUT/OUTPUT GUIDE

  THE GAME PORTS

    The Commodore 64 has two 9-pin Game Ports which allow the use of
  joysticks, paddies, or a light pen. Each port will accept either one joy-
  stick or one paddle pair. A light pen can be plugged into Port A (only)
  for special graphic control, etc. This section gives you examples of how
  to use the joysticks and paddies from both BASIC and machine language.
    The digital joystick is connected to CIA #1 (MOS 6526 Complex Interface
  Adapter). This input/output device also handles the paddle fire buttons
  and keyboard scanning. The 6526 CIA chip has 16 registers which are in
  memory locations 56320 through 56335 inclusive ($DC00 to $DC0F). Port A
  data appears at location 56320 (DC00) and Port B data is found at
  location 56321 ($DC01).
    A digital joystick has five distinct switches, four of the switches are
  used for direction and one of the switches is used for the fire button.
  The joystick switches are arranged as shown:

                                    (Top)
                FIRE
             (Switch 4)
                                     UP
                                 (Switch 0)
                                      |
                                      |
                                      |
                         LEFT         |         RIGHT
                               -------+-------
                      (Switch 2)      |       (Switch 3)
                                      |
                                      |
                                      |
                                    DOWN
                                 (Switch 1)

    These switches correspond to the lower 5 bits of the data in location
  56320 or 56321. Normally the bit is set to a one if a direction is NOT
  chosen or the fire button is NOT pressed. When the fire button is

                                                   INPUT/OUTPUT GUIDE   343

  pressed, the bit (bit 4 in this case) changes to a 0. To read the
  joystick from BASIC, the following subroutine should be used:

start tok64 page344.prg
  10 fork=0to10:rem set up direction string
  20 readdr$(k):next
  30 data"","n","s","","w","nw"
  40 data"sw","","e","ne","se"
  50 print"going...";
  60 gosub100:rem read the joystick
  65 ifdr$(jv)=""then80:rem check if a direction was chosen
  70 printdr$(jv);" ";:rem output which direction
  80 iffr=16then60:rem check if fire button was pushed
  90 print"-----f-----i-----r-----e-----!!!":goto60
  100 jv=peek(56320):rem get joystick value
  110 fr=jvand16:rem form fire button status
  120 jv=15-(jvand15):rem form direction value
  130 return
stop tok64

  +-----------------------------------------------------------------------+
  | NOTE: For the second joystick, set JV = PEEK (56321).                 |
  +-----------------------------------------------------------------------+

    The values for JV correspond to these directions:

                       +-------------+---------------+
                       | JV EQUAL TO |   DIRECTION   |
                       +-------------+---------------+
                       |      0      |          NONE |
                       |      1      |            UP |
                       |      2      |          DOWN |
                       |      3      |             - |
                       |      4      |          LEFT |
                       |      5      |     UP & LEFT |
                       |      6      |   DOWN & LEFT |
                       |      7      |             - |
                       |      8      |         RIGHT |
                       |      9      |    UP & RIGHT |
                       |     10      |  DOWN & RIGHT |
                       +-------------+---------------+

  344   INPUT/OUTPUT GUIDE

    A small machine code routine which accomplishes the same task is as
  follows:

                      ; joystick - button read routine
                      ;
                      ; author - bill hindorff
                      ;
dx = $c110
dy = $c111

* = $c200

djrr    lda $dc00     ; get input from port a only
djrrb   ldy #0        ; this routine reads and decodes the
        ldx #0        ; joystick/firebutton input data in
        lsr a         ; the accumulator. this least significant
        bcs djr0      ; 5 bits contain the switch closure
        dey           ; information. if a switch is closed then it
djr0    lsr a         ; produces a zero bit. if a switch is open then
        bcs djr1      ; it produces a one bit. The joystick dir-
        iny           ; ections are right, left, forward, backward
djr1    lsr a         ; bit3=right, bit2=left, bit1=backward,
        bcs djr2      ; bit0=forward and bit4=fire button.
        dex           ; at rts time dx and dy contain 2's compliment
djr2    lsr a         ; direction numbers i.e. $ff=-1, $00=0, $01=1.
        bcs djr3      ; dx=1 (move right), dx=-1 (move left),
        inx           ; dx=0 (no x change). dy=-1 (move up screen),
djr3    lsr a         ; dy=0 (move down screen), dy=0 (no y change).
        stx dx        ; the forward joystick position corresponds
        sty dy        ; to move up the screen and the backward
        rts           ; position to move down screen.
                      ;
                      ; at rts time the carry flag contains the fire
                      ; button state. if c=1 then button not pressed.
                      ; if c=0 then pressed.
.end

                                                   INPUT/OUTPUT GUIDE   345

  PADDLES

    A paddle is connected to both CIA #1 and the SID chip (MOS 6581 Sound
  Interface Device) through a game port. The paddle value is read via the
  SID registers 54297 ($D419) and 54298 ($D41A). PADDLES ARE NOT RELIABLE
  WHEN READ FROM BASIC ALONE!!!! The best way to use paddles, from BASIC or
  machine code, is to use the following machine language routine... (SYS to
  it from BASIC then PEEK the memory locations used by the subroutine).

                      ; four paddle read routine (can also be used for two)
                      ;
                      ; author - bill hindorff
                      ;
porta=$dc00
ciddra=$dc02
sid=$d400

*=$c100

buffer  *=*+1
pdlx    *=*+2
pdly    *=*+2
btna    *=*+1
btnb    *=*+1

* = $c000

pdlrd   ldx #1        ; for four paddles or two analog joysticks
pdlrd0                ; entry point for one pair (condition x 1st)
        sei
        lda ciddra    ; get current value of ddr
        sta buffer    ; save it away
        lda #$c0
        sta ciddra    ; set port a for input
        lda #$80
pdlrd1
        sta porta     ; address a pair of paddles
        ldy #$80      ; wait a while
pdlrd2
        nop
        dey
        bpl pdlrd2
        lda sid+25    ; get x value
        sta pdlx,x
        lda sid+26
        sta pdly,x    ; get y value
        lda porta     ; time to read paddle fire buttons
        ora #80       ; make it the same as other pair
        sta btna      ; bit 2 is pdl x, bit 3 is pdl y
        lda #$40
        dex           ; all pairs done?
        bpl pdlrd1    ; no
        lda buffer
        sta ciddra    ; restore previous value of ddr
        lda porta+1   ; for 2nd pair -
        sta btnb      ; bit 2 is pdl x, bit 3 is pdl y
        cli
        rts
.end

    The paddles can be read by using the following BASIC program:

start tok64 page347.prg
  10 c=12*4096:rem set paddle routine start
  11 rem poke in the paddle reading routine
  15 fori=0to63:reada:pokec+i,a:next
  20 sysc:rem call the paddle routine
  30 p1=peek(c+257):rem set paddle one value
  40 p2=peek(c+258):rem set paddle two value
  50 p3=peek(c+259):rem set paddle three value
  60 p4=peek(c+260):rem set paddle four value
  61 rem read fire button status
  62 s1=peek(c+261):s2=peek(c+262)
  70 printp1,p2,p3,p4:rem print paddle values
  72 rem print fire button status
  75 print:print"fire a ";s1,"fire b ";s2
  80 forw=1to50:next:rem wait a while
  90 print"{clear}":print:goto20:rem clear screen and do again
  95 rem data for machine code routine
  100 data162,1,120,173,2,220,141,0,193,169,192,141,2,220,169
  110 data128,141,0,220,160,128,234,136,16,252,173,25,212,157
  120 data1,193,173,26,212,157,3,193,173,0,220,9,128,141,5,193
  130 data169,64,202,16,222,173,0,193,141,2,220,173,1,220,141
  140 data6,193,88,96
stop tok64

                                                   INPUT/OUTPUT GUIDE   347

  LIGHT PEN

    The light pen input latches the current screen position into a pair of
  registers (LPX, LPY) on a low-going edge. The X position register 19
  ($13) will contain the 8 MSB of the X position at the time of transition.
  Since the X position is defined by a 512-state counter (9 bits),
  resolution to 2 horizontal dots is provided. Similarly, the Y position is
  latched in its register 20 ($14), but here 8 bits provide single raster
  resolution within the visible display. The light pen latch may be
  triggered only once per frame, and subsequent triggers within the same
  frame will have no effect. Therefore, you must take several samples
  before turning the pen to the screen (3 or more samples average),
  depending upon the characteristics of your light pen.

  RS-232 INTERFACE DESCRIPTION

  GENERAL OUTLINE

    The Commodore 64 has a built-in RS-232 interface for connection to any
  RS-232 modem, printer, or other device. To connect a device to the
  Commodore 64, all you need is a cable and a little bit of programming.
    RS-232 on the Commodore 64 is set-up in the standard RS-232 format, but
  the voltages are TTL levels (0 to 5V) rather than the normal RS-232 -12
  to 12 volt range. The cable between the Commodore 64 and the RS-232
  device should take care of the necessary voltage conversions. The
  Commodore RS-232 interface cartridge handles this properly.
    The RS-232 interface software can be accessed from BASIC or from the
  KERNAL for machine language programming.
    RS-232 on the BASIC level uses the normal BASIC commands: OPEN, CLOSE,
  CMD, INPUT#, GET#, PRINT#, and the reserved variable ST. INPUT# and GET#
  fetch data from the receiving buffer, while PRINT# and CMD place data
  into the transmitting buffer. The use of these commands (and examples)
  will be described in more detail later in this chapter.
    The RS-232 KERNAL byte and bit level handlers run under the control of
  the 6526 CIA #2 device timers and interrupts. The 6526 chip generates

  348   INPUT/OUTPUT GUIDE

  NMI (Non-Maskable Interrupt) requests for RS-232 processing. This allows
  background RS-232 processing to take place during BASIC and machine
  language programs. There are built-in hold-offs in the KERNAL, cassette,
  and serial bus routines to prevent the disruption of data storage or
  transmission by the NMIs that are generated by the RS-232 routines.
  During cassette or serial bus activities, data can NOT be received from
  RS-232 devices. But because these hold-offs are only local (assuming
  you're careful about your programming) no interference should result.
    There are two buffers in the Commodore 64 RS-232 interface to help
  prevent the loss of data when transmitting or receiving RS-232 informa-
  tion.
    The Commodore 64 RS-232 KERNAL buffers consist of two first-in/first-
  out (FIFO) buffers, each 256 bytes long, at the top of memory. The
  OPENing of an RS-232 channel automatically allocates 512 bytes of memory
  for these buffers. If there is not enough free space beyond the end of
  your BASIC program no error message will be printed, and the end of your
  program will be destroyed. SO BE CAREFUL!
    These buffers are automatically removed by using the CLOSE command.

  OPENING AN RS-232 CHANNEL

    Only one RS-232 channel should be open at any time; a second OPEN
  statement will cause the buffer pointers to be reset. Any characters in
  either the transmit buffer or the receive buffer will be lost.
    Up to 4 characters can be sent in the filename field. The first two are
  the control and command register characters; the other two are reserved
  for future system options. Baud rate, parity, and other options can be
  selected through this feature.
    No error-checking is done on the control word to detect a non-
  implemented baud rate. Any illegal control word will cause the system
  output to operate at a very slow rate (below 50 baud).

  BASIC SYNTAX:

    OPEN lfn,2,0,"<control register><command register><opt baud low><opt
  baud high>"
    lfn-The logical file number (lfn) then can be any number from 1 through
  255. But be aware of the fact that if you choose a logical file number
  that is greater than 127, then a line feed will follow all carriage
  returns.

                                                   INPUT/OUTPUT GUIDE   349

                   +-+-+-+ +-+ +-+-+-+-+
                   |7|6|5| |4| |3|2|1|0|
                   +-+-+-+ +-+ +-+-+-+-+   BAUD RATE
                    | | |   |  +-+-+-+-+----------------+
      STOP BITS ----+ | |   |  |0|0|0|0| USER RATE  [NI]|
                      | |   |  +-+-+-+-+----------------+
   0 - 1 STOP BIT     | |   |  |0|0|0|1|       50 BAUD  |
   1 - 2 STOP BITS    | |   |  +-+-+-+-+----------------+
                      | |   |  |0|0|1|0|       75       |
                      | |   |  +-+-+-+-+----------------+
                      | |   |  |0|0|1|1|      110       |
                      | |   |  +-+-+-+-+----------------+
     WORD LENGTH -----+-+   |  |0|1|0|0|      134.5     |
                            |  +-+-+-+-+----------------+
  +---+-----------+         |  |0|1|0|1|      150       |
  |BIT|           |         |  +-+-+-+-+----------------+
  +-+-+    DATA   |         |  |0|1|1|0|      300       |
  |6|5|WORD LENGTH|         |  +-+-+-+-+----------------+
  +-+-+-----------+         |  |0|1|1|1|      600       |
  |0|0|  8 BITS   |         |  +-+-+-+-+----------------+
  +-+-+-----------+         |  |1|0|0|0|     1200       |
  |0|1|  7 BITS   |         |  +-+-+-+-+----------------+
  +-+-+-----------+         |  |1|0|0|1|    (1800)  2400|
  |1|0|  6 BITS   |         |  +-+-+-+-+----------------+
  +-+-+-----------+         |  |1|0|1|0|     2400       |
  |1|1|  5 BITS   |         |  +-+-+-+-+----------------+
  +-+-+-----------+         |  |1|0|1|1|     3600   [NI]|
                            |  +-+-+-+-+----------------+
                            |  |1|1|0|0|     4800   [NI]|
        UNUSED -------------+  +-+-+-+-+----------------+
                               |1|1|0|1|     7200   [NI]|
                               +-+-+-+-+----------------+
          Figure 6-1.          |1|1|1|0|     9600   [NI]|
     Control Register Map.     +-+-+-+-+----------------+
                               |1|1|1|1|    19200   [NI]|
                               +-+-+-+-+----------------+
    <control register>- Is a single byte character (see Figure 6-1, Control
  Register Map) required to specify the baud rates. If the lower 4 bits of
  the baud rate is equal to zero (0), the <opt baud low><opt baud high>
  characters give you a rate based on the following:
    <opt baud low>=<system frequency/rate/2-100-<opt baud high>*256
    <opt baud high>=INT((system frequency/rate/2-100)/256

  350   INPUT/OUTPUT GUIDE

                              +-+-+-+-+-+-+-+-+
                              |7|6|5|4|3|2|1|0|
                              +-+-+-+-+-+-+-+-+
                               | | | | | | | |
                               | | | | | | | |
                               | | | | | | | |
                               | | | | | | | |
            PARITY OPTIONS ----+-+-+ | | | | +----- HANDSHAKE
  +---+---+---+---------------------+| | | |
  |BIT|BIT|BIT|     OPERATIONS      || | | |        0 - 3-LINE
  | 7 | 6 | 5 |                     || | | |        1 - X-LINE
  +---+---+---+---------------------+| | | |
  | - | - | 0 |PARITY DISABLED, NONE|| | | |
  |   |   |   |GENERATED/RECEIVED   || | | |
  +---+---+---+---------------------+| | | +------- UNUSED
  | 0 | 0 | 1 |ODD PARITY           || | +--------- UNUSED
  |   |   |   |RECEIVER/TRANSMITTER || +----------- UNUSED
  +---+---+---+---------------------+|
  | 0 | 1 | 1 |EVEN PARITY          ||
  |   |   |   |RECEIVER/TRANSMITTER |+------------- DUPLEX
  +---+---+---+---------------------+
  | 1 | 0 | 1 |MARK TRANSMITTED     |               0 - FULL DUPLEX
  |   |   |   |PARITY CHECK DISABLED|               1 - HALF DUPLEX
  +---+---+---+---------------------+
  | 1 | 1 | 1 |SPACE TRANSMITTED    |
  |   |   |   |PARITY CHECK DISABLED|
  +---+---+---+---------------------+

                      Figure 6-2. Command Register Map.

  The formulas above are based on the fact that:

    system frequency = 1.02273E6 NTSC (North American TV standard)
                     = 0.98525E6 PAL (U.K. and most European TV standard)

    <command register>- Is a single byte character (see Figure 6-2, Command
  Register Map) that defines other terminal parameters. This character is
  NOT required.

                                                    INPUT/OUTPUT GUIDE  351

  KERNAL ENTRY:

    OPEN ($FFC0) (See KERNAL specifications for more information on entry
  conditions and instructions.)

  +-----------------------------------------------------------------------+
  | IMPORTANT NOTE: In a BASIC program, the RS-232 OPEN command should be |
  | performed before creating any variables or arrays because an automatic|
  | CLR is performed when an RS-232 channel is OPENed (This is due to the |
  | allocation of 512 bytes at the top of memory.) Also remember that your|
  | program will be destroyed if 512 bytes of space are not available at  |
  | the time of the OPEN statement.                                       |
  +-----------------------------------------------------------------------+

  GETTING DATA FROM AN RS-232 CHANNEL

    When getting data from an RS-232 channel, the Commodore 64 receiver
  buffer will hold up to 255 characters before the buffer overflows. This
  is indicated in the RS-232 status word (ST in BASIC, or RSSTAT in machine
  language). If an overflow occurs, then all characters received during a
  full buffer condition, from that point on, are lost. Obviously, it pays
  to keep the buffer as clear as possible.
    If you wish to receive RS-232 data at high speeds (BASIC can only go so
  fast, especially considering garbage collects. This can cause the re-
  ceiver buffer to overflow), you will have to use machine language
  routines to handle this type of data burst.

  BASIC SYNTAX:

    Recommended: GET#lfn, <string variable>
    NOT Recommended: INPUT#lfn <variable list>

  KERNAL ENTRIES:

    CHKIN ($FFC6)-See Memory Map for more information on entry and exit
  conditions.
    GETIN ($FFE4)-See Memory Map for more information on entry and exit
  conditions.
    CHRIN ($FFCF)-See Memory Map for more information on entry and exit
  conditions.

  352   INPUT/OUTPUT GUIDE

  +-----------------------------------------------------------------------+
  | NOTES:                                                                |
  |   If the word length is less than 8 bits, all unused bit(s) will be   |
  | assigned a value of zero.                                             |
  |   If a GET# does not find any data in the buffer, the character "" (a |
  | null) is returned.                                                    |
  |   If INPUT# is used, then the system will hang in a waiting condition |
  | until a non-null character and a following carriage return is         |
  | received. Therefore, if the Clear To Send (CTS) or Data Set Ready     |
  | (DSR) line(s) disappear during character INPUT#, the system will hang |
  | in a RESTORE-only state. This is why the INPUT# and CHRIN routines are|
  | NOT recommended.                                                      |
  |   The routine CHKIN handles the x-line handshake which follows the EIA|
  | standard (August 1979) for RS-232-C interfaces. (The Request To Send  |
  | (RTS), CTS, and Received line signal (DCD) lines are implemented with |
  | the Commodore 64 computer defined as the Data Terminal device.)       |
  +-----------------------------------------------------------------------+

  SENDING DATA TO AN RS-232 CHANNEL

    When sending data, the output buffer can hold 255 characters before a
  full buffer hold-off occurs. The system will wait in the CHROUT routine
  until transmission is allowed or the <RUN/STOP> and <RESTORE> keys are
  used to recover the system through a WARM START.

  BASIC SYNTAX:

    CMD lfn-acts same as in the BASIC specifications.
    PRINT#lfn,<variable list>

  KERNAL ENTRIES:

    CHKOUT ($FFC9)-See Memory Map for more information on entry and exit
  conditions.
    CHROUT ($FFD2)-See Memory Map for more information on entry conditions.

                                                   INPUT/OUTPUT GUIDE   353

  +-----------------------------------------------------------------------+
  | IMPORTANT NOTES: There is no carriage-return delay built into the     |
  | output channel. This means that a normal RS-232 printer cannot        |
  | correctly print, unless some form of hold-off (asking the Commodore 64|
  | to wait) or internal buffering is implemented by the printer. The     |
  | hold-off can easily be implemented in your program. If a CTS (x-line) |
  | handshake is implemented, the Commodore 64 buffer will fill, and then |
  | hold-off more output until transmission is allowed by the RS-232      |
  | device. X-line handshaking is a handshake routine that uses multi-    |
  | lines for receiving and transmitting data.                            |
  |   The routine CHKOUT handles the x-line handshake, which follows the  |
  | EIA standard (August 1979) for RS-232-C interfaces. The RTS, CTS, and |
  | DCD lines are implemented with the Commodore 64 defined as the Data   |
  | Terminal Device.                                                      |
  +-----------------------------------------------------------------------+

  CLOSING AN RS-232 DATA CHANNEL

    Closing an RS-232 file discards all data in the buffers at the time of
  execution (whether or not it had been transmitted or printed out), stops
  all RS-232 transmitting and receiving, sets the RTS and transmitted data
  (Sout) lines high, and removes both RS-232 buffers.

  BASIC SYNTAX:

    CLOSE lfn

  KERNAL ENTRY:

    CLOSE ($FFC3)-See Memory Map for more information on entry and exit
  conditions.

  +-----------------------------------------------------------------------+
  | NOTE: Care should be taken to ensure all data is transmitted before   |
  | closing the channel. A way to check this from BASIC is:               |
  |                                                                       |
  | 100 SS=ST: IF(SS=0 OR SS=8) THEN 100                                  |
  | 110 CLOSE lfn                                                         |
  +-----------------------------------------------------------------------+

  354   INPUT/OUTPUT GUIDE

                         Table 6-1. User-Port Lines
  +-----------------------------------------------------------------------+
  |                   (6526 DEVICE #2 Loc. $DD00-$DD0F)                   |
  +---+-----+----------------------+------+-------+-------+---------------+
  |PIN| 6526|      DESCRIPTION     | EIA  |  ABV  |  IN/  |     MODES     |
  | ID|  ID |                      |      |       |  OUT  |               |
  +---+-----+----------------------+------+-------+-------+---------------+
  | C | PB0 | RECEIVED DATA        | (BB) |  Sin  |  IN   |     1 2       |
  | D | PB1 | REQUEST TO SEND      | (CA) |  RTS  |  OUT  |     1*2       |
  | E | PB2 | DATA TERMINAL READY  | (CD) |  DTR  |  OUT  |     1*2       |
  | F | PB3 | RING INDICATOR       | (CE) |  RI   |  IN   |         3     |
  | H | PB4 | RECEIVED LINE SIGNAL | (CF) |  DCD  |  IN   |       2       |
  | I | PB5 | UNASSIGNED           | (  ) |  XXX  |  IN   |         3     |
  | K | PB6 | CLEAR TO SEND        | (CB) |  CTS  |  IN   |       2       |
  | L | PB7 | DATA SET READY       | (CC) |  DSR  |  IN   |       2       |
  |   |     |                      |      |       |       |               |
  | B |FLAG2| RECEIVED DATA        | (BB) |  Sin  |  IN   |     1 2       |
  | M | PA2 | TRANSMITTED DATA     | (BA) |  Sout |  OUT  |     1 2       |
  |   |     |                      |      |       |       |               |
  | A | GND | PROTECTIVE GROUND    | (AA) |  GND  |       |     1 2       |
  | N | GND | SIGNAL GROUND        | (AB) |  GND  |       |     1 2 3     |
  +---+-----+----------------------+------+-------+-------+---------------+
  | MODES:                                                                |
  | 1) 3-LINE INTERFACE (Sin,Sout,GND)                                    |
  | 2) X-LINE INTERFACE                                                   |
  | 3) USER AVAILABLE ONLY (Unused/unimplemented in code.)                |
  | * These lines are held high during 3-LINE mode.                       |
  +-----------------------------------------------------------------------+
  +-----------------------------------------------------------------------+
  | [7] [6] [5] [4] [3] [2] [1] [0] (Machine Lang.-RSSTAT                 |
  |  |   |   |   |   |   |   |   +- PARITY ERROR BIT                      |
  |  |   |   |   |   |   |   +----- FRAMING ERROR BIT                     |
  |  |   |   |   |   |   +--------- RECEIVER BUFFER OVERRUN BIT           |
  |  |   |   |   |   +------------- RECEIVER BUFFER-EMPTY                 |
  |  |   |   |   |                  (USE TO TEST AFTER A GET#)            |
  |  |   |   |   +----------------- CTS SIGNAL MISSING BIT                |
  |  |   |   +--------------------- UNUSED BIT                            |
  |  |   +------------------------- DSR SIGNAL MISSING BIT                |
  |  +----------------------------- BREAK DETECTED BIT                    |
  |                                                                       |
  +-----------------------------------------------------------------------+
                     Figure 6-3. RS-232 Status Register.

                                                   INPUT/OUTPUT GUIDE   355

  +-----------------------------------------------------------------------+
  | NOTES:                                                                |
  |   If the BIT=0, then no error has been detected.                      |
  |   The RS-232 status register can be read from BASIC using the variable|
  | ST.                                                                   |
  |   If ST is read by BASIC or by using the KERNAL READST routine the    |
  | RS-232 status word is cleared when you exit. If multiple uses of the  |
  | STATUS word are necessary the ST should be assigned to another        |
  | variable. For example:                                                |
  |                                                                       |
  | SR=ST: REM ASSIGNS ST TO SR                                           |
  |                                                                       |
  |   The RS-232 status is read (and cleared) only when the RS-232 channel|
  | was the last external I/O used.                                       |
  +-----------------------------------------------------------------------+

  SAMPLE BASIC PROGRAMS

start tok64 page356.prg
  10 rem this program sends and receives data to/from a silent 700
  11 rem terminal modified for pet ascii
  20 rem ti silent 700 set-up: 300 baud, 7-bit ascii, mark parity,
  21 rem full duplex
  30 rem same set-up at computer using 3-line interface
  100 open2,2,3,chr$(6+32)+chr$(32+128):rem open the channel
  110 get#2,a$:rem turn on the receiver channel (toss a null)
  200 rem main loop
  210 get b$:rem get from computer keyboard
  220 if b$<>""then print#2,b$;:rem if a key pressed, send to terminal
  230 get#2,c$:rem get a key from the terminal
  240 print b$;c$;:rem print all inputs to computer screen
  250 sr=st:ifsr=0orsr=8then200:rem check status, if good then continue
  300 rem error reporting
  310 print "error: ";
  320 if sr and 1 then print"parity"
  330 if sr and 2 then print"frame"
  340 if sr and 4 then print"receiver buffer full"
  350 if sr and 128 then print"break"
  360 if (peek(673)and1)then360:rem wait until all chars transmitted
  370 close 2:end
stop tok64

  356   INPUT/OUTPUT GUIDE

start tok64 page357.prg
  10 rem this program sends and receives true ascii data
  100 open 5,2,3,chr$(6)
  110 dim f%(255),t%(255)
  200 for j=32 to 64:t%(j)=j:next
  210 t%(13)=13:t%(20)=8:rv=18:ct=0
  220 for j=65 to 90:k=j+32:t%=(j)=k:next
  230 for j=91 to 95:t%(j)=j:next
  240 for j=193 to 218:k=j-128:t%(j)=k:next
  250 t%(146)=16:t%(133)=16
  260 for j=0 to 255
  270 k=t%(j)
  280 if k<>0then f%(k)=j:f%(k+128)=j
  290 next
  300 print" "chr$(147)
  310 get#5,a$
  320 if a$=""or st<>0 then 360
  330 print" "chr$(157);chr$(f%(asc(a$)));
  340 if f%(asc(a$))=34 then poke212,0
  350 goto310
  360 printchr$(rv)" "chr$(157);chr$(146);:get a$
  370 if a$<>""then print#5,chr$(t%(asc(a$)));
  380 ct=ct+1
  390 if ct=8 thenct=0:rv=164-rv
  410 goto310
stop tok64

  RECEIVER/TRANSMITTER BUFFER BASE LOCATION POINTERS

    $00F7-REBUF-A two-byte pointer to the Receiver Buffer base location.
    $00F9-ROBUF-A two-byte pointer to the Transmitter Buffer base location.

    The two locations above are set up by the OPEN KERNAL routine, each
  pointing to a different 256-byte buffer. They are de-allocated by writing
  a zero into the high order bytes ($00F8 and $00FA), which is done by the
  CLOSE KERNAL entry. They may also be allocated/de-allocated by the
  machine language programmer for his/her own purposes, removing/creating
  only the buffer(s) required. When using a machine language program that
  allocates these buffers, care must be taken to make sure that the top of
  memory pointers stay correct, especially if BASIC programs are expected
  to run at the same time.
                                                   INPUT/OUTPUT GUIDE   357

  ZERO-PAGE MEMORY LOCATIONS AND USAGE FOR
  RS-232 SYSTEM INTERFACE

    $00A7-INBIT-Receiver input bit temp storage.
    $00A8-BITCI-Receiver bit count in.
    $00A9-RINONE-Receiver flag Start bit check.
    $00AA-RIDATA-Receiver byte buffer/assembly location.
    $00AB-RIPRTY-Receiver parity bit storage.
    $00B4-BITTS-Transmitter bit count out.
    $00B5-NXTBIT-Transmitter next bit to be sent.
    $00B6-RODATA-Transmitter byte buffer/disassembly location.

    All the above zero-page locations are used locally and are only given
  as a guide to understand the associated routines. These cannot be used
  directly by the BASIC or KERNAL level programmer to do RS-232 type
  things. The system RS-232 routines must be used.

  NONZERO-PAGE MEMORY LOCATIONS AND USAGE FOR
  RS-232 SYSTEM INTERFACE

    General RS-232 storage:

    $0293-M51CTR-Pseudo 6551 control register (see Figure 6-1).
    $0294-M51COR-Pseudo 6551 command register (see Figure 6-2) .
    $0295-M51AJB-Two bytes following the control and command registers in
          the file name field. These locations contain the baud rate for
          the start of the bit test during the interface activity, which,
          in turn, is used to calculate baud rate.
    $0297-RSSTAT-The RS-232 status register (see Figure 6-3).
    $0298-BITNUM-The number of bits to be sent/received.
    $0299-BAUDOF-Two bytes that are equal to the time of one bit cell.
          (Based on system clock/baud rate.)

  358   INPUT/OUTPUT GUIDE

    $029B-RIDBE-The byte index to the end of the receiver FIFO buffer.
    $029C-RIDBS-The byte index to the start of the receiver FIFO buffer.
    $029D-RODBS-The byte index to the start of the transmitter FIFO buffer.
    $029E-RODBE-The byte index to the end of the transmitter FIFO buffer.
    $02A1-ENABL-Holds current active interrupts in the CIA #2 ICR.
          When bit 4 is turned on means that the system is waiting for the
          Receiver Edge. When bit 1 is turned on then the system is
          receiving data. When bit 0 is turned on then the system is
          transmitting data.

  THE USER PORT

    The user port is meant to connect the Commodore 64 to the outside
  world. By using the lines available at this port, you can connect the
  Commodore 64 to a printer, a Votrax Type and Talk, a MODEM, even another
  computer.
    The port on the Commodore 64 is directly connected to one of the 6526
  CIA chips. By programming, the CIA will connect to many other devices.

  PORT PIN DESCRIPTION

                                             1 1 1
                           1 2 3 4 5 6 7 8 9 0 1 2
                        +--@-@-@-@-@-@-@-@-@-@-@-@--+
                        |                           |
                        +--@-@-@-@-@-@-@-@-@-@-@-@--+
                           A B C D E F H J K L M N

                                                   INPUT/OUTPUT GUIDE   359

                            PORT PIN DESCRIPTION
  +-----------+-----------+-----------------------------------------------+
  |    PIN    |           |                                               |
  +-----------+DESCRIPTION|                     NOTES                     |
  | TOP SIDE  |           |                                               |
  +-----------+-----------+-----------------------------------------------+
  |     1     |  GROUND   |                                               |
  |     2     |   +5V     |  (100 mA MAX.)                                |
  |     3     |  RESET    |  By grounding this pin, the Commodore 64 will |
  |           |           |  do a COLD START, resetting completely. The   |
  |           |           |  pointers to a BASIC program will be reset,   |
  |           |           |  but memory will not be cleared. This is also |
  |           |           |  a RESET output for the external devices.     |
  |     4     |    CNT1   |  Serial port counter from CIA#1(SEE CIA SPECS)|
  |     5     |    SP1    |  Serial port from CIA #l (SEE 6526 CIA SPECS) |
  |     6     |    CNT2   |  Serial port counter from CIA#2(SEE CIA SPECS)|
  |     7     |    SP2    |  Serial port from CIA #l (SEE 6526 CIA SPECS) |
  |     8     |    PC2    |  Handshaking line from CIA #2 (SEE CIA SPECS) |
  |     9     |SERIAL ATN |  This pin is connected to the ATN line of the |
  |           |           |  serial bus.                                  |
  |    10     |9 VAC+phase|  Connected directly to the Commodore          |
  |    11     |9 VAC-phase|  64 transformer (50 mA MAX.).                 |
  |    12     |    GND    |                                               |
  |           |           |                                               |
  |BOTTOM SIDE|           |                                               |
  |           |           |                                               |
  |     A     |    GND    |  The Commodore 64 gives you control over      |
  |     B     |   FLAG2   |  PORT B on CIA chip #1. Eight lines for input |
  |     C     |    PB0    |  or output are available, as well as 2 lines  |
  |     D     |    PB1    |  for handshaking with an outside device. The  |
  |     E     |    PB2    |  I/O lines for PORT B are controlled by two   |
  |     F     |    PB3    |  locations. One is the PORT itself, and is    |
  |     H     |    PB4    |  located at 56577 ($DD01 HEX). Naturally you  |
  |     I     |    PB5    |  PEEK it to read an INPUT, or POKE it to set  |
  |     K     |    PB6    |  an OUTPUT. Each of the eight I/O lines can   |
  |     L     |    PB7    |  be set up as either an INPUT or an OUTPUT by |
  |     M     |    PA2    |  by setting the DATA DIRECTION REGISTER       |
  |     N     |    GND    |  properly.                                    |
  +-----------+-----------+-----------------------------------------------+

  360   INPUT/OUTPUT GUIDE

    The DATA DIRECTION REGISTER has its location at 56579 ($DD03 hex). Each
  of the eight lines in the PORT has a BIT in the eight-bit DATA DIRECTION
  REGISTER (DDR) which controls whether that line will be an input or an
  output. If a bit in the DDR is a ONE, the corresponding line of the PORT
  will be an OUTPUT. If a bit in the DDR is a ZERO, the corresponding line
  of the PORT will be an INPUT. For example, if bit 3 of the DDR is set to
  1, then line 3 of the PORT will be an output. A further example:
    If the DDR is set like this:

                          BIT #: 7 6 5 4 3 2 1 0
                          VALUE: 0 0 1 1 1 0 0 0

  You can see that lines 5,4, and 3 will be outputs since those bits are
  ones. The rest of the lines will be inputs, since those lines are zeros.
    To PEEK or POKE the USER port, it is necessary to use both the DDR and
  the PORT itself.
    Remember that the PEEK and POKE statements want a number from 0-255.
  The numbers given in the example must be translated into decimal before
  they can be used. The value would be:

                     2^5 + 2^4 + 2^3 = 32 + 16 + 8 = 56

  Notice that the bit # for the DDR is the same number that = 2 raised to
  a power to turn the bit value on.

                      (16 = 2^4=2*2*2*2, 8 = 2^3=2*2*2)

    The two other lines, FLAG1 and PA2 are different from the rest of the
  USER PORT. These two lines are mainly for HANDSHAKING, and are programmed
  differently from port B.
    Handshaking is needed when two devices communicate. Since one device
  may run at a different speed than another device it is necessary to give
  the devices some way of knowing what the other device is doing. Even when
  the devices are operating at the same speed, handshaking is necessary to
  let the other know when data is to be sent, and if it has been received.
  The FLAG1 line has special characteristics which make it well suited for
  handshaking.
    FLAG1 is a negative edge sensitive input which can be used as a general
  purpose interrupt input. Any negative transition on the FLAG line will
  set the FLAG interrupt bit. If the FLAG interrupt is enabled, this will

                                                   INPUT/OUTPUT GUIDE   361

  cause an INTERRUPT REQUEST. If the FLAG bit is not enabled, it can be
  polled from the interrupt register under program control.
    PA2 is bit 2 of PORT A of the CIA. It is controlled like any other bit
  in the port. The port is located at 56576 ($DD00). The data direction
  register is located at 56578 ($DD02.)
    FOR MORE INFORMATION ON THE 6526 SEE THE CHIP SPECIFICATIONS IN
  APPENDIX M.

  THE SERIAL BUS

    The serial bus is a daisy chain arrangement designed to let the Com-
  modore 64 communicate with devices such as the VIC-1541 DISK DRIVE and
  the VIC-1525 GRAPHICS PRINTER. The advantage of the serial bus is that
  more than one device can be connected to the port. Up to 5 devices can be
  connected to the serial bus at one time.
    There are three types of operation over a serial bus-CONTROL, TALK, and
  LISTEN. A CONTROLLER device is one which controls operation of the serial
  bus. A TALKER transmits data onto the bus. A LISTENER receives data from
  the bus.
    The Commodore 64 is the controller of the bus. It also acts as a TALKER
  (when sending data to the printer, for example) and as a LISTENER (when
  loading a program from the disk drive, for example). Other devices may be
  either LISTENERS (the printer), TALKERS, or both (the disk drive). Only
  the Commodore 64 can act as the controller.
    All devices connected on the serial bus will receive all the data
  transmitted over the bus. To allow the Commodore 64 to route data to its
  intended destination, each device has a bus ADDRESS. By using this device
  address, the Commodore 64 can control access to the bus. Addresses on the
  serial bus range from 4 to 31.
    The Commodore 64 can COMMAND a particular device to TALK or LISTEN.
  When the Commodore 64 commands a device to TALK, the device will begin
  putting data onto the serial bus. When the Commodore 64 commands a device
  to LISTEN, the device addressed will get ready to receive data (from the
  Commodore 64 or from another device on the bus). Only one device can TALK
  on the bus at a time; otherwise, the data will collide and the system
  will crash in confusion. However, any number of devices can LISTEN at the
  same time to one TALKER.

  362   INPUT/OUTPUT GUIDE

                         COMMON SERIAL BUS ADDRESSES
                    +--------+--------------------------+
                    | NUMBER |        DEVICE            |
                    +--------+--------------------------+
                    | 4 or 5 | VIC-1525 GRAPHIC PRINTER |
                    | 8      | VIC-1541 DISK DRIVE      |
                    +--------+--------------------------+

    Other device addresses are possible. Each device has its own address.
  Certain devices (like the Commodore 64 printer) provide a choice between
  two addresses for the convenience of the user.
    The SECONDARY ADDRESS is to let the Commodore 64 transmit setup
  information to a device. For example, to OPEN a connection on the bus to
  the printer, and have it print in UPPER/LOWER case, use the following

    OPEN 1,4,7

  where,
    1 is the logical file number (the number you PRINT# to),
    4 is the ADDRESS of the printer, and
    7 is the SECONDARY ADDRESS that tells the printer to go into UPPER/
      LOWER case mode.

    There are 6 lines used in serial bus operations - input and 3 output.
  The 3 input lines bring data, control, and timing signals into the Com-
  modore 64. The 3 output lines send data, control, and timing signals from
  the Commodore 64 to external devices on the serial bus.

  Serial I/O
                                                       ++ ++
  +-------+----------------------+                    / +-+ \
  |  Pin  |         Type         |                   /5     1\
  +-------+----------------------+                  +  O   O  +
  |   1   |  /SERIAL SRQ IN      |                  |    6    |
  |   2   |  GND                 |                  |    O    |
  |   3   |  SERIAL ATN OUT      |                  |         |
  |   4   |  SERIAL CLK IN/OUT   |                  +  O   O  +
  |   5   |  SERIAL DATA IN/OUT  |                   \4  O  2/
  |   6   |  /RESET              |                    \  3  /
  +-------+----------------------+                     +---+

                                                   INPUT/OUTPUT GUIDE   363

  SERIAL SRQ IN: (SERIAL SERVICE REQUEST IN)

    Any device on the serial bus can bring this signal LOW when it requires
  attention from the Commodore 64. The Commodore 64 will then take care of
  the device. (See Figure 6-4).

                          [THE PICTURE IS MISSING!]

                        Figure 6-4. Serial Bus Timing.

  364   INPUT/OUTPUT GUIDE

  SERIAL ATN OUT: (SERIAL ATTENTION OUT)

    The Commodore 64 uses this signal to start a command sequence for a
  device on the serial bus. When the Commodore 64 brings this signal LOW,
  all other devices on the bus start listening for the Commodore 64 to
  transmit an address. The device addressed must respond in a preset period
  of time; otherwise, the Commodore 64 will assume that the device
  addressed is not on the bus, and will return an error in the STATUS WORD.
  (See Figure 6-4).

                          [THE PICTURE IS MISSING!]

                              SERIAL BUS TIMING
  +-----------------------------+-------+-------+-------+-----------------+
  |     Description             | Symbol|  Min. |  Typ. |       Max.      |
  +-----------------------------+-------+-------+-------+-----------------+
  | ATN RESPONSE (REQUIRED) (1) |  Tat  |   -   |   -   |     1000us      |
  | LISTENER HOLD-OFF           |  Th   |   0   |   -   |    infinite     |
  | NON-EOI RESPONSE TO RFD (2) |  Tne  |   -   |  40us |      200us      |
  | BIT SET-UP TALKER (4)       |  Ts   |  20us |  70us |        -        |
  | DATA VALID                  |  Tv   |  20us |  20us |        -        |
  | FRAME HANDSHAKE (3)         |  Tf   |   0   |  20   |     1000us      |
  | FRAME TO RELEASE OF ATN     |  Tr   |  20us |   -   |        -        |
  | BETWEEN BYTES TIME          |  Tbb  | 100us |   -   |        -        |
  | EOI RESPONSE TIME           |  Tye  | 200us | 250us |        -        |
  | EOI RESPONSE HOLD TIME (5)  |  Tei  |  60us |   -   |        -        |
  | TALKER RESPONSE LIMIT       |  Try  |   0   |  30us |       60us      |
  | BYTE-ACKNOWLEDGE (4)        |  Tpr  |  20us |  30us |        -        |
  | TALK-ATTENTION RELEASE      |  Ttk  |  20us |  30us |      100us      |
  | TALK-ATTENTION ACKNOWLEDGE  |  Tdc  |   0   |   -   |        -        |
  | TALK-ATTENTION ACK. HOLD    |  Tda  |  80us |   -   |        -        |
  | EOI ACKNOWLEDGE             |  Tfr  |  60us |   -   |        -        |
  +-----------------------------+-------+-------+-------+-----------------+
     Notes:
     1. If maximum time exceeded, device not present error.
     2. If maximum time exceeded, EOI response required.
     3. If maximum time exceeded, frame error.
     4. Tv and Tpr minimum must be 60us for external device to be a talker.
     5. Tei minimum must be 80us for external device to be a listener.

                                                   INPUT/OUTPUT GUIDE   365

  SERIAL CLK IN/OUT: (SERIAL CLOCK IN/OUT)

    This signal is used for timing the data sent on the serial bus. (See
  Figure 6-4).

  SERIAL DATA IN/OUT:

    Data on the serial bus is transmitted one bit at a time on this line.
  (See Figure 6-4.)

  THE EXPANSION PORT

    The expansion connector is a 44-pin (22122) female edge connector on
  the back of the Commodore 64. With the Commodore 64 facing you, the
  expansion connector is on the far right of the back of the computer. To
  use the connector, a 44-pin (22/22) male edge connector is required.
    This port is used for expansions of the Commodore 64 system which
  require access to the address bus or the data bus of the computer.
  Caution is necessary when using the expansion bus, because it's possible
  to damage the Commodore 64 by a malfunction of your equipment.
    The expansion bus is arranged as follows:
                 2 2 2 1 1 1 1 1 1 1 1 1 1
                 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1
             +---@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@---+
             |                                                 |
             +---@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@---+
                 Z Y X W V U T S R P N M L K J H F E D C B A

    The signals available on the connector are as follows:
  +---------+---+---------------------------------------------------------+
  |   NAME  |PIN|                       DESCRIPTION                       |
  +---------+---+---------------------------------------------------------+
  |   GND   | 1 |  System ground                                          |
  |  +5VDC  | 2 |  (Total USER PORT and CARTRIDGE devices can             |
  |  +5VDC  | 3 |  draw no more than 450 mA.)                             |
  |  /IRQ   | 4 |  Interrupt Request line to 6502 (active low)            |
  |   R/W   | 5 |  Read/Write (write active low)                          |
  |DOT CLOCK| 6 |  8.18 MHz video dot clock                               |
  |  /I/O1  | 7 |  I/O block 1 @ $ DE00-$DEFF (active low) unbuffered I/O |
  |  /GAME  | 8 |  active low ls ttl input                                |
  |  /EXROM | 9 |  active low ls ttl input                                |
  |  /I/O2  |10 |  I/O block 2 @ $DF00-$DFFF (active low) buff'ed ls ttl  |
                                                                  output  |
  366   INPUT/OUTPUT GUIDE

  +---------+---+---------------------------------------------------------+
  |   NAME  |PIN|                       DESCRIPTION                       |
  +---------+---+---------------------------------------------------------+
  |  /ROML  |11 |  8K decoded RAM/ROM block @ $8000 (active low) buffered |
  |         |   |  ls ttl output                                          |
  |   BA    |12 |  Bus available signal from the VIC-II chip unbuffered   |
  |         |   |    1 Is load max.                                       |
  |  /DMA   |13 |  Direct memory access request line (active low input)   |
  |         |   |  ls ttl input                                           |
  |   D7    |14 |  Data bus bit 7 \                                       |
  |   D6    |15 |  Data bus bit 6  +                                      |
  |   D5    |16 |  Data bus bit 5  |                                      |
  |   D4    |17 |  Data bus bit 4  +-  unbuffered, 1 ls ttl load max      |
  |   D3    |18 |  Data bus bit 3  +-                                     |
  |   D2    |19 |  Data bus bit 2  |                                      |
  |   D1    |20 |  Data bus bit 1  +                                      |
  |   D0    |21 |  Data bus bit 0 /                                       |
  |   GND   |22 |  System ground                                          |
  |   GND   | A |                                                         |
  |  /ROMH  | B |  8K decoded RAM/ROM block @ $E000 buffered              |
  |  /RESET | C |  6502 RESET pin(active low) buff'ed ttl out/unbuff'ed in|
  |  /NMI   | D |  6502 Non Maskable Interrupt (active low) buff'ed ttl   |
  |         |   |  out, unbuff'ed in                                      |
  |   02    | E |  Phase 2 system clock                                   |
  |   A15   | F |  Address bus bit 15 \                                   |
  |   A14   | H |  Address bus bit 14  +                                  |
  |   A13   | J |  Address bus bit 13  |                                  |
  |   A12   | K |  Address bus bit 12  |                                  |
  |   A11   | L |  Address bus bit 11  |                                  |
  |   A10   | M |  Address bus bit 10  |                                  |
  |   A9    | N |  Address bus bit 9   |                                  |
  |   A8    | P |  Address bus bit 8   +--  unbuffered, 1 ls ttl load max |
  |   A7    | R |  Address bus bit 7   +--                                |
  |   A6    | S |  Address bus bit 6   |                                  |
  |   A5    | T |  Address bus bit 5   |                                  |
  |   A4    | U |  Address bus bit 4   |                                  |
  |   A3    | V |  Address bus bit 3   |                                  |
  |   A2    | W |  Address bus bit 2   |                                  |
  |   A1    | X |  Address bus bit 1   +                                  |
  |   A0    | Y |  Address bus bit 0  /                                   |
  |   GND   | Z |  System ground                                          |
  +---------+---+---------------------------------------------------------+

                                                   INPUT/OUTPUT GUIDE   367

    Following is a description of some important fines on the expansion
  port:

    Pins 1,22,A,Z are connected to the system ground.
    Pin 6 is the DOT CLOCK. This is the 8.18-MHz video dot clock. All
  system timing is derived from this clock.
    Pin 12 is the BA (BUS AVAILABLE) signal from the VIC-II chip. This line
  will go low 3 cycles before the VIC-II takes over the system busses, and
  remains low until the VIC-II is finished fetching display information.
    Pin 13 is the DMA (DIRECT MEMORY ACCESS) line. When this line is pulled
  low, the address bus, the data bus, and the Read/Write line of the 6510
  processor chip enter high-impedance state mode. This allows an external
  processor to take control of the system busses. This line should only be
  pulled low when the (02 clock is low. Also, since the VIC-II chip will
  continue to perform display DMA, the external device must conform to the
  VIC-II timing. (See VIC-II timing diagram.) This line is pulled up on the
  Commodore 64.

  Z-80 MICROPROCESSOR CARTRIDGE

    Reading this book and using your computer has shown you just how
  versatile your Commodore 64 really is. But what makes this machine even
  more capable of meeting your needs is the addition of peripheral
  equipment. Peripherals are things like Datassette(TM) recorders, disk
  drives, printers, and modems. All these items can be added to your
  Commodore 64 through the various ports and sockets on the back of your
  machine. The thing that makes Commodore peripherals so good is the fact
  that our peripherals are "intelligent." That means that they don't take
  up valuable Random Access Memory space when they're in use. You're free
  to use all 64K of memory in your Commodore 64.
    Another advantage of your Commodore 64 is the fact most programs you
  write on your Commodore 64 today will be upwardly compatible with any new
  Commodore computer you buy in the future. This is partially because of
  the qualities of the computer's Operating System (OS).
    However, there is one thing that the Commodore OS can't do: make your
  programs compatible with a computer made by another company.

  368   INPUT/OUTPUT GUIDE

    Most of the time you won't even have to think about using another com-
  pany's computer, because your Commodore 64 is so easy to use. But for the
  occasional user who wants to take advantage of software that may not be
  available in Commodore 64 format we have created a Commodore CP/M(R)
  cartridge.
    CP/M(R) is not a "computer dependent" operating system. Instead it uses
  some of the memory space normally available for programming to run its
  own operating system. There are advantages and disadvantages to this. The
  disadvantages are that the programs you write will have to be shorter
  than the programs you can write using the Commodore 64's built-in
  operating system. In addition, you can NOT use the Commodore 64's
  powerful screen editing capabilities. The advantages are that you can now
  use a large amount of software that has been specifically designed for
  CP/M(R) and the Z-80 microprocessor, and the programs that you write
  using the CP/M(R) operating system can be transported and run on any
  other computer that has CP/M(R) and a Z-80 card.
    By the way, most computers that have a Z-80 microprocessor require that
  you go inside the computer to actually install a Z-80 card. With this
  method you have to be very careful not to disturb the delicate circuitry
  that runs the rest of the computer. The Commodore CP/M& cartridge
  eliminates this hassle because our Z-80 cartridge plugs into the back of
  your Commodore 64 quickly and easily, without any messy wires that can
  cause problems later.

  USING COMMODORE CP/M(R)

    The Commodore Z-80 cartridge let's you run programs designed for a Z-80
  microprocessor on your Commodore 64. The cartridge is provided with a
  diskette containing the Commodore CP/M(R) operating system.

  RUNNING COMMODORE CP/M(R)

    To run CP/M(R):

      1) LOAD the CP/M(R) program from your disk drive.
      2) Type RUN.
      3) Hit the <RETURN> key.

                                                   INPUT/OUTPUT GUIDE   369

    At this point the 64K bytes of RAM in the Commodore 64 are accessible
  by the built-in 6510 central processor, OR 48K bytes of RAM are available
  for the Z-80 central processor. You can shift back and forth between
  these two processors, but you can NOT use them at the same time in a
  single program. This is possible because of your Commodore 64's
  sophisticated timing mechanism.
    Below is the memory address translation that is performed on the Z-80
  cartridge. You should notice that by adding 4096 bytes to the memory
  locations used in CP/M(R) $1000 (hex) you equal the memory addresses of
  the normal Commodore 64 operating system. The correspondence between Z-80
  and 6510 memory addresses is as follows:

  +-----------------------------------+-----------------------------------+
  |          Z-80 ADDRESSES           |           6510 ADDRESSES          |
  +-----------------+-----------------+-----------------+-----------------+
  |     DECIMAL     |       HEX       |     DECIMAL     |       HEX       |
  +-----------------+-----------------+-----------------+-----------------+
  |    0000-4095    |    0000-0FFF    |    4096-8191    |    1000-1FFF    |
  |    4096-8191    |    1000-1FFF    |    8192-12287   |    2000-2FFF    |
  |    8192-12287   |    2000-2FFF    |   12288-16383   |    3000-3FFF    |
  |   12288-16383   |    3000-3FFF    |   16384-20479   |    4000-4FFF    |
  |   16384-20479   |    4000-4FFF    |   20480-24575   |    5000-5FFF    |
  |   20480-24575   |    5000-5FFF    |   24576-28671   |    6000-6FFF    |
  |   24576-28671   |    6000-6FFF    |   28672-32767   |    7000-7FFF    |
  |   28672-32767   |    7000-7FFF    |   32768-36863   |    8000-SFFF    |
  |   32768-36863   |    8000-8FFF    |   36864-40959   |    9000-9FFF    |
  |   36864-40959   |    9000-9FFF    |   40960-45055   |    A000-AFFF    |
  |   40960-45055   |    A000-AFFF    |   45056-49151   |    B000-BFFF    |
  |   45056-49151   |    B000-BFFF    |   49152-53247   |    C000-CFFF    |
  |   49152-53247   |    C000-CFFF    |   53248-57343   |    D000-DFFF    |
  |   53248-57343   |    D000-DFFF    |   57344-61439   |    E000-EFFF    |
  |   57344-61439   |    E000-EFFF    |   61440-65535   |    F000-FFFF    |
  |   61440-65535   |    F000-FFFF    |    0000-4095    |    0000-0FFF    |
  +-----------------+-----------------+-----------------+-----------------+

  370   INPUT/OUTPUT GUIDE

    To TURN ON the Z-80 and TURN OFF the 6510 chip, type in the following
  program:

start tok64 page371.prg
  10 rem this program is to be used with the z80 card
  20 rem it first stores z80 data at $1000 (Z80=$0000)
  30 rem then it turns off the 6510 irq's and enables
  40 rem the z80 card. the z80 card must be turned off
  50 rem to reenable the 6510 system.
  100 rem store z80 data
  110 read b: rem get size of z80 code to be moved
  120 for i=4096 to 4096+b-1:rem move code
  130 read a:poke i,a
  140 next i
  200 rem run z80 code
  210 poke 56333,127: rem turn of 6510 irq's
  220 poke 56832,00 : rem turn on z80 card
  230 poke 56333,129: rem turn on 6510 irq's when z80 done
  240 end
  1000 rem z80 machine language code data section
  1010 data 18 : rem size of data to be passed
  1100 rem z80 turn on code
  1110 data 00,00,00 : rem our z80 card requires turn on time at $0000
  1200 rem z80 task data here
  1210 data 33,02,245: rem ld hl,nn (location on screen)
  1220 data 52 : rem inc hl (increment that location)
  1300 rem z80 self-turn off data here
  1310 data 62,01 : rem ld a,n
  1320 data 50,00,206 : rem ld (nn),a :i/o location
  1330 data 00,00,00  : rem nop, nop, nop
  1340 data 195,00,00 : rem jmp $0000
stop tok64

    For more details about Commodore CP/M(R) and the Z-80 microprocessor
  look for the cartridge and the Z-80 Reference Guide at your local
  Commodore computer dealer.

                                                   INPUT/OUTPUT GUIDE   371

                                                APPENDICES

                                     373

  APPENDIX A

  ABBREVIATIONS FOR BASIC KEYWORDS

    As a time-saver when typing in programs and commands, Commodore 64
  BASIC allows the user to abbreviate most keywords. The abbreviation for
  PRINT is a question mark. The abbreviations for other words are made by
  typing the first one or two letters of the word, followed by the SHIFTed
  next letter of the word. If the abbreviations are used in a program line,
  the keyword will LIST in the full form.
                          Looks like  |                        Looks like
  Command Abbreviation this on screen | Command Abbreviation this on screen
  ------------------------------------+------------------------------------
   ABS     A <SHIFT+B>                | END     E <SHIFT+N>
                                      |
   AND     A <SHIFT+N>                | EXP     E <SHIFT+X>
                                      |
   ASC     A <SHIFT+S>                | FN      NONE               FN
                                      |
   ATN     A <SHIFT+T>                | FOR     F <SHIFT+O>
                                      |
   CHR$    C <SHIFT+H>                | FRE     F <SHIFT+R>
                                      |
   CLOSE   CL <SHIFT+O>               | GET     G <SHIFT+E>
                                      |
   CLR     C <SHIFT+L>                | GET#    NONE               GET#
                                      |
   CMD     C <SHIFT+M>                | GOSUB   GO <SHIFT+S>
                                      |
   CONT    C <SHIFT+O>                | GOTO    G <SHIFT+O>
                                      |
   COS     NONE               COS     | IF      NONE               IF
                                      |
   DATA    D <SHIFT+A>                | INPUT   NONE               INPUT
                                      |
   DEF     D <SHIFT+E>                | INPUT#  I <SHIFT+N>
                                      |
   DIM     D <SHIFT+I>                | INT     NONE               INT
                                      |
   LEFT$   LE <SHIFT+F>               | RIGHT$  R <SHIFT+I>
                                      |
   LEN     NONE               LEN     | RND     R <SHIFT+N>

  374   APPENDIX A

                          Looks like  |                        Looks like
  Command Abbreviation this on screen | Command Abbreviation this on screen
  ------------------------------------+------------------------------------
   LET     L <SHIFT+E>                | RUN     R <SHIFT+U>
                                      |
   LIST    L <SHIFT+I>        SAVE    | SAVE    S <SHIFT+A>
                                      |
   LOAD    L <SHIFT+O>                | SGN     S <SHIFT+G>
                                      |
   LOG     NONE               LOG     | SIN     S <SHIFT+I>
                                      |
   MID$    M <SHIFT+I>                | SPC(    S <SHIFT+P>
                                      |
   NEW     NONE               NEW     | SQR     S <SHIFT+Q>
                                      |
   NEXT    N <SHIFT+E>                | STATUS  ST                 ST
                                      |
   NOT     N <SHIFT+O>                | STEP    ST <SHIFT+E>
                                      |
   ON      NONE               ON      | STOP    S <SHIFT+T>
                                      |
   OPEN    O <SHIFT+P>                | STR$    ST <SHIFT+R>
                                      |
   OR      NONE               OR      | SYS     S <SHIFT+Y>
                                      |
   PEEK    P <SHIFT+E>                | TAB(    T <SHIFT+A>
                                      |
   POKE    P <SHIFT+O>                | TAN     NONE               TAN
                                      |
   POS     NONE               POS     | THEN    T <SHIFT+H>
                                      |
   PRINT   ?                  ?       | TIME    TI                 TI
                                      |
   PRINT#  P <SHIFT+R>                | TIME$   TI$                TI$
                                      |
   READ    R <SHIFT+E>                | USR     U <SHIFT+S>
                                      |
   REM     NONE               REM     | VAL     V <SHIFT+A>
                                      |
   RESTORE RE <SHIFT+S>               | VERIFY  V <SHIFT+E>
                                      |
   RETURN  RE <SHIFT+T>               | WAIT    W <SHIFT+A>

                                                           APPENDIX A   375

  APPENDIX B

  SCREEN DISPLAY CODES

    The following chart lists all of the characters built into the
  Commodore 64 character sets. It shows which numbers should be POKED into
  screen memory (locations 1024-2023) to get a desired character. Also
  shown is which character corresponds to a number PEEKed from the screen.
    Two character sets are available, but only one set at a time. This
  means that you cannot have characters from one set on the screen at the
  same time you have characters from the other set displayed. The sets are
  switched by holding down the <SHIFT> and <C=> keys simultaneously.
    From BASIC, POKE 53272,21 will switch to upper case mode and
  POKE 53272,23 switches to lower case.
    Any number on the chart may also be displayed in REVERSE. The reverse
  character code may be obtained by adding 128 to the values shown.
    If you want to display a solid circle at location 1504, POKE the code
  for the circle (81) into location 1504: POKE 1504,81.
    There is a corresponding memory location to control the color of each
  character displayed on the screen (locations 55296-56295). To change the
  color of the circle to yellow (color code 7) you would POKE the corre-
  sponding memory location (55776) with the character color: POKE 55776,7.
    Refer to Appendix D for the complete screen and color memory maps,
  along with color codes.

  +-----------------------------------------------------------------------+
  | NOTE: The following POKEs display the same symbol in set 1 and 2: 1,  |
  | 27-64, 91-93, 96-104, 106-121, 123-127.                               |
  +-----------------------------------------------------------------------+

  SCREEN CODES

    SET 1   SET 2   POKE  |  SET 1   SET 2   POKE  |  SET 1   SET 2   POKE
  ------------------------+------------------------+-----------------------
                          |                        |
      @               0   |    C       c       3   |    F       f       6
      A       a       1   |    D       d       4   |    G       g       7
      B       b       2   |    E       e       5   |    H       h       8

  376   APPENDIX B

    SET 1   SET 2   POKE  |  SET 1   SET 2   POKE  |  SET 1   SET 2   POKE
  ------------------------+------------------------+-----------------------
                          |                        |
      I       i       9   |    %              37   |            A      65
      J       j      10   |    &              38   |            B      66
      K       k      11   |    '              39   |            C      67
      L       l      12   |    (              40   |            D      68
      M       m      13   |    )              41   |            E      69
      N       n      14   |    *              42   |            F      70
      O       o      15   |    +              43   |            G      71
      P       p      16   |    ,              44   |            H      72
      Q       q      17   |    -              45   |            I      73
      R       r      18   |    .              46   |            J      74
      S       s      19   |    /              47   |            K      75
      T       t      20   |    0              48   |            L      76
      U       u      21   |    1              49   |            M      77
      V       v      22   |    2              50   |            N      78
      W       w      23   |    3              51   |            O      79
      X       x      24   |    4              52   |            P      80
      Y       y      25   |    5              53   |            Q      81
      Z       z      26   |    6              54   |            R      82
      [              27   |    7              55   |            S      83
    pound            28   |    8              56   |            T      84
      ]              29   |    9              57   |            U      85
      ^              30   |    :              58   |            V      86
      <-             31   |    ;              59   |            W      87
    SPACE            32   |    <              60   |            X      88
      !              33   |    =              61   |            Y      89
      "              34   |    >              62   |            Z      90
      #              35   |    ?              63   |                   91
      $              36   |                   64   |                   92

                                                           APPENDIX B   377

    SET 1   SET 2   POKE  |  SET 1   SET 2   POKE  |  SET 1   SET 2   POKE
  ------------------------+------------------------+-----------------------
                          |                        |
                     93   |                  105   |                  117
                     94   |                  106   |                  118
                     95   |                  107   |                  119
    SPACE            96   |                  108   |                  120
                     97   |                  109   |                  121
                     98   |                  110   |                  122
                     99   |                  111   |                  123
                    100   |                  112   |                  124
                    101   |                  113   |                  125
                    102   |                  114   |                  126
                    103   |                  115   |                  127
                    104   |                  116   |

            Codes from 128-255 are reversed images of codes 0-127.

  378   APPENDIX B

  APPENDIX C

  ASCII AND CHR$ CODES

    This appendix shows you what characters will appear if you PRINT
  CHR$(X), for all possible values of X. It will also show the values ob-
  tained by typing PRINT ASC("x"), where x is any character you can type.
  This is useful in evaluating the character received in a GET statement,
  converting upper/lower case, and printing character based commands (like
  switch to upper/lower case) that could not be enclosed in quotes.

  +-----------------+-----------------+-----------------+-----------------+
  |  PRINTS   CHR$  |  PRINTS   CHR$  |  PRINTS   CHR$  |  PRINTS   CHR$  |
  +-----------------+-----------------+-----------------+-----------------+
  |             0   |  {down}    17   |    "       34   |    3       51   |
  |             1   | {rvs on}   18   |    #       35   |    4       52   |
  |             2   |  {home}    19   |    $       36   |    5       53   |
  |             3   |  {del}     20   |    %       37   |    6       54   |
  |             4   |            21   |    &       38   |    7       55   |
  | {white}     5   |            22   |    '       39   |    8       56   |
  |             6   |            23   |    (       40   |    9       57   |
  |             7   |            24   |    )       41   |    :       58   |
  | disSHIFT+C= 8   |            25   |    *       42   |    ;       59   |
  | enaSHIFT+C= 9   |            26   |    +       43   |    <       60   |
  |            10   |            27   |    ,       44   |    =       61   |
  |            11   |  {red}     28   |    -       45   |    >       62   |
  |            12   | {right}    29   |    .       46   |    ?       63   |
  | return     13   | {green}    30   |    /       47   |    @       64   |
  | lower case 14   |  {blue}    31   |    0       48   |    A       65   |
  |            15   |  SPACE     32   |    1       49   |    B       66   |
  |            16   |    !       33   |    2       50   |    C       67   |

                                                           APPENDIX C   379

  +-----------------+-----------------+-----------------+-----------------+
  |  PRINTS   CHR$  |  PRINTS   CHR$  |  PRINTS   CHR$  |  PRINTS   CHR$  |
  +-----------------+-----------------+-----------------+-----------------+
  |    D       68   |            97   |           126   | {grey 3}  155   |
  |    E       69   |            98   |           127   | {purple}  156   |
  |    F       70   |            99   |           128   | {left}    157   |
  |    G       71   |           100   | {orange}  129   | {yellow}  158   |
  |    H       72   |           101   |           130   |  {cyan}   159   |
  |    I       73   |           102   |           131   |  SPACE    160   |
  |    J       74   |           103   |           132   |           161   |
  |    K       75   |           104   |    f1     133   |           162   |
  |    L       76   |           105   |    f3     134   |           163   |
  |    M       77   |           106   |    f5     135   |           164   |
  |    N       78   |           107   |    f7     136   |           165   |
  |    O       79   |           108   |    f2     137   |           166   |
  |    P       80   |           109   |    f4     138   |           167   |
  |    Q       81   |           110   |    f6     139   |           168   |
  |    R       82   |           111   |    f8     140   |           169   |
  |    S       83   |           112   |shift+ret. 141   |           170   |
  |    T       84   |           113   |upper case 142   |           171   |
  |    U       85   |           114   |           143   |           172   |
  |    V       86   |           115   | {black}   144   |           173   |
  |    W       87   |           116   |   {up}    145   |           174   |
  |    X       88   |           117   | {rvs off} 146   |           175   |
  |    Y       89   |           118   | {clear}   147   |           176   |
  |    Z       90   |           119   |  {inst}   148   |           177   |
  |    [       91   |           120   | {brown}   149   |           178   |
  |  pound     92   |           121   | {lt. red} 150   |           179   |
  |    ]       93   |           122   | {grey 1}  151   |           180   |
  |    ^       94   |           123   | {grey 2}  152   |           181   |
  |{arrow left}95   |           124   | {lt.green}153   |           182   |
  |            96   |           125   | {lt.blue} 154   |           183   |

  380   APPENDIX C

  +-----------------+-----------------+-----------------+-----------------+
  |  PRINTS   CHR$  |  PRINTS   CHR$  |  PRINTS   CHR$  |  PRINTS   CHR$  |
  +-----------------+-----------------+-----------------+-----------------+
  |           184   |           186   |           188   |           190   |
  |           185   |           187   |           189   |           191   |
  +-----------------+-----------------+-----------------+-----------------+

  CODES 192-223 SAME AS  96-127
  CODES 224-254 SAME AS 160-190
  CODE 255 SAME AS 126

                                                           APPENDIX C   381

  APPENDIX D

  SCREEN AND COLOR MEMORY MAPS

    The following charts list which memory locations control placing char-
  acters on the screen, and the locations used to change individual char-
  acter colors, as well as showing character color codes.

                             SCREEN MEMORY MAP

                                   COLUMN                             1063
        0             10             20             30            39 /
       +------------------------------------------------------------/
  1024 |                                                            |  0
  1064 |                                                            |
  1104 |                                                            |
  1144 |                                                            |
  1184 |                                                            |
  1224 |                                                            |
  1264 |                                                            |
  1304 |                                                            |
  1344 |                                                            |
  1384 |                                                            |
  1424 |                                                            | 10
  1464 |                                                            |
  1504 |                                                            |   ROW
  1544 |                                                            |
  1584 |                                                            |
  1624 |                                                            |
  1664 |                                                            |
  1704 |                                                            |
  1744 |                                                            |
  1784 |                                                            |
  1824 |                                                            | 20
  1864 |                                                            |
  1904 |                                                            |
  1944 |                                                            |
  1984 |                                                            | 24
       +------------------------------------------------------------\
                                                                     \
                                                                      2023

  382   APPENDIX D

    The actual values to POKE into a color memory location to change a
  character's color are:

             0  BLACK   4  PURPLE     8  ORANGE     12  GRAY 2
             1  WHITE   5  GREEN      9  BROWN      13  Light GREEN
             2  RED     6  BLUE      10  Light RED  14  Light BLUE
             3  CYAN    7  YELLOW    11  GRAY 1     15  GRAY 3

    For example, to change the color of a character located at the upper
  left-hand corner of the screen to red, type: POKE 55296,2.

                              COLOR MEMORY MAP
                                   COLUMN                             55335
        0             10             20             30            39 /
       +------------------------------------------------------------/
  55296|                                                            |  0
  55336|                                                            |
  55376|                                                            |
  55416|                                                            |
  55456|                                                            |
  55496|                                                            |
  55536|                                                            |
  55576|                                                            |
  55616|                                                            |
  55656|                                                            |
  55696|                                                            | 10
  55736|                                                            |
  55776|                                                            |   ROW
  55816|                                                            |
  55856|                                                            |
  55896|                                                            |
  55936|                                                            |
  55976|                                                            |
  56016|                                                            |
  56056|                                                            |
  56096|                                                            | 20
  56136|                                                            |
  56176|                                                            |
  56216|                                                            |
  56256|                                                            | 24
       +------------------------------------------------------------\
                                                                     56295

                                                           APPENDIX D   383

  APPENDIX E

  MUSIC NOTE VALUES

    This appendix contains a complete list of Note#, actual note, and the
  values to be POKED into the HI FREQ and LOW FREQ registers of the sound
  chip to produce the indicated note.

  +-----------------------------+-----------------------------------------+
  |        MUSICAL NOTE         |             OSCILLATOR FREQ             |
  +-------------+---------------+-------------+-------------+-------------+
  |     NOTE    |    OCTAVE     |   DECIMAL   |      HI     |     LOW     |
  +-------------+---------------+-------------+-------------+-------------+
  |       0     |      C-0      |     268     |       1     |      12     |
  |       1     |      C#-0     |     284     |       1     |      28     |
  |       2     |      D-0      |     301     |       1     |      45     |
  |       3     |      D#-0     |     318     |       1     |      62     |
  |       4     |      E-0      |     337     |       1     |      81     |
  |       5     |      F-0      |     358     |       1     |     102     |
  |       6     |      F#-0     |     379     |       1     |     123     |
  |       7     |      G-0      |     401     |       1     |     145     |
  |       8     |      G#-0     |     425     |       1     |     169     |
  |       9     |      A-0      |     451     |       1     |     195     |
  |      10     |      A#-0     |     477     |       1     |     221     |
  |      11     |      B-0      |     506     |       1     |     250     |
  |      16     |      C-1      |     536     |       2     |      24     |
  |      17     |      C#-1     |     568     |       2     |      56     |
  |      18     |      D-1      |     602     |       2     |      90     |
  |      19     |      D#-1     |     637     |       2     |     125     |
  |      20     |      E-1      |     675     |       2     |     163     |
  |      21     |      F-1      |     716     |       2     |     204     |
  |      22     |      F#-1     |     758     |       2     |     246     |
  |      23     |      G-1      |     803     |       3     |      35     |
  |      24     |      G#-1     |     851     |       3     |      83     |
  |      25     |      A-1      |     902     |       3     |     134     |
  |      26     |      A#-1     |     955     |       3     |     187     |
  |      27     |      B-1      |    1012     |       3     |     244     |
  |      32     |      C-2      |    1072     |       4     |      48     |

  384   APPENDIX E

  +-----------------------------+-----------------------------------------+
  |        MUSICAL NOTE         |             OSCILLATOR FREQ             |
  +-------------+---------------+-------------+-------------+-------------+
  |     NOTE    |    OCTAVE     |   DECIMAL   |      HI     |     LOW     |
  +-------------+---------------+-------------+-------------+-------------+
  |      33     |      C#-2     |     1136    |       4     |     112     |
  |      34     |      D-2      |     1204    |       4     |     180     |
  |      35     |      D#-2     |     1275    |       4     |     251     |
  |      36     |      E-2      |     1351    |       5     |      71     |
  |      37     |      F-2      |     1432    |       5     |     152     |
  |      38     |      F#-2     |     1517    |       5     |     237     |
  |      39     |      G-2      |     1607    |       6     |      71     |
  |      40     |      G#-2     |     1703    |       6     |     167     |
  |      41     |      A-2      |     1804    |       7     |      12     |
  |      42     |      A#-2     |     1911    |       7     |     119     |
  |      43     |      B-2      |     2025    |       7     |     233     |
  |      48     |      C-3      |     2145    |       8     |      97     |
  |      49     |      C#-3     |     2273    |       8     |     225     |
  |      50     |      D-3      |     2408    |       9     |     104     |
  |      51     |      D#-3     |     2551    |       9     |     247     |
  |      52     |      E-3      |     2703    |      10     |     143     |
  |      53     |      F-3      |     2864    |      11     |      48     |
  |      54     |      F#-3     |     3034    |      11     |     218     |
  |      55     |      G-3      |     3215    |      12     |     143     |
  |      56     |      G#-3     |     3406    |      13     |      78     |
  |      57     |      A-3      |     3608    |      14     |      24     |
  |      58     |      A#-3     |     3823    |      14     |     239     |
  |      59     |      B-3      |     4050    |      15     |     210     |
  |      64     |      C-4      |     4291    |      16     |     195     |
  |      65     |      C#-4     |     4547    |      17     |     195     |
  |      66     |      D-4      |     4817    |      18     |     209     |
  |      67     |      D#-4     |     5103    |      19     |     239     |
  |      68     |      E-4      |     5407    |      21     |      31     |
  |      69     |      F-4      |     5728    |      22     |      96     |
  |      70     |      F#-4     |     6069    |      23     |     181     |
  |      71     |      G-4      |     6430    |      25     |      30     |
  |      72     |      G#-4     |     6812    |      26     |     156     |
  |      73     |      A-4      |     7217    |      28     |      49     |
  |      74     |      A#-4     |     7647    |      29     |     223     |
  |      75     |      B-4      |     8101    |      31     |     165     |
  |      80     |      C-5      |     8583    |      33     |     135     |
  |      81     |      C#-5     |     9094    |      35     |     134     |

                                                           APPENDIX E   385

  +-----------------------------+-----------------------------------------+
  |        MUSICAL NOTE         |             OSCILLATOR FREQ             |
  +-------------+---------------+-------------+-------------+-------------+
  |     NOTE    |    OCTAVE     |   DECIMAL   |      HI     |     LOW     |
  +-------------+---------------+-------------+-------------+-------------+
  |      82     |      D-5      |     9634    |      37     |     162     |
  |      83     |      D#-5     |    10207    |      39     |     223     |
  |      84     |      E-5      |    10814    |      42     |      62     |
  |      85     |      F-5      |    11457    |      44     |     193     |
  |      86     |      F#-5     |    12139    |      47     |     107     |
  |      87     |      G-5      |    12860    |      50     |      60     |
  |      88     |      G#-5     |    13625    |      53     |      57     |
  |      89     |      A-5      |    14435    |      56     |      99     |
  |      90     |      A#-5     |    15294    |      59     |     190     |
  |      91     |      B-5      |    16203    |      63     |      75     |
  |      96     |      C-6      |    17167    |      67     |      15     |
  |      97     |      C#-6     |    18188    |      71     |      12     |
  |      98     |      D-6      |    19269    |      75     |      69     |
  |      99     |      D#-6     |    20415    |      79     |     191     |
  |     100     |      E-6      |    21629    |      84     |     125     |
  |     101     |      F-6      |    22915    |      89     |     131     |
  |     102     |      F#-6     |    24278    |      94     |     214     |
  |     103     |      G-6      |    25721    |     100     |     121     |
  |     104     |      G#-6     |    27251    |     106     |     115     |
  |     105     |      A-6      |    28871    |     112     |     199     |
  |     106     |      A#-6     |    30588    |     119     |     124     |
  |     107     |      B-6      |    32407    |     126     |     151     |
  |     112     |      C-7      |    34334    |     134     |      30     |
  |     113     |      C#-7     |    36376    |     142     |      24     |
  |     114     |      D-7      |    38539    |     150     |     139     |
  |     115     |      D#-7     |    40830    |     159     |     126     |
  |     116     |      E-7      |    43258    |     168     |     250     |
  |     117     |      F-7      |    45830    |     179     |       6     |
  |     118     |      F#-7     |    48556    |     189     |     172     |
  |     119     |      G-7      |    51443    |     200     |     243     |
  |     120     |      G#-7     |    54502    |     212     |     230     |
  |     121     |      A-7      |    57743    |     225     |     143     |
  |     122     |      A#-7     |    61176    |     238     |     248     |
  |     123     |      B-7      |    64814    |     253     |      46     |
  +-------------+---------------+-------------+-------------+-------------+

  386   APPENDIX E

                              FILTER SETTINGS
               +------------+--------------------------------+
               |  Location  |            Contents            |
               +------------+--------------------------------+
               |    54293   |  Low cutoff frequency (0-7)    |
               |    54294   |  High cutoff frequency (0-255) |
               |    54295   |  Resonance (bits 4-7)          |
               |            |  Filter voice 3 (bit 2)        |
               |            |  Filter voice 2 (bit 1)        |
               |            |  Filter voice 1 (bit 0)        |
               |    54296   |  High pass (bit 6)             |
               |            |  Bandpass (bit 5)              |
               |            |  Low pass (bit 4)              |
               |            |  Volume (bits 0-3)             |
               +------------+--------------------------------+

                                                           APPENDIX E   387

  APPENDIX F

  BIBLIOGRAPHY

  Addison-Wesley          "BASIC and the Personal Computer", Dwyer and
                          Critchfield

  Compute                 "Compute's First Book of PET/CBM"

  Cowbay Computing        "Feed Me, I'm Your PET Computer", Carol Alexander

                          "Looking Good with Your PET", Carol Alexander

                          "Teacher's PET-Plans, Quizzes, and Answers"

  Creative Computing      "Getting Acquainted With Your VIC 20",
                          T. Hartnell

  Dilithium Press         "BASIC Basic-English Dictionary for the PET",
                          Lorry Noonan

                          "PET BASIC", Tom Rugg and Phil Feldman

  Faulk Baker Associates  "MOS Programming Manual", MOS Technology

  Hoyden Book Co.         "BASIC From the Ground Up", David E. Simon

                          "I Speak BASIC to My PET", Aubrey Jones, Jr.

                          "Library of PET Subroutines',', Nick Hampshire

                          "PET Graphics", Nick Hampshire

                          "BASIC Conversions Handbook, Apple, TRS-80, and
                          PET", David A. Brain, Phillip R. Oviatt,
                          Paul J. Paquin, and Chandler P. Stone

  388   APPENDIX F

  Howard W. Sams          "The Howard W. Sams Crash Course in Mi-
                          crocomputers", Louis E. Frenzel, Jr.

                          "Mostly BASIC: Applications for Your PET",
                          Howard Berenbon

                          "PET Interfacing", James M. Downey and Steven
                          M. Rogers

                          "VIC 20 Programmer's Reference Guide", A. Finkel,
                          P. Higginbottom, N. Harris, and M. Tomczyk

  Little, Brown & Co.     "Computer Games for Businesses, Schools, and
                          Homes", J. Victor Nagigian, and William S. Hodges

                          "The Computer Tutor: Learning Activities for
                          Homes and Schools", Gary W. Orwig, University of
                          Central Florida, and William S. Hodges

  McGraw-Hill             "Hands-On BASIC With a PET", Herbert D. Peckman

                          "Home and Office Use of VisiCalc", D. Castlewitz,
                          and L. Chisauki

  Osborne/McGraw-Hill     "PET/CBM Personal Computer Guide", Carroll
                          S. Donahue

                          "PET Fun and Games", R. Jeffries and G. Fisher

                          "PET and the IEEE", A. Osborne and C. Donahue

                          "Some Common BASIC Programs for the PET",
                          L. Poole, M. Borchers, and C. Donahue

                          "Osborne CP/M User Guide", Thorn Hogan

                          "CBM Professional Computer Guide"

                          "The PET Personal Guide"

                          "The 8086 Book", Russell Rector and George Alexy

                                                           APPENDIX F   389

  P. C. Publications      "Beginning Self-Teaching Computer Lessons"

  Prentice-Hall           "The PET Personal Computer for Beginners",
                          S. Dunn and V. Morgan

  Reston Publishing Co.   "PET and the IEEE 488 Bus (GPIB)", Eugene
                          Fisher and C. W. Jensen

                          "PET BASIC-Training Your PET Computer",
                          Roman Zamora, Wm. F. Carrie, and B. Allbrecht

                          "PET Games and Recreation", M. Ogelsby, L.
                          Lindsey, and D. Kunkin

                          "PET BASIC", Richard Huskell

                          "VIC Games and Recreation"

  Telmas Courseware       "BASIC and the Personal Computer", T. A. Dwyer,
  Ratings                 and M. Critchfield

  Total Information Ser-  "Understanding Your PET/CBM, Vol. 1, BASIC
  vices                   Programming"

                          "Understanding Your VIC", David Schultz

    Commodore Magazines provide you with the most up-to-date information
  for your Commodore 64. Two of the most popular publications that you
  should seriously consider subscribing to are:

    COMMODORE-The Microcomputer Magazine is published bimonthly and is
  available by subscription ($15.00 per year, U.S., and $25.00 per year,
  worldwide).

    POWER/PLAY-The Home Computer Magazine is, published quarterly and is
  available by subscription ($10.00 per year, U.S,, and $15.00 per year
  worldwide).

  390   APPENDIX F

  APPENDIX G

  VIC CHIP REGISTER MAP

  53248 ($D000) Starting (Base) Address
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  |Register#|     |     |     |     |     |     |     |     |             |
  | Dec Hex | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 |             |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  |  0   0  | S0X7|     |     |     |     |     |     | S0X0| SPRITE 0 X  |
  |         |     |     |     |     |     |     |     |     |  Component  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  |  1   1  | S0Y7|     |     |     |     |     |     | S0Y0| SPRITE 0 Y  |
  |         |     |     |     |     |     |     |     |     |  Component  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  |  2   2  | S1X7|     |     |     |     |     |     | S1X0| SPRITE 1 X  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  |  3   3  | S1Y7|     |     |     |     |     |     | S1Y0| SPRITE 1 Y  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  |  4   4  | S2X7|     |     |     |     |     |     | S2X0| SPRITE 2 X  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  |  5   5  | S2Y7|     |     |     |     |     |     | S2Y0| SPRITE 2 Y  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  |  6   6  | S3X7|     |     |     |     |     |     | S3X0| SPRITE 3 X  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  |  7   7  | S3Y7|     |     |     |     |     |     | S3Y0| SPRITE 3 Y  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  |  8   8  | S4X7|     |     |     |     |     |     | S4X0| SPRITE 4 X  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  |  9   9  | S4Y7|     |     |     |     |     |     | S4Y0| SPRITE 4 Y  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 10   A  | S5X7|     |     |     |     |     |     | S5X0| SPRITE 5 X  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 11   B  | S5Y7|     |     |     |     |     |     | S5Y0| SPRITE 5 Y  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 12   C  | S6X7|     |     |     |     |     |     | S6X0| SPRITE 6 X  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 13   D  | S6Y7|     |     |     |     |     |     | S6Y0| SPRITE 6 Y  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 14   E  | S7X7|     |     |     |     |     |     | S7X0| SPRITE 7 X  |
  |         |     |     |     |     |     |     |     |     |  Component  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+

                                                           APPENDIX G   391

  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  |Register#|     |     |     |     |     |     |     |     |             |
  | Dec Hex | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 |             |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 15   F  | S7Y7|     |     |     |     |     |     | S7Y0| SPRITE 7 Y  |
  |         |     |     |     |     |     |     |     |     |  Component  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 16  10  | S7X8| S6X8| S5X8| S4X8| S3X8| S2X8| S1X8| S0X8|  MSB of X   |
  |         |     |     |     |     |     |     |     |     |   COORD.    |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 17  11  | RC8 | ECM | BMM | BLNK| RSEL|YSCL2|YSCL1|YSCL0|  Y SCROLL   |
  |         |     |     |     |     |     |     |     |     |  MODE       |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 18  12  | RC7 | RC6 | RC5 | RC4 | RC3 | RC2 | RC1 | RC0 |   RASTER    |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 19  13  | LPX7|     |     |     |     |     |     | LPX0| LIGHT PEN X |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 20  14  | LPY7|     |     |     |     |     |     |     | LIGHT PEN Y |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 21  15  | SE7 |     |     |     |     |     |     | SE0 |SPRITE ENABLE|
  |         |     |     |     |     |     |     |     |     |  (ON/OFF)   |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 22  16  | N.C.| N.C.| RST | MCM | CSEL|XSCL2|XSCL1|XSCL0|  X SCROLL   |
  |         |     |     |     |     |     |     |     |     |  MODE       |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 23  17  |SEXY7|     |     |     |     |     |     |SEXY0|   SPRITE    |
  |         |     |     |     |     |     |     |     |     |  EXPAND Y   |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 24  18  | VS13| VS12| VS11| VS10| CB13| CB12| CB11| N.C.| SCREEN and  |
  |         |     |     |     |     |     |     |     |     |  Character  |
  |         |     |     |     |     |     |     |     |     | Memory Base |
  |         |     |     |     |     |     |     |     |     |  Address    |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 25  19  | IRQ | N.C.| N.C.| N.C.|LPIRQ| ISSC| ISBC| RIRQ|  Interrupt  |
  |         |     |     |     |     |     |     |     |     |  Request's  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 26  1A  | N.C.| N.C.| N.C.| N.C.| MLPI|MISSC|MISBC|MRIRQ|  IRQ MASKS  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 27  1B  | BSP7|     |     |     |     |     |     | BSP0| Background- |
  |         |     |     |     |     |     |     |     |     | Sprite      |
  |         |     |     |     |     |     |     |     |     | PRIORITY    |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+

  392   APPENDIX G

  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  |Register#|     |     |     |     |     |     |     |     |             |
  | Dec Hex | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 |             |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 28  1C  | SCM7|     |     |     |     |     |     | SCM0| MULTICOLOR  |
  |         |     |     |     |     |     |     |     |     |SPRITE SELECT|
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 29  1D  |SEXX7|     |     |     |     |     |     |SEXX0|   SPRITE    |
  |         |     |     |     |     |     |     |     |     |  EXPAND X   |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 30  1E  | SSC7|     |     |     |     |     |     | SSC0|Sprite-Sprite|
  |         |     |     |     |     |     |     |     |     |  COLLISION  |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+
  | 31  1F  | SBC7|     |     |     |     |     |     | SBC0| Sprite-     |
  |         |     |     |     |     |     |     |     |     | Background  |
  |         |     |     |     |     |     |     |     |     | COLLISION   |
  +---------+-----+-----+-----+-----+-----+-----+-----+-----+-------------+

  +---------+-----------------------+   +---------+-----------------------+
  |Register#|                       |   |Register#|                       |
  | Dec Hex |         Color         |   | Dec Hex |         Color         |
  | 32  20  |  BORDER COLOR         |   | 39  27  |  SPRITE 0 COLOR       |
  | 33  21  |  BACKGROUND COLOR 0   |   | 40  28  |  SPRITE 1 COLOR       |
  | 34  22  |  BACKGROUND COLOR 1   |   | 41  29  |  SPRITE 2 COLOR       |
  | 35  23  |  BACKGROUND COLOR 2   |   | 42  2A  |  SPRITE 3 COLOR       |
  | 36  24  |  BACKGROUND COLOR 3   |   | 43  2B  |  SPRITE 4 COLOR       |
  | 37  25  |  SPRITE MULTICOLOR 0  |   | 44  2C  |  SPRITE 5 COLOR       |
  | 38  26  |  SPRITE MULTICOLOR 1  |   | 45  2D  |  SPRITE 6 COLOR       |
  +---------+-----------------------+   | 46  2E  |  SPRITE 7 COLOR       |
  COLOR CODES                           +---------+-----------------------+
  +---------+-----------+  +---------+-----------+
  | Dec Hex |   Color   |  | Dec Hex |   Color   |
  |  0   0  |  BLACK    |  |  8   8  |  ORANGE   |
  |  1   1  |  WHITE    |  |  9   9  |  BROWN    |
  |  2   2  |  RED      |  | 10   A  |  LT RED   |
  |  3   3  |  CYAN     |  | 11   B  |  GRAY 1   |
  |  4   4  |  PURPLE   |  | 12   C  |  GRAY 2   |
  |  5   5  |  GREEN    |  | 13   D  |  LT GREEN |
  |  6   6  |  BLUE     |  | 14   E  |  LT BLUE  |
  |  7   7  |  YELLOW   |  | 15   F  |  GRAY 3   |
  +---------+-----------+  +---------+-----------+
  LEGEND: ONLY COLORS 0-7 MAY BE USED IN MULTICOLOR CHARACTER MODE

                                                           APPENDIX G   393

  APPENDIX H

  DERIVING MATHEMATICAL FUNCTIONS

    Functions that are not intrinsic to Commodore 64 BASIC may be calcu-
  lated as follows:

  +------------------------------+----------------------------------------+
  |           FUNCTION           |            BASIC EQUIVALENT            |
  +------------------------------+----------------------------------------+
  |  SECANT                      |  SEC(X)=1/COS(X)                       |
  |  COSECANT                    |  CSC(X)=1/SIN(X)                       |
  |  COTANGENT                   |  COT(X)=1/TAN(X)                       |
  |  INVERSE SINE                |  ARCSIN(X)=ATN(X/SQR(-X*X+1))          |
  |  INVERSE COSINE              |  ARCCOS(X)=-ATN(X/SQR(-X*X+1))+{pi}/2  |
  |  INVERSE SECANT              |  ARCSEC(X)=ATN(X/SQR(X*X-1))           |
  |  INVERSE COSECANT            |  ARCCSC(X)=ATN(X/SQR(X*X-1))           |
  |                              |    +(SGN(X)-1*{pi}/2                   |
  |  INVERSE COTANGENT           |  ARCOT(X)=ATN(X)+{pi}/2                |
  |  HYPERBOLIC SINE             |  SINH(X)=(EXP(X)-EXP(-X))/2            |
  |  HYPERBOLIC COSINE           |  COSH(X)=(EXP(X)+EXP(-X))/2            |
  |  HYPERBOLIC TANGENT          |  TANH(X)=EXP(-X)/(EXP(X)+EXP(-X))*2+1  |
  |  HYPERBOLIC SECANT           |  SECH(X)=2/(EXP(X)+EXP(-X))            |
  |  HYPERBOLIC COSECANT         |  CSCH(X)=2/(EXP(X)-EXP(-X))            |
  |  HYPERBOLIC  COTANGENT       |  COTH(X)=EXP(-X)/(EXP(X)-EXP(-X))*2+1  |
  |  INVERSE HYPERBOLIC SINE     |  ARCSINH(X)=LOG(X+SQR(X*X+1))          |
  |  INVERSE HYPERBOLIC COSINE   |  ARCCOSH(X)=LOG(X+SQR(X*X-1))          |
  |  INVERSE HYPERBOLIC TANGENT  |  ARCTANH(X)=LOG((1+X)/(1-X))/2         |
  |  INVERSE HYPERBOLIC SECANT   |  ARCSECH(X)=LOG((SQR(-X*X+1)+1/X)      |
  |  INVERSE HYPERBOLIC COSECANT |  ARCCSCH(X)=LOG((SGN(X)*SQR(X*X+1/X)   |
  |  INVERSE HYPERBOLIC COTANGENT|  ARCCOTH(X)=LOG((X+1)/(X-1))/2         |
  +------------------------------+----------------------------------------+

  394   APPENDIX H

  APPENDIX I

  PINOUTS FOR INPUT/OUTPUT DEVICES

    This appendix is designed to show you what connections may be made to
  the Commodore 64.

          1) Game I/O             4) Serial I/O (Disk/Printer)
          2) Cartridge Slot       5) Modulator Output
          3) Audio/Video          6) Cassette
                                  7) User Port

  Control Port 1
  +-----+-------------+-----------+
  | Pin |    Type     |   Note    |            1 2 3 4 5
  |  1  |    JOYA0    |           |            O O O O O
  |  2  |    JOYA1    |           |
  |  3  |    JOYA2    |           |             O O O O
  |  4  |    JOYA3    |           |             6 7 8 9
  |  5  |    POT AY   |           |
  |  6  | BUTTON A/LP |           |
  |  7  |     +5V     | MAX. 50mA |
  |  8  |     GND     |           |
  |  9  |   POT AX    |           |
  +-----+-------------+-----------+

  Control Port 2
  +-----+-------------+-----------+
  | Pin |    Type     |   Note    |
  |  1  |    JOYB0    |           |
  |  2  |    JOYB1    |           |
  |  3  |    JOYB2    |           |
  |  4  |    JOYB3    |           |
  |  5  |    POT BY   |           |
  |  6  |  BUTTON B   |           |
  |  7  |     +5V     | MAX. 50mA |
  |  8  |     GND     |           |
  |  9  |   POT BX    |           |
  +-----+-------------+-----------+

                                                           APPENDIX I   395

  Cartridge Expansion Slot
    Pin    Type       Pin    Type       Pin    Type       Pin    Type
  +----+----------+ +----+----------+ +----+----------+ +----+----------+
  |  1 | GND      | | 12 | BA       | |  A | GND      | |  N | A9       |
  |  2 | +5V      | | 13 | /DMA     | |  B | /ROMH    | |  P | A8       |
  |  3 | +5V      | | 14 | D7       | |  C | /RESET   | |  R | A7       |
  |  4 | /IRQ     | | 15 | D6       | |  D | /NMI     | |  S | A6       |
  |  5 | R/W      | | 16 | D5       | |  E | 02       | |  T | A5       |
  |  6 | Dot Clock| | 17 | D4       | |  F | A15      | |  U | A4       |
  |  7 | I/O1     | | 18 | D3       | |  H | A14      | |  V | A3       |
  |  8 | /GAME    | | 19 | D2       | |  J | A13      | |  W | A2       |
  |  9 | /EXROM   | | 20 | D1       | |  K | A12      | |  X | A1       |
  | 10 | I/O2     | | 21 | D0       | |  L | A11      | |  Y | A0       |
  | 11 | /ROML    | | 22 | GND      | |  M | A10      | |  Z | GND      |
  +----+----------+ +----+----------+ +----+----------+ +----+----------+
                 2 2 2 1 1 1 1 1 1 1 1 1 1
                 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1
             +---@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@---+
             |                                                 |
             +---@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@---+
                 Z Y X W V U T S R P N M L K J H F E D C B A

  Audio/Video                        Serial I/O
     Pin            Type                Pin            Type
  +-------+----------------------+   +-------+----------------------+
  |   1   |  LUMINANCE           |   |   1   |  /SERIAL SRQ IN      |
  |   2   |  GND                 |   |   2   |  GND                 |
  |   3   |  AUDIO OUT           |   |   3   |  SERIAL ATN OUT      |
  |   4   |  VIDEO OUT           |   |   4   |  SERIAL CLK IN/OUT   |
  |   5   |  AUDIO IN            |   |   5   |  SERIAL DATA IN/OUT  |
  |   6   |  CHROMINANCE         |   |   6   |  /RESET              |
  +-------+----------------------+   +-------+----------------------+
                ++ ++                             ++ ++
               / +-+ \                           / +-+ \
              /       \                         /5     1\
             +         +                       +  O   O  +
             |    6    |                       |    6    |
             |3O  O  O1|                       |    O    |
             |         |                       |         |
             +  O   O  +                       +  O   O  +
              \5  O  4/                         \4  O  2/
               \  2  /                           \  3  /
                +---+                             +---+
  396   APPENDIX I

  Cassette

  +-------+--------------------+
  |  Pin  |        Type        |
  +-------+--------------------+
  |  A-1  |  GND               |              1 2 3 4 5 6
  |  B-2  |  +5V               |          +---@-@-@-@-@-@---+
  |  C-3  |  CASSETTE MOTOR    |          |                 |
  |  D-4  |  CASSETTE READ     |          +---@-@-@-@-@-@---+
  |  E-5  |  CASSETTE WRITE    |              A B C D E F
  |  F-6  |  CASSETTE SENSE    |
  +-------+--------------------+

  User I/O

  +-----+---------------+-----------+   +-----+---------------+-----------+
  | Pin |      Type     |    Note   |   | Pin |      Type     |    Note   |
  +-----+---------------+-----------+   +-----+---------------+-----------+
  |   1 |  GND          |           |   |  A  |  GND          |           |
  |   2 |  +5V          |MAX. 100 mA|   |  B  |  /FLAG2       |           |
  |   3 |  /RESET       |           |   |  C  |  PB0          |           |
  |   4 |  CNT1         |           |   |  D  |  PB1          |           |
  |   5 |  SP1          |           |   |  E  |  PB2          |           |
  |   6 |  CNT2         |           |   |  F  |  PB3          |           |
  |   7 |  SP2          |           |   |  H  |  PB4          |           |
  |   8 |  /PC2         |           |   |  I  |  PB5          |           |
  |   9 |  SER. ATN OUT |           |   |  K  |  PB6          |           |
  |  10 |  9 VAC        |MAX. 100 mA|   |  L  |  PB7          |           |
  |  11 |  9 VAC        |MAX. 100 mA|   |  M  |  PA2          |           |
  |  12 |  GND          |           |   |  N  |  GND          |           |
  +-----+---------------+-----------+   +-----+---------------+-----------+

                                             1 1 1
                           1 2 3 4 5 6 7 8 9 0 1 2
                        +--@-@-@-@-@-@-@-@-@-@-@-@--+
                        |                           |
                        +--@-@-@-@-@-@-@-@-@-@-@-@--+
                           A B C D E F H J K L M N

                                                           APPENDIX I   397

  APPENDIX J

  CONVERTING STANDARD
  BASIC PROGRAMS TO
  COMMODORE 64 BASIC

    If you have programs written in a BASIC other than Commodore BASIC,
  some minor adjustments may be necessary before running them on the
  Commodore-64. We've included some hints to make the conversion easier.

  String Dimensions

    Delete all statements that are used to declare the length of strings.
  A statement such as DIM A$(I,J), which dimensions a string array for J
  elements of length I, should be converted to the Commodore BASIC
  statement DIM A$(J).
    Some BASICs use a comma or an ampersand for string concatenation. Each
  of these must be changed to a plus sign, which is the Commodore BASIC
  operator for string concatenation.
    In Commodore-64 BASIC, the MID$, RIGHT$, and LEFT$ functions are used
  to take substrings of strings. Forms such as A$(I) to access the Ith
  character in A$, or A$(I,J) to take a substring of A$ from position I to
  J, must be changed as follows:

  Other BASIC     Commodore 64 BASIC

  A$(I)=X$        A$=LEFT$(A$,I-1)+X$+MID$(A$,I+1)
  A$(I,J)=X$      A$=LEFT$(A$,I-1)+X$+MID$(A$,J+1)

  Multiple Assignments

    To set B and C equal to zero, some BASICs allow statements of the form:

  10 LET B=C=0

  398   APPENDIX J

    Commodore 64 BASIC would interpret the second equal sign as a logical
  operator and set B = -1 if C = 0. Instead, convert this statement to:

  10 C=0:B=0

  Multiple Statements

    Some BASICs use a backslash to separate multiple statements on a line.
  With Commodore 64 BASIC, separate all statements by a colon (:).

  MAT Functions

    Programs using the MAT functions available on some BASICs must be
  rewritten using FOR...NEXT loops to execute properly.

                                                           APPENDIX J   399

  APPENDIX K

  ERROR MESSAGES

    This appendix contains a complete list of the error messages generated
  by the Commodore-64, with a description of causes.

  BAD DATA            String data was received from an open file, but the
                      program was expecting numeric data.
  BAD SUBSCRIPT       The program was trying to reference an element of an
                      array whose number is outside of the range specified
                      in the DIM statement.
  BREAK               Program execution was stopped because you hit the
                      <STOP> key.
  CAN'T CONTINUE      The CONT command will not work, either because the
                      program was never RUN, there has been an error, or
                      a line has been edited.
  DEVICE NOT PRESENT  The required I/O device was not available for an
                      OPEN, CLOSE, CMD, PRINT#, INPUT#, or GET#.
  DIVISION BY ZERO    Division by zero is a mathematical oddity and not
                      allowed.
  EXTRA IGNORED       Too many items of data were typed in response to an
                      INPUT statement. Only the first few items were
                      accepted.
  FILE NOT FOUND      If you were looking for a file on tape, and END-OF-
                      TAPE marker was found. If you were looking on disk,
                      no file with that name exists.
  FILE NOT OPEN       The file specified in a CLOSE, CMD, PRINT#, INPUT#,
                      or GET#, must first be OPENed.
  FILE OPEN           An attempt was made to open a file using the number
                      of an already open file.
  FORMULA TOO COMPLEX The string expression being evaluated should be split
                      into at least two parts for the system to work with,
                      or a formula has too many parentheses.
  ILLEGAL DIRECT      The INPUT statement can only be used within a pro-
                      gram, and not in direct mode.
  ILLEGAL QUANTITY    A number used as the argument of a function or
                      statement is out of the allowable range.

  400   APPENDIX K

  LOAD                There is a problem with the program on tape.
  NEXT WITHOUT FOR    This is caused by either incorrectly nesting loops or
                      having a variable name in a NEXT statement that
                      doesn't correspond with one in a FOR statement.
  NOT INPUT FILE      An attempt was made to INPUT or GET data from a file
                      which was specified to be for output only.
  NOT OUTPUT FILE     An attempt was mode to PRINT data to a file which was
                      specified as input only.
  OUT OF DATA         A READ statement was executed but there is no data
                      left unREAD in a DATA statement.
  OUT OF MEMORY       There is no more RAM available for program or
                      variables. This may also occur when too many FOR
                      loops have been nested, or when there are too many
                      GOSUBs in effect.
  OVERFLOW            The result of a computation is larger than the
                      largest number allowed, which is 1.70141884E+38.
  REDIM'D ARRAY       An array may only be DiMensioned once. If an array
                      variable is used before that array is DIM'D, an
                      automatic DIM operation is performed on that array
                      setting the number of elements to ten, and any
                      subsequent DIMs will cause this error.
  REDO FROM START     Character data was typed in during an INPUT statement
                      when numeric data was expected. Just re-type the
                      entry so that it is correct, and the program will
                      continue by itself.
  RETURN WITHOUT GOSUB  A RETURN statement was encountered, and no GOSUB
                      command has been issued.
  STRING TOO LONG     A string can contain up to 255 characters.
  ?SYNTAX ERROR       A statement is unrecognizable by the Commodore 64. A
                      missing or extra parenthesis, misspelled keywords,
                      etc.
  TYPE MISMATCH       This error occurs when a number is used in place of a
                      string, or vice-versa.
  UNDEF'D FUNCTION    A user defined function was referenced, but it has
                      never been defined using the DEF FN statement.
  UNDEF'D STATEMENT   An attempt was made to GOTO or GOSUB or RUN a line
                      number that doesn't exist.
  VERIFY              The program on tape or disk does not match the
                      program currently in memory.

                                                           APPENDIX K   401

  APPENDIX L

  6510 MICROPROCESSOR CHIP
  SPECIFICATIONS

  DESCRIPTION

    The 6510 is a low-cost microcomputer system capable of solving a broad
  range of small-systems and peripheral-control problems at minimum cost to
  the user.
    An 8-bit Bi-Directional I/O Port is located on-chip with the Output
  Register at Address 0000 and the Data-Direction Register at Address 0001.
  The I/O Port is bit-by-bit programmable.
    The Three-State sixteen-bit Address Bus allows Direct Memory Accessing
  (DMA) and multiprocessor systems sharing a common memory.
    The internal processor architecture is identical to the MOS Technology
  6502 to provide software compatibility.

  FEATURES OF THE 6510...

  o Eight-Bit Bi-Directional I/O Port
  o Single +5-volt supply
  o N-channel, silicon gate, depletion load technology
  o Eight-bit parallel processing
  o 56 Instructions
  o Decimal and binary arithmetic
  o Thirteen addressing modes
  o True indexing capability
  o Programmable stack pointer
  o Variable length stack
  o Interrupt capability
  o Eight-Bit Bi-Directional Data Bus
  o Addressable memory range of up to 64K bytes
  o Direct memory access capability
  o Bus compatible with M6800
  o Pipeline architecture
  o 1-MHz and 2-MHz operation
  o Use with any type or speed memory

  402  APPENDIX L

                              PIN CONFIGURATION

                                +----+ +----+
                     01 IN   1 @|    +-+    |@ 40  /RES
                                |           |
                       RDY   2 @|           |@ 39  02 IN
                                |           |
                      /IRQ   3 @|           |@ 38  R/W
                                |           |
                      /NMI   4 @|           |@ 37  D0
                                |           |
                       AEC   5 @|           |@ 36  D1
                                |           |
                       VCC   6 @|           |@ 35  D2
                                |           |
                        A0   7 @|           |@ 34  D3
                                |           |
                        A1   8 @|           |@ 33  D4
                                |           |
                        A2   9 @|           |@ 32  D5
                                |           |
                        A3  10 @|           |@ 31  D6
                                |    6510   |
                        A4  11 @|           |@ 30  D7
                                |           |
                        A5  12 @|           |@ 29  P0
                                |           |
                        A6  13 @|           |@ 28  P1
                                |           |
                        A7  14 @|           |@ 27  P2
                                |           |
                        A8  15 @|           |@ 26  P3
                                |           |
                        A9  16 @|           |@ 25  P4
                                |           |
                       A10  17 @|           |@ 24  P5
                                |           |
                       A11  18 @|           |@ 23  A15
                                |           |
                       A12  19 @|           |@ 22  A14
                                |           |
                       A13  20 @|           |@ 21  GND
                                +-----------+
                                                           APPENDIX L   403

                         [THE PICTURE IS MISSING!]

                             6510 BLOCK DIAGRAM

  404   APPENDIX L

  6510 CHARACTERISTICS

  MAXIMUM RATINGS
  +--------------------------+------------+-----------------+-------------+
  |          RATING          |   SYMBOL   |      VALUE      |    UNIT     |
  +--------------------------+------------+-----------------+-------------+
  |  SUPPLY VOLTAGE          |    Vcc     |   -0.3 to +7.0  |     VDC     |
  |  INPUT VOLTAGE           |    Vin     |   -0.3 to +7.0  |     VDC     |
  |  OPERATING TEMPERATURE   |    Ta      |    0 to +70     |   Celsius   |
  |  STORAGE TEMPERATURE     |    Tstg    |   -55 to +150   |   Celsius   |
  +--------------------------+------------+-----------------+-------------+
  +-----------------------------------------------------------------------+
  | NOTE: This device contains input protection against damage due to high|
  | static voltages or electric fields; however, precautions should be    |
  | taken to avoid application of voltages higher than the maximum rating.|
  +-----------------------------------------------------------------------+

  ELECTRICAL CHARACTERISTICS  (VCC=5.0V +-5%, VSS=0, Ta=0 to +70 Celsius)
  +------------------------------------+--------+-------+---+-------+-----+
  |           CHARACTERISTIC           | SYMBOL |  MIN. |TYP|  MAX. |UNIT |
  +------------------------------------+--------+-------+---+-------+-----+
  | Input High Voltage                 |        |       |   |       |     |
  |   01, 02(in)                       |  Vih   |Vcc-0.2| - |Vcc+1.0| VDC |
  | Input High Voltage                 |        |       |   |       |     |
  | /RES, P0-P7, /IRQ, Data            |        |Vss+2.0| - |   -   | VDC |
  +------------------------------------+--------+-------+---+-------+-----+
  | Input Low Voltage                  |        |       |   |       |     |
  | 01,02(in)                          |  Vil   |Vss-0.3| - |Vss+0.2| VDC |
  | /RES, P0-P7, /IRQ, Data            |        |   -   | - |Vss+0.8| VDC |
  +------------------------------------+--------+-------+---+-------+-----+
  | Input Leakage Current              |        |       |   |       |     |
  |   (Vin=0 to 5.25V, Vcc=5.25V       |        |       |   |       |     |
  |   Logic                            |  Iin   |   -   | - |  2.5  |  uA |
  |   01, 02(in)                       |        |   -   | - |  100  |  uA |
  +------------------------------------+--------+-------+---+-------+-----+
  | Three State(Off State)Input Current|        |       |   |       |     |
  | (Vin=0.4 to 2.4V, Vcc=5.25V)       |        |       |   |       |     |
  |   Data Lines                       |  Itsi  |   -   | - |   10  |  uA |
  +------------------------------------+--------+-------+---+-------+-----+
  | Output High Voltage                |        |       |   |       |     |
  | (Ioh=-100uADC, Vcc=4.75V)          |        |       |   |       |     |
  |   Data, A0-A15, R/W, P0-P7         |  Voh   |Vss+2.4| - |   -   | VDC |
  +------------------------------------+--------+-------+---+-------+-----+
                                                           APPENDIX L   405

  +------------------------------------+--------+-------+---+-------+-----+
  |           CHARACTERISTIC           | SYMBOL |  MIN. |TYP|  MAX. |UNIT |
  +------------------------------------+--------+-------+---+-------+-----+
  | Out Low Voltage                    |        |       |   |       |     |
  | (Iol=1.6mADC, Vcc=4.75V)           |        |       |   |       |     |
  |   Data, A0-A15, R/W, P0-P7         |   Vol  |   -   | - |Vss+0.4| VDC |
  +------------------------------------+--------+-------+---+-------+-----+
  | Power Supply Current               |   Icc  |   -   |125|       |  mA |
  +------------------------------------+--------+-------+---+-------+-----+
  | Capacitance                        |   C    |       |   |       |  pF |
  | Vin=0, Ta=25 Celsius, f=1MHz)      |        |       |   |       |     |
  |   Logic, P0-P7                     |   Cin  |   -   | - |   10  |     |
  |   Data                             |        |   -   | - |   15  |     |
  |   A0-A15, R/W                      |   Cout |   -   | - |   12  |     |
  |   01                               |   C01  |   -   | 30|   50  |     |
  |   02                               |   C02  |   -   | 50|   80  |     |
  +------------------------------------+--------+-------+---+-------+-----+

                               CLOCK TIMING

                          [THE PICTURE IS MISSING!]

               TIMING FOR READING DATA FROM MEMORY OR PERIPHERALS

  406   APPENDIX L

                                CLOCK TIMING

                         [THE PICTURE IS MISSING!]

               TIMING FOR WRITING DATA TO MEMORY OR PERIPHERALS

                                                           APPENDIX L   407

  AC CHARACTERISTICS

  ELECTRICAL CHARACTERISTICS (Vcc=5V +-5%, Vss=0V, Ta=0-70 Celsius)

        CLOCK TIMING                        1 MHz TIMING 2 MHz TIMING
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | CHARACTERISTIC                  |SYMBOL|MIN.|TYP|MAX|MIN|TYP|MAX|UNITS|
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Cycle Time                      | Tcyc |1000| - | - |500| - | - | ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Clock Pulse Width 01            |PWH01 | 430| - | - |215| - | - | ns  |
  | (Measured at Vcc-0.2V) 02       |PWH02 | 470| - | - |235| - | - | ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Fall Time, Rise Time            |      |    |   |   |   |   |   |     |
  | (Measured from 0.2V to Vcc-0.2V)|Tf, Tr|  - | - | 25| - | - | 15| ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Delay Time between Clocks       |      |    |   |   |   |   |   |     |
  | (Measured at 0.2V)              |  Td  |  0 | - | - | 0 | - | - | ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+

  READ/WRITE TIMING (LOAD=1TTL)             1 MHz TIMING 2 MHz TIMING
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | CHARACTERISTIC                  |SYMBOL|MIN.|TYP|MAX|MIN|TYP|MAX|UNITS|
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Read/Write Setup Time from 6508 | Trws |  - |100|300| - |100|150| ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Address Setup Time from 6508    | Tads |  - |100|300| - |100|150| ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Memory Read Access Time         | Tacc |  - | - |575| - | - |300| ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Data Stability Time Period      | Tdsu | 100| - | - | 50|   |   | ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Data Hold Time-Read             | Thr  |    | - | - |   |   |   | ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Data Hold Time-Write            | Thw  |  10| 30| - | 10| 30|   | ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Data Setup Time from 6510       | Tmds |  - |150|200| - | 75|100| ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Address Hold Time               | Tha  |  10| 30| - | 10| 30|   | ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | R/W Hold Time                   | Thrw |  10| 30| - | 10| 30|   | ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+

  408   APPENDIX L

  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Delay Time, Address valid to    |      |    |   |   |   |   |   |     |
  | 02 positive transition          | Taew | 180| - | - |   |   |   | ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Delay Time, 02 positive         |      |    |   |   |   |   |   |     |
  | transition to Data valid on bus | Tedr |  - | - |395|   |   |   | ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Delay Time, data valid to 02    |      |    |   |   |   |   |   |     |
  | negative transition             | Tdsu | 300| - | - |   |   |   | ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Delay Time, R/W negative        |      |    |   |   |   |   |   |     |
  | transition to 02 positive trans.| Twe  | 130| - | - |   |   |   | ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Delay Time, 02 negative trans.  |      |    |   |   |   |   |   |     |
  | to Peripheral data valid        | Tpdw |  - | - | 1 |   |   |   | us  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Peripheral Data Setup Time      | Tpdsu| 300| - | - |   |   |   | ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+
  | Address Enable Setup Time       | Taes |    |   | 60|   |   | 60| ns  |
  +---------------------------------+------+----+---+---+---+---+---+-----+

                                                           APPENDIX L   409

  SIGNAL DESCRIPTION

  Clocks (01, 02)

    The 6510 requires a two-phase non-overlapping clock that runs at the
  Vcc voltage level.

  Address Bus (A0-A15)

    These outputs are TTL compatible, capable of driving one standard TTL
  load and 130 pf.

  Data Bus (D0-D7)

    Eight pins are used for the data bus. This is a Bi-Directional bus,
  transferring data to and from the device and peripherals. The outputs are
  tri-state buffers capable of driving one standard TTL load and 130 pf.

  Reset

    This input is used to reset or start the microprocessor from a power
  down condition. During the time that this line is held low, writing to or
  from the microprocessor is inhibited. When a positive edge is detected on
  the input, the microprocessor will immediately begin the reset sequence.
    After a system initialization time of six clock cycles, the mask
  interrupt flag will be set and the microprocessor will load the program
  counter from the memory vector locations FFFC and FFFD. This is the start
  location for program control.
    After Vcc reaches 4.75 volts in a power-up routine, reset must be held
  low for at least two clock cycles. At this time the R/W signal will
  become valid.
    When the reset signal goes high following these two clock cycles, the
  microprocessor will proceed with the normal reset procedure detailed
  above.

  Interrupt Request (/IRQ)

    This TTL level input requests that an interrupt sequence begin within
  the microprocessor. The microprocessor will complete the current in-
  struction being executed before recognizing the request. At that time,
  the interrupt mask bit in the Status Code Register will be examined. If
  the interrupt mask flag is not set, the microprocessor will begin an

  410   APPENDIX L

  interrupt sequence. The Program Counter and Processor Status Register are
  stored in the stack. The microprocessor will then set the interrupt mask
  flag high so that no further interrupts may occur. At the end of this
  cycle, the program counter low will be loaded from address FFFE, and
  program counter high from location FFFF, therefore transferring program
  control to the memory vector located at these addresses.

  Address Enable Control (AEC)

    The Address Bus is valid only when the Address Enable Control line is
  high. When low, the Address Bus is in a high-impedance state. This
  feature allows easy DMA and multiprocessor systems.

  I/O Port (P0-P7)

    Six pins are used for the peripheral port, which can transfer data to
  or from peripheral devices. The Output Register is located in RAM at
  address 0001, and the Data Direction Register is at Address 0000. The
  outputs are capable at driving one standard TTL load and 130 pf.

  Read/Write (R/W)

    This signal is generated by the microprocessor to control the direction
  of data transfers on the Data Bus. This line is high except when the
  microprocessor is writing to memory or a peripheral device.

  ADDRESSING MODES

  ACCUMULATOR ADDRESSING - This form of addressing is represented with a
  one byte instruction, implying an operation on the accumulator.

  IMMEDIATE ADDRESSING - In immediate addressing, the operand is contained
  in the second byte of the instruction, with no further memory addressing
  required.

  ABSOLUTE ADDRESSING - In absolute addressing, the second byte of the
  instruction specifies the eight low order bits of the effective address
  while the third byte specifies the eight high order bits. Thus, the
  absolute addressing mode allows access to the entire 64K bytes of
  addressable memory.

  ZERO PAGE ADDRESSING - The zero page instructions allow for shorter code

                                                           APPENDIX L   411

  and execution times by only fetching the second byte of the instruction
  and assuming a zero high address byte. Careful use of the zero page can
  result in significant increase in code efficiency.

  INDEXED ZERO PAGE ADDRESSING - (X, Y indexing)-This form of addressing is
  used in conjunction with the index register and is referred to as "Zero
  Page, X" or "Zero Page, Y." The effective address is calculated by adding
  the second byte to the contents of the index register. Since this is a
  form of "Zero Page" addressing, the content of the second byte references
  a location in page zero. Additionally, due to the "Zero Page" addressing
  nature of this mode, no carry is added to the high order 8 bits of memory
  and crossing of page boundaries does not occur.

  INDEXED ABSOLUTE ADDRESSING - (X, Y indexing)-This form of addressing is
  used in conjunction with X and Y index register and is referred to as
  "Absolute, X," and "Absolute, Y." The effective address is formed by
  adding the contents of X and Y to the address contained in the second and
  third bytes of the instruction. This mode allows the index register to
  contain the index or count value and the instruction to contain the base
  address. This type of indexing allows any location referencing and the
  index to modify multiple fields resulting in reduced coding and execution
  time.

  IMPLIED ADDRESSING - In the implied addressing mode, the address
  containing the operand is implicitly stated in the operation code of the
  instruction.

  RELATIVE ADDRESSING - Relative addressing is used only with branch
  instructions and establishes a destination for the conditional branch.

  The second byte of the instruction becomes the operand which is an
  "Offset" added to the contents of the lower eight bits of the program
  counter when the counter is set at the next instruction. The range of the
  offset is -128 to +127 bytes from the next instruction.

  INDEXED INDIRECT ADDRESSING - In indexed indirect addressing (referred to
  as [Indirect, X]), the second byte of the instruction is added to the
  contents of the X index register, discarding the carry. The result of
  this addition points to a memory location on page zero whose contents is
  the low order eight bits of the effective address. The next memory loca-
  tion in page zero contains the high order eight bits of the effective ad-
  dress. Both memory locations specifying the high and low order bytes of

  412   APPENDIX L

  the effective address must be in page zero.

  INDIRECT INDEXED ADDRESSING - In indirect indexed addressing (referred to
  as [Indirect], Y), the second byte of the instruction points to a memory
  location in page zero. The contents of this memory location is added to
  the contents of the Y index register, the result being the low order
  eight bits of the effective address. The carry from this addition is
  added to the contents of the next page zero memory location, the result
  being the high order eight bits of the effective address.

  ABSOLUTE INDIRECT - The second byte of the instruction contains the low
  order eight bits of a memory location. The high order eight bits of that
  memory location is contained in the third byte of the instruction. The
  contents of the fully specified memory location is the low order byte of
  the effective address. The next memory location contains the high order
  byte of the effective address which is loaded into the sixteen bits of
  the program counter.

  INSTRUCTION SET - ALPHABETIC SEQUENCE

          ADC   Add Memory to Accumulator with Carry
          AND   "AND" Memory with Accumulator
          ASL   Shift left One Bit (Memory or Accumulator)

          BCC   Branch on Carry Clear
          BCS   Branch on Carry Set
          BEQ   Branch on Result Zero
          BIT   Test Bits in Memory with Accumulator
          BMI   Branch on Result Minus
          BNE   Branch on Result not Zero
          BPL   Branch on Result Plus
          BRK   Force Break
          BVC   Branch on Overflow Clear
          BVS   Branch on Overflow Set

          CLC   Clear Carry Flag
          CLD   Clear Decimal Mode
          CLI   Clear Interrupt Disable Bit
          CLV   Clear Overflow Flag
          CMP   Compare Memory and Accumulator
          CPX   Compare Memory and Index X
          CPY   Compare Memory and Index Y

                                                           APPENDIX L   413

          DEC   Decrement Memory by One
          DEX   Decrement Index X by One
          DEY   Decrement Index Y by One

          EOR   "Exclusive-OR" Memory with Accumulator

          INC   Increment Memory by One
          INX   Increment Index X by one
          INY   Increment Index Y by one

          JMP   Jump to New location
          JSR   Jump to New Location Saving Return Address

          LDA   Load Accumulator with Memory
          LDX   Load Index X with Memory
          LDY   Load Index Y with Memory
          LSR   Shift One Bit Right (Memory or Accumulator)

          NOP   No Operation

          ORA   "OR" Memory with Accumulator

          PHA   Push Accumulator on Stack
          PHP   Push Processor Status on Stack
          PLA   Pull Accumulator from Stack
          PLP   Pull Processor Status from Stack

          ROL   Rotate One Bit Left (Memory or Accumulator)
          ROR   Rotate One Bit Right (Memory or Accumulator)
          RTI   Return from Interrupt
          RTS   Return from Subroutine

          SBC   Subtract Memory from Accumulator with Borrow
          SEC   Set Carry Flag
          SED   Set Decimal Mode
          SEI   Set Interrupt Disable Status
          STA   Store Accumulator in Memory
          STX   Store Index X in Memory
          STY   Store Index Y in Merrory

  414   APPENDIX L

          TAX   Transfer Accumulator to Index X
          TAY   Transfer Accumulator to Index Y
          TSX   Transfer Stack Pointer to Index X
          TXA   Transfer Index X to Accumulator
          TXS   Transfer Index X to Stack Register
          TYA   Transfer Index Y to Accumulator

  PROGRAMMING MODEL
                        +---------------+
                        |       A       |  ACCUMULATOR           A
                        +---------------+

                        +---------------+
                        |       Y       |  INDEX REGISTER        Y
                        +---------------+

                        +---------------+
                        |       X       |  INDEX REGISTER        X
                        +---------------+
        15               7             0
        +---------------+---------------+
        |      PCH      |      PCL      |  PROGRAM COUNTER     "PC"
        +---------------+---------------+
                       8 7             0
                      +-+---------------+
                      |1|       S       |  STACK POINTER        "S"
                      +-+---------------+
                         7             0
                        +-+-+-+-+-+-+-+-+
                        |N|V| |B|D|I|Z|C|  PROCESSOR STATUS REG "P"
                        +-+-+-+-+-+-+-+-+
                         | |   | | | | |
                         | |   | | | | +>  CARRY         1=TRUE
                         | |   | | | +-->  ZERO          1=RESULT ZERO
                         | |   | | +---->  IRQ DISABLE   1=DISABLE
                         | |   | +------>  DECIMAL MODE  1=TRUE
                         | |   +-------->  BRK COMMAND
                         | |
                         | +------------>  OVERFLOW      1=TRUE
                         +-------------->  NEGATIVE      1=NEG

                                                           APPENDIX L   415

      INSTRUCTION SET - OP CODES, EXECUTION TIME, MEMORY REQUIREMENTS

                          [THE PICTURE IS MISSING!]

  +-----------------------------------------------------------------------+
  | NOTE: COMMODORE SEMICONDUCTOR GROUP cannot assume liability for the   |
  | use of undefined OP CODES.                                            |
  +-----------------------------------------------------------------------+

  416   APPENDIX L

      INSTRUCTION SET - OP CODES, EXECUTION TIME, MEMORY REQUIREMENTS

                          [THE PICTURE IS MISSING!]

                                                           APPENDIX L   417

  6510 MEMORY MAP

       +-------------------+
  FFFF |                   |
       |    ADDRESSABLE    |
       /      EXTERNAL     /
       /       MEMORY      /
       |                   |
  0200 |                   |
       +-------------------+           STACK
  01FF |  |    STACK    |  | 01FF <--- POINTER
  0100 | \|/   Page 1  \|/ |           INITIALIZED
       +-------------------+
  00FF |                   |
       |       Page 0      |
       +-------------------+
       |  OUTPUT REGISTER  | 0001 <-+- Used For
       +-------------------+        |  Internal
  0000 |DATA DIRECTION REG.| 0000 <-+  I/O Port
       +-------------------+

  APPLICATIONS NOTES

    Locating the Output Register at the internal I/O Port in Page Zero
  enhances the powerful Zero Page Addressing instructions of the 6510.
    By assigning the I/O Pins as inputs (using the Data Direction Register)
  the user has the ability to change the contents of address 0001 (the
  Output Register) using peripheral devices. The ability to change these
  contents using peripheral inputs, together with Zero Page Indirect
  Addressing instructions, allows novel and versatile programming tech-
  niques not possible earlier.

  +-----------------------------------------------------------------------+
  | COMMODORE SEMICONDUCTOR GROUP reserves the right to make changes to   |
  | any products herein to improve reliability, function or design.       |
  | COMMODORE SEMICONDUCTOR GROUP does not assume any liability arising   |
  | out of the application or use of any product or circuit described     |
  | herein; neither does it convey any license under its patent rights nor|
  | the rights of others.                                                 |
  +-----------------------------------------------------------------------+

  418   APPENDIX L

  APPENDIX M

  6526 COMPLEX INTERFACE ADAPTER
  (CIA) CHIP SPECIFICATIONS

  DESCRIPTION

    The 6526 Complex Interface Adapter (CIA) is a 65XX bus compatible
  peripheral interface device with extremely flexible timing and I/O
  capabilities.

  FEATURES

  o 16 Individually programmable 110 lines
  o 8 or 16-Bit handshaking on read or write
  o 2 independent, linkable 16-Bit interval timers
  o 24-hour (AM/PM) time of day clock with programmable alarm
  o 8-Bit shift register for serial I/O
  o 2 TTL load capability
  o CMOS compatible I/O lines
  o 1 or 2 MHz operation available

                                                           APPENDIX M   419

                              PIN CONFIGURATION

                                +----+ +----+
                       Vss   1 @|    +-+    |@ 40  CNT
                                |           |
                       PA0   2 @|           |@ 39  SP
                                |           |
                       PA1   3 @|           |@ 38  RS0
                                |           |
                       PA2   4 @|           |@ 37  RS1
                                |           |
                       PA3   5 @|           |@ 36  RS2
                                |           |
                       PA4   6 @|           |@ 35  RS3
                                |           |
                       PA5   7 @|           |@ 34  /RES
                                |           |
                       PA6   8 @|           |@ 33  D0
                                |           |
                       PA7   9 @|           |@ 32  D1
                                |           |
                       PB0  10 @|           |@ 31  D2
                                |    6526   |
                       PB1  11 @|           |@ 30  D3
                                |           |
                       PB2  12 @|           |@ 29  D4
                                |           |
                       PB3  13 @|           |@ 28  D5
                                |           |
                       PB4  14 @|           |@ 27  D6
                                |           |
                       PB5  15 @|           |@ 26  D7
                                |           |
                       PB6  16 @|           |@ 25  02
                                |           |
                       PB7  17 @|           |@ 24  /FLAG
                                |           |
                       /PC  18 @|           |@ 23  /CS
                                |           |
                       TOD  19 @|           |@ 22  R/W
                                |           |
                       Vcc  20 @|           |@ 21  /IRQ
                                +-----------+
  420   APPENDIX M

                             6526 BLOCK DIAGRAM

                          [THE PICTURE IS MISSING!]

                                                           APPENDIX M   421

  MAXIMUM RATINGS

  Supply Voltage, Vcc                   -0.3V to +7.0V
  Input/Output Voltage, Vin             -0.3V to +7.0V
  Operating Temperature, Top             0 to 70 Celsius
  Storage Temperature, Tstg             -55 to 150 Celsius

    All inputs contain protection circuitry to prevent damage due to high
  static discharges. Care should be exercised to prevent unnecessary ap-
  plication of voltages in excess of the allowable limits.

  COMMENT

    Stresses above those listed under "Absolute Maximum Ratings" may cause
  permanent damage to the device. These are stress ratings oily. Functional
  operation of this device at these or any other conditions above those
  indicated in the operational sections of this specification is not
  implied and exposure to absolute maximum rating conditions for extended
  periods may affect device reliability.

  ELECTRICAL CHARACTERISTICS (Vcc +-5%, Vss=0V, Ta=0-70 Celsius)

  +-------------------------------+--------+-------+-------+-------+------+
  | CHARACTERISTIC                | SYMBOL | MIN.  | TYP.  | MAX.  | UNIT |
  +-------------------------------+--------+-------+-------+-------+------+
  | Input High Voltage            |  Vih   | +2.4  |   -   |  Vcc  |   V  |
  +-------------------------------+--------+-------+-------+-------+------+
  | Input Low Voltage             |  Vil   | -0.3  |   -   |   -   |   V  |
  +-------------------------------+--------+-------+-------+-------+------+
  | Input Leakage Current;        |  Iin   |   -   |  1.0  |  2.5  |  uA  |
  | Vin=Vss+5V                    |        |       |       |       |      |
  | (TOD, R/W, /FLAG, 02,         |        |       |       |       |      |
  | /RES, RS0-RS3, /CS)           |        |       |       |       |      |
  +-------------------------------+--------+-------+-------+-------+------+

  422   APPENDIX M

  +-------------------------------+--------+-------+-------+-------+------+
  | CHARACTERISTIC                | SYMBOL | MIN.  | TYP.  | MAX.  | UNIT |
  +-------------------------------+--------+-------+-------+-------+------+
  | Port Input Pull-up Resistance |  Rpi   |  3.1  |  5.0  |   -   | kohms|
  +-------------------------------+--------+-------+-------+-------+------+
  | Output Leakage Current for    |  Itsi  |   -   |+-1.0  |+-10.0 |  uA  |
  | High Impedance State (Three   |        |       |       |       |      |
  | State); Vin=4V to 2.4V;       |        |       |       |       |      |
  | (D0-D7, SP, CNT, /IRQ)        |        |       |       |       |      |
  +-------------------------------+--------+-------+-------+-------+------+
  | Output High Voltage           |  Voh   | +2.4  |   -   |  Vcc  |   V  |
  | Vcc=MIN, Iload <              |        |       |       |       |      |
  | -200uA (PA0-PA7, /PC,         |        |       |       |       |      |
  | PB0-PB7, D0-D7)               |        |       |       |       |      |
  +-------------------------------+--------+-------+-------+-------+------+
  | Output Low Voltage            |  Vol   |   -   |   -   | +0.40 |   V  |
  | Vcc=MIN, Iload < 3.2 mA       |        |       |       |       |      |
  +-------------------------------+--------+-------+-------+-------+------+
  | Output High Current (Sourcing)|  Ioh   | -200  | -1000 |   -   |  uA  |
  | Voh > 2.4V (PA0-PA7,          |        |       |       |       |      |
  | PB0-PB7, /PC, D0-D7           |        |       |       |       |      |
  +-------------------------------+--------+-------+-------+-------+------+
  | Output Low Current (Sinking); |  Iol   |  3.2  |   -   |   -   |  mA  |
  | Vol <  .4V (PA0-PA7, /PC,     |        |       |       |       |      |
  | PB0-PB7, D0-D7                |        |       |       |       |      |
  +-------------------------------+--------+-------+-------+-------+------+
  | Input Capacitance             |  Cin   |   -   |    7  |   10  |  pf  |
  +-------------------------------+--------+-------+-------+-------+------+
  | Output Capacitance            |  Cout  |   -   |    7  |   10  |  pf  |
  +-------------------------------+--------+-------+-------+-------+------+
  | Power Supply Current          |  Icc   |   -   |   70  |  100  |  mA  |
  +-------------------------------+--------+-------+-------+-------+------+

                                                           APPENDIX M   423

                         6526 WRITE TIMING DIAGRAM

                          [THE PICTURE IS MISSING!]

  424   APPENDIX M

                          6526 READ TIMING DIAGRAM

                          [THE PICTURE IS MISSING!]

                                                           APPENDIX M   425

  6526 INTERFACE SIGNALS

  02-Clock Input

    The 02 clock is a TTL compatible input used for internal device opera-
  tion and as a timing reference for communicating with the system data
  bus.

  /CS-Chip Select Input

    The /CS input controls the activity of the 6526. A low level on /CS
  while 02 is high causes the device to respond to signals on the R/W and
  address (RS) lines. A high on /CS prevents these lines from controlling
  the 6526. The /CS line is normally activated (low) at 02 by the
  appropriate address combination.

  R/W-Read/Write Input

    The R/W signal is normally supplied by the microprocessor and controls
  the direction of data transfers of the 6526. A high on R/W indicates
  a read (data transfer out of the 6526), while a low indicates a write
  (data transfer into the 6526).

  RS3-RS0-Address Inputs

    The address inputs select the internal registers as described by the
  Register Map.

  DB7-DB0-Data Bus Inputs/Outputs

    The eight data bus pins transfer information between the 6526 and the
  system data bus. These pins are high impedance inputs unless CS is low
  and R/W and 02 are high to read the device. During this read, the data
  bus output buffers are enabled, driving the data from the selected
  register onto the system data bus.

  IRQ-Interrupt Request Output

    IRQ is an open drain output normally connected to the processor inter-
  rupt input. An external pullup resistor holds the signal high, allowing
  multiple IRQ outputs to be connected together. The IRQ output is normally

  426   APPENDIX M

  off (high impedance) and is activated low as indicated in the functional
  description.

  /RES-Reset Input

    A low on the RES pin resets all internal registers. The port pins are
  set as inputs and port registers to zero (although a read of the ports
  will return all highs because of passive pullups). The timer control
  registers are set to zero and the timer latches to all ones. All other
  registers are reset to zero.

                        6526 TIMING CHARACTERISTICS
  +--------+-----------------------+---------------+---------------+------+
  |        |                       |      1MHz     |      2MHz     |      |
  |        |                       +-------+-------+-------+-------+      |
  | Symbol |    Characteristic     |  MIN  |  MAX  |  MIN  |  MAX  | Unit |
  +--------+-----------------------+-------+-------+-------+-------+------+
  |        | 02 CLOCK              |       |       |       |       |      |
  | Tcyc   | Cycle Time            |  1000 |20,000 |   500 |20,000 |  ns  |
  | Tr, Tf | Rise and Fall Time    |   -   |    25 |   -   |    25 |  ns  |
  | Tchw   | Clock Pulse Width     |       |       |       |       |      |
  |        |   (High)              |   420 |10,000 |   200 |10,000 |  ns  |
  | Tclw   | Clock Pulse Width     |       |       |       |       |      |
  |        |   (Low)               |   420 |10,000 |   200 |10,000 |  ns  |
  +--------+-----------------------+-------+-------+-------+-------+------+
  |        | WRITE CYCLE           |       |       |       |       |      |
  | Tpd    | Output Delay From 02  |    -  |  1000 |   -   |   500 |  ns  |
  | Twcs   | /CS low while 02 high |   420 |   -   |   200 |   -   |  ns  |
  | Tads   | Address Setup Time    |     0 |   -   |     0 |   -   |  ns  |
  | Tadh   | Address Hold Time     |    10 |   -   |     5 |   -   |  ns  |
  | Trws   | R/W Setup Time        |     0 |   -   |     0 |   -   |  ns  |
  | Trwh   | R/W Hold Time         |     0 |   -   |     0 |   -   |  ns  |
  | Tds    | Data Bus Setup Time   |   150 |   -   |    75 |   -   |  ns  |
  | Tdh    | Data Bus Hold Time    |     0 |   -   |     0 |   -   |  ns  |
  +--------+-----------------------+-------+-------+-------+-------+------+
  |        | READ CYCLE            |       |       |       |       |      |
  | Tps    | Port Setup Time       |   300 |   -   |   150 |   -   |  ns  |
  | Twcs(2)| /CS low while 02 high |   420 |   -   |    20 |   -   |  ns  |
  | Tads   | Address Setup Time    |     0 |   -   |     0 |   -   |  ns  |
  | Tadh   | Address Hold Time     |    10 |   -   |     5 |   -   |  ns  |
  | Trws   | R/W Setup Time        |     0 |   -   |     0 |   -   |  ns  |
  | Trwh   | R/W Hold Time         |     0 |   -   |     0 |   -   |  ns  |

                                                           APPENDIX M   427

  +--------+-----------------------+---------------+---------------+------+
  |        |                       |      1MHz     |      2MHz     |      |
  |        |                       +-------+-------+-------+-------+      |
  | Symbol |    Characteristic     |  MIN  |  MAX  |  MIN  |  MAX  | Unit |
  +--------+-----------------------+-------+-------+-------+-------+------+
  | Tacc   | Data Access from      |       |       |       |       |      |
  |        | RS3-RS0               |   -   |   550 |   -   |   275 |  ns  |
  | Tco(3) | Data Access from /CS  |   -   |   320 |   -   |   150 |  ns  |
  | Tdr    | Data Release Time     |    50 |   -   |    25 |   -   |  ns  |
  +--------+-----------------------+-------+-------+-------+-------+------+

  +-----------------------------------------------------------------------+
  | NOTES: 1 -All timings are referenced from Vil max and Vih min on      |
  | inputs and Vol max and Voh min on outputs.                            |
  |        2 -Twcs is measured from the later of 02 high or /CS low. /CS  |
  | must be low at least until the end of 02 high.                        |
  |        3 -Tco is measured from the later of 02 high or /CS low.       |
  |        Valid data is available only after the later of Tacc or Tco.   |
  +-----------------------------------------------------------------------+

                                REGISTER MAP
  +---+---+---+---+---+----------+----------------------------------------+
  |RS3|RS2|RS1|RS0|REG|   NAME   |                                        |
  +---+---+---+---+---+----------+----------------------------------------+
  | 0 | 0 | 0 | 0 | 0 | PRA      |  PERIPHERAL DATA REG A                 |
  | 0 | 0 | 0 | 1 | 1 | PRB      |  PERIPHERAL DATA REG B                 |
  | 0 | 0 | 1 | 0 | 2 | DDRA     |  DATA DIRECTION REG A                  |
  | 0 | 0 | 1 | 1 | 3 | DDRB     |  DATA DIRECTION REG B                  |
  | 0 | 1 | 0 | 0 | 4 | TA LO    |  TIMER A LOW REGISTER                  |
  | 0 | 1 | 0 | 1 | 5 | TA HI    |  TIMER A HIGH REGISTER                 |
  | 0 | 1 | 1 | 0 | 6 | TB LO    |  TIMER B LOW REGISTER                  |
  | 0 | 1 | 1 | 1 | 7 | TB HI    |  TIMER B HIGH REGISTER                 |
  | 1 | 0 | 0 | 0 | 8 | TOD 10THS|  10THS OF SECONDS REGISTER             |
  | 1 | 0 | 0 | 1 | 9 | TOD SEC  |  SECONDS REGISTER                      |
  | 1 | 0 | 1 | 0 | A | TOD MIN  |  MINUTES REGISTER                      |
  | 1 | 0 | 1 | 1 | B | TOD HR   |  HOURS-AM/PM REGISTER                  |
  | 1 | 1 | 0 | 0 | C | SDR      |  SERIAL DATA REGISTER                  |
  | 1 | 1 | 0 | 1 | 0 | ICR      |  INTERRUPT CONTROL REGISTER            |
  | 1 | 1 | 1 | 0 | E | CRA      |  CONTROL REG A                         |
  | 1 | 1 | 1 | 1 | F | CRB      |  CONTROL REG B                         |
  +---+---+---+---+---+----------+----------------------------------------+

  428   APPENDIX M

  6526 FUNCTIONAL DESCRIPTION

  I/O Ports (PRA, PRB, DDRA, DDRB).

    Ports A and B each consist of an 8-bit Peripheral Data Register (PR)
  and an 8-bit Data Direction Register (DDR). If a bit in the DDR is set to
  a one, the corresponding bit in the PR is an output; if a DDR bit is set
  to a zero, the corresponding PR bit is defined as an input. On a READ,
  the PR reflects the information present on the actual port pins (PA0-PA7,
  PB0-PB7) for both input and output bits. Port A and Port B have passive
  pull-up devices as well as active pull-ups, providing both CMOS and TTL
  compatibility. Both ports have two TTL load drive capability. In addition
  to normal I/O operation, PB6 and PB7 also provide timer output functions.

  Handshaking

    Handshaking on data transfers can be accomplished using the /PC output
  pin and the FLAG input pin. PC will go low for one cycle following a read
  or write of PORT B. This signal can be used to indicate "data ready" at
  PORT B or "data accepted" from PORT B. Handshaking on 16-bit data
  transfers (using both PORT A and PORT B) is possible by always reading or
  writing PORT A first. /FLAG is a negative edge sensitive input which can
  be used for receiving the /PC output from another 6526, or as a general
  purpose interrupt input. Any negative transition of /FLAG will set the
  /FLAG interrupt bit.
  +-----+---------+------+------+------+------+------+------+------+------+
  | REG |  NAME   |  D7  |  D6  |  D5  |  D4  |  D3  |  D2  |  D1  |  D0  |
  +-----+---------+------+------+------+------+------+------+------+------+
  |  0  |   PRA   |  PA7 |  PA6 |  PA5 |  PA4 |  PA3 |  PA2 |  PA1 |  PA0 |
  |  1  |   PRB   |  PB7 |  PB6 |  PB5 |  PB4 |  PB3 |  PB2 |  PB1 |  PB0 |
  |  2  |  DDRA   | DPA7 | DPA6 | DPA5 | DPA4 | DPA3 | DPA2 | DPA1 | DPA0 |
  |  3  |  DDRB   | DPB7 | DPB6 | DPB5 | DPB4 | DPB3 | DPB2 | DPB1 | DPB0 |
  +-----+---------+------+------+------+------+------+------+------+------+

  Interval Timers (Timer A, Timer B)

    Each interval timer consists of a 16-bit read-only Timer Counter and a
  16-bit write-only Timer Latch. Data written to the timer are latched in
  the Timer Latch, while data read from the timer are the present contents
  of the Time Counter. The timers can be used independently or linked for
  extended operations. The various timer modes allow generation of long
  time delays, variable width pulses, pulse trains and variable frequency

                                                           APPENDIX M   429

  waveforms. Utilizing the CNT input, the timers can count external pulses
  or measure frequency, pulse width and delay times of external signals.
  Each timer has an associated control register, providing independent
  control of the following functions:

  Start/Stop

    A control bit allows the timer to be started or stopped by the micro-
  processor at any time.

  PB On/Off:

    A control bit allows the timer output to appear on a PORT B output line
  (PB6 for TIMER A and PB7 for TIMER B). This function overrides the DDRB
  control bit and forces the appropriate PB line to an output.

  Toggle/Pulse

    A control bit selects the output applied to PORT B. On every timer
  underflow the output can either toggle or generate a single positive
  pulse of one cycle duration. The Toggle output is set high whenever the
  timer is started and is set low by /RES.

  One-Shot/Continuous

    A control bit selects either timer mode. In one-shot mode, the timer
  will count down from the latched value to zero, generate an interrupt,
  reload the latched value, then stop. In continuous mode, the timer will
  count from the latched value to zero, generate' an interrupt, reload the
  latched value and repeat the procedure continuously.

  Force Load

    A strobe bit allows the timer latch to be loaded into the timer counter
  at any time, whether the timer is running or not.

  Input Mode:

    Control bits allow selection of the clock used to decrement the timer.
  TIMER A can count 02 clock pulses or external pulses applied to the CNT
  pin. TIMER B can count (02 pulses, external CNT pulses, TIMER A underflow
  pulses or TIMER A underflow pulses while the CNT pin is held high.

  430   APPENDIX M

    The timer latch is loaded into the timer on any timer underflow, on a
  force load or following a write to the high byte of the prescaler while
  the timer is stopped. If the timer is running, a write to the high byte
  will load the timer latch, but not reload the counter.

  READ (TIMER)
    REG    NAME
  +-----+---------+------+------+------+------+------+------+------+------+
  |  4  |  TA LO  | TAL7 | TAL6 | TAL5 | TAL4 | TAL3 | TAL2 | TAL1 | TAL0 |
  |  5  |  TA HI  | TAH7 | TAH6 | TAH5 | TAH4 | TAH3 | TAH2 | TAH1 | TAH0 |
  |  6  |  TB LO  | TBL7 | TBL6 | TBL5 | TBL4 | TBL3 | TBL2 | TBL1 | TBL0 |
  |  7  |  TB HI  | TBH7 | TBH6 | TBH5 | TBH4 | TBH3 | TBH2 | TBH1 | TBH0 |
  +-----+---------+------+------+------+------+------+------+------+------+
  WRITE (PRESCALER)
    REG    NAME
  +-----+---------+------+------+------+------+------+------+------+------+
  |  4  |  TA LO  | PAL7 | PAL6 | PAL5 | PAL4 | PAL3 | PAL2 | PAL1 | PAL0 |
  |  5  |  TA HI  | PAH7 | PAH6 | PAH5 | PAH4 | PAH3 | PAH2 | PAH1 | PAH0 |
  |  6  |  TB LO  | PBL7 | PBL6 | PBL5 | PBL4 | PBL3 | PBL2 | PBL1 | PBL0 |
  |  7  |  TB HI  | PBH7 | PBH6 | PBH5 | PBH4 | PBH3 | PBH2 | PBH1 | PBH0 |
  +-----+---------+------+------+------+------+------+------+------+------+

  Time of Day Clock (TOD)

    The TOD clock is a special purpose timer for real-time applications.
  TOD consists of a 24-hour (AM/PM) clock with 1/10th second resolution. It
  is organized into 4 registers: 10ths of seconds, Seconds, Minutes and
  Hours. The AM/PM flag is in the MSB of the Hours register for easy bit
  testing. Each register reads out in BCD format to simplify conversion for
  driving displays, etc. The clock requires an external 60 Hz or 50 Hz
  (programmable) TTL level input on the TOD pin for accurate time-keeping.
  In addition to time-keeping, a programmable ALARM is provided for
  generating an interrupt at a desired time. The ALARM registers or located
  at the same addresses as the corresponding TOD registers. Access to the
  ALARM is governed by a Control Register bit. The ALARM is write-only; any
  read of a TOD address will read time regardless of the state of the ALARM
  access bit.
    A specific sequence of events must be followed for proper setting and
  reading of TOD. TOD is automatically stopped whenever a write to the
  Hours register occurs. The clock will not start again until after a write
  to the 10ths of seconds register. This assures TOD will always start at
  the desired time. Since a carry from one stage to the next can occur at

                                                           APPENDIX M   431

  any time with respect to a read operation, a latching function is
  included to keep all Time Of Day information constant during a read
  sequence. All four TOD registers latch on a read of Hours and remain
  latched until after a read of 10ths of seconds. The TOD clock continues
  to count when the output registers are latched. If only one register is
  to be read, there is no carry problem and the register can be read "on
  the fly," provided that any read of Hours is followed by a read of 10ths
  of seconds to disable the latching.

  READ
    REG    NAME
  +-----+---------+------+------+------+------+------+------+------+------+
  |  8  |TOD 10THS|  0   |  0   |  0   |  0   |  T8  |  T4  |  T2  |  T1  |
  |  9  |TOD SEC  |  0   |  SH4 |  SH2 |  SH1 |  SL8 |  SL4 |  SL2 |  SL1 |
  |  A  |TOD MIN  |  0   |  MH4 |  MH2 |  MH1 |  ML8 |  ML4 |  ML2 |  ML1 |
  |  B  |TOD HR   |  PM  |  0   |  0   |  HH  |  HL8 |  HL4 |  HL2 |  HL1 |
  +-----+---------+------+------+------+------+------+------+------+------+

  WRITE

  CRB7=0 TOD
  CRB7=1 ALARM
  (SAME FORMAT AS READ)

  Serial Port (SDR)

    The serial port is a buffered, 8-bit synchronous shift register system.
  A control bit selects input or output mode. In input mode, data on the SP
  pin is shifted into the shift register on the rising edge of the signal
  applied to the CNT pin. After 8 CNT pulses, the data in the shift
  register is dumped into the Serial Data Register and an interrupt is
  generated. In the output mode, TIMER A is used for the baud rate
  generator. Data is shifted out on the SP pin at 1/2 the underflow rate of
  TIMER A. The maximum baud rate possible is 02 divided by 4, but the
  maximum useable baud rate will be determined by line loading and the
  speed at which the receiver responds to input data. Transmission will
  start following a write to the Serial Data Register (provided TIMER A is
  running and in continuous mode). The clock signal derived from TIMER A
  appears as an output on the CNT pin. The data in the Serial Data Register
  will be loaded into the shift register then shift out to the SP pin when
  a CNT pulse occurs. Data shifted out becomes valid on the falling edge of
  CNT and remains valid until the next falling edge. After 8 CNT pulses, an

  432   APPENDIX M

  interrupt is generated to indicate more data can be sent. If the Serial
  Data Register was loaded with new information prior to this interrupt,
  the new data will automatically be loaded into the shift register and
  transmission will continue. If the microprocessor stays one byte ahead of
  the shift register, transmission will be continuous. If no further data
  is to be transmitted, after the 8th CNT pulse, CNT will return high and
  SP will remain at the level of the last data bit transmitted. SDR data is
  shifted out MSB first and serial input data should also appear in this
  format.
    The bidirectional capability of the Serial Port and CNT clock allows
  many 6526 devices to be connected to a common serial communication bus on
  which one 6526 acts as a master, sourcing data and shift clock, while all
  other 6526 chips act as slaves. Both CNT and SP outputs are open drain to
  allow such a common bus. Protocol for master/slave selection can be
  transmitted over the serial bus, or via dedicated handshaking lines.

    REG    NAME
  +-----+---------+------+------+------+------+------+------+------+------+
  |  C  |   SDR   |  S7  |  S6  |  S5  |  S4  |  S3  |  S2  |  S1  |  S0  |
  +-----+---------+------+------+------+------+------+------+------+------+

  Interrupt Control (ICR)

    There are five sources of interrupts on the 6526: underflow from TIMER
  A, underflow from TIMER B, TOD ALARM, Serial Port full/empty and /FLAG.
  A single register provides masking and interrupt information. The
  interrupt Control Register consists of a write-only MASK register and a
  read-only DATA register. Any interrupt will set the corresponding bit in
  the DATA register. Any interrupt which is enabled by the MASK register
  will set the IR bit (MSB) of the DATA register and bring the /IRQ pin
  low. In a multi-chip system, the IR bit can be polled to detect which
  chip has generated an interrupt request. The interrupt DATA register is
  cleared and the /IRQ line returns high following a read of the DATA
  register. Since each interrupt sets an interrupt bit regardless of the
  MASK, and each interrupt bit can be selectively masked to prevent the
  generation of a processor interrupt, it is possible to intermix polled
  interrupts with true interrupts. However, polling the IR bit will cause
  the DATA register to clear, therefore, it is up to the user to preserve
  the information contained in the DATA register if any polled interrupts
  were present.
    The MASK register provides convenient control of individual mask bits.
  When writing to the MASK register, if bit 7 (SET/CLEAR) of the data

                                                           APPENDIX M   433

  written is a ZERO, any mask bit written with a one will be cleared, while
  those mask bits written with a zero will be unaffected. If bit 7 of the
  data written is a ONE, any mask bit written with a one will be set, while
  those mask bits written with a zero will be unaffected. In order for an
  interrupt flag to set IR and generate an Interrupt Request, the corre-
  sponding MASK bit must be set.

  READ (INT DATA)
    REG    NAME
  +-----+---------+------+------+------+------+------+------+------+------+
  |  D  |   ICR   |  IR  |   0  |   0  |  FLG |  SP  | ALRM |  TB  |  TA  |
  +-----+---------+------+------+------+------+------+------+------+------+

  WRITE (INT MASK)
    REG    NAME
  +-----+---------+------+------+------+------+------+------+------+------+
  |  D  |   ICR   |  S/C |   X  |   X  |  FLG |  SP  | ALRM |  TB  |  TA  |
  +-----+---------+------+------+------+------+------+------+------+------+

  CONTROL REGISTERS

    There are two control registers in the 6526, CRA and CRB. CRA is
  associated with TIMER A and CRB is associated with TIMER B. The register
  format is as follows:

  CRA:
  Bit  Name    Function
   0  START    1=START TIMER A, 0=STOP TIMER A. This bit is automatically
               reset when underflow occurs during one-shot mode.
   1  PBON     1=TIMER A output appears on PB6, 0=PB6 normal operation.

   2  OUTMODE  1=TOGGLE, 0=PULSE
   3  RUNMODE  1=ONE-SHOT, 0=CONTINUOUS
   4  LOAD     1=FORCE LOAD (this is a STROBE input, there is no data
               storage, bit 4 will always read back a zero and writing a
               zero has no effect).
   5  INMODE   1=TIMER A counts positive CNT transitions, 0=TIMER A counts
               02 pulses.
   6  SPMODE   1=SERIAL PORT output (CNT sources shift clock),
               0=SERIAL PORT input (external shift clock required).
   7  TODIN    1=50 Hz clock required on TOD pin for accurate time,
               0=60 Hz clock required on TOD pin for accurate time.

  434   APPENDIX M

  CRB:
  Bit  Name    Function
               (Bits CRB0-CRB4 are identical to CRA0-CRA4 for TIMER B with
               the exception that bit 1 controls the output of TIMER B on
               PB7).
  5,6 INMODE   Bits CRB5 and CRB6 select one of four input modes for
               TIMER B as:
               CRB6   CRB5
                0      0       TIMER B counts 02 pulses.
                0      1       TIMER B counts positive CNT transistions.
                1      0       TIMER B counts TIMER A underflow pulses.
                1      1       TIMER B counts TIMER A underflow pulses
                               while CNT is high.
  7   ALARM     1=writing to TOD registers sets ALARM, 0=writing to TOD
                registers sets TOD clock.

  REGNAME TODIN SP MODE IN MODE   LOAD  RUN MODE OUT MODE   PB ON   START
  +-+---+------+-------+-------+--------+-------+--------+--------+-------+
  |E|CRA|0=60Hz|0=INPUT| 0=02  |1=FORCE |0=CONT.|0=PULSE |0=PB6OFF|0=STOP |
  | |   |      |       |       |  LOAD  |       |        |        |       |
  | |   |1=50Hz|1=OUTP.| 1=CNT |(STROBE)|1=O.S. |1=TOGGLE|1=PB6ON |1=START|
  +-+---+------+-------+-------+--------+-------+--------+--------+-------+
                       +------------------ TA ----------------------------+

  REGNAME ALARM    IN MODE        LOAD  RUN MODE OUT MODE   PB ON   START
  +-+---+------+------+--------+--------+-------+--------+--------+-------+
  |E|CRB|0=TOD |   0  |0=02    |1=FORCE |0=CONT.|0=PULSE |0=PB7OFF|0=STOP |
  | |   |      |   1  |1=CNT   |LOAD    |       |        |        |       |
  | |   |1=    |   1  |0=TA    |        |       |        |        |       |
  | |   | ALARM|   1  |1=CNT&TA|(STROBE)|1=O.S. |1=TOGGLE|1=PB7ON |1=START|
  +-+---+------+------+--------+--------+-------+--------+--------+-------+
               +-------------------------- TB ----------------------------+

  All unused register bits are unaffected by a write and are forced to zero
  on a read.
  +-----------------------------------------------------------------------+
  | COMMODORE SEMICONDUCTOR GROUP reserves the right to make changes to   |
  | any products herein to improve reliability, function or design.       |
  | COMMODORE SEMICONDUCTOR GROUP does not assume any liability arising   |
  | out of the application or use of any product or circuit described     |
  | herein; neither does it convey any license under its patent rights nor|
  | the rights of others.                                                 |
  +-----------------------------------------------------------------------+
                                                           APPENDIX M   435

  APPENDIX N

  6566/6567 (VIC-II) CHIP
  SPECIFICATIONS

    The 6566/6567 are multi-purpose color video controller devices for use
  in both computer video terminals and video game applications. Both
  devices contain 47 control registers which are accessed via a standard
  8-bit microprocessor bus (65XX) and will access up to 16K of memory for
  display information. The various operating modes and options within each
  mode are described.

  CHARACTER DISPLAY MODE

    In the character display mode, the 6566/6567 fetches CHARACTER POINTERs
  from the VIDEO MATRIX area of memory and translates the pointers to
  character dot location addresses in the 2048 byte CHARACTER BASE area of
  memory. The video matrix is comprised of 1000 consecutive locations in
  memory which each contain an eight-bit character pointer. The location of
  the video matrix within memory is defined by VM13-VM10 in register 24
  ($18) which are used as the 4 MSB of the video matrix address. The lower
  order 10 bits are provided by an internal counter (VC9-VC0) which steps
  through the 1000 character locations. Note that the 6566/6567 provides 14
  address outputs; therefore, additional system hardware may be required
  for complete system memory decodes.

                          CHARACTER POINTER ADDRESS

     A13| A12| A11| A10| A09| A08| A07| A06| A05| A04| A03| A02| A01| A00
  ------+----+----+----+----+----+----+----+----+----+----+----+----+------
    VM13|VM12|VM11|VM10| VC9| VC8| VC7| VC6| VC5| VC4| VC3| VC2| VC1| VC0

  436   APPENDIX N

    The eight-bit character pointer permits up to 256 different character
  definitions to be available simultaneously. Each character is an 8*8 dot
  matrix stored in the character base as eight consecutive bytes. The loca-
  tion of the character base is defined by CB13-CB11 also in register 24
  ($18) which are used for the 3 most significant bits (MSB) of the char-
  acter base address. The 11 lower order addresses are formed by the 8-bit
  character pointer from the video matrix (D7-D0) which selects a
  particular character, and a 3-bit raster counter (RC2-RC0) which selects
  one of the eight character bytes. The resulting characters are formatted
  as 25 rows of 40 characters each. In addition to the 8-bit character
  pointer, a 4-bit COLOR NYBBLE is associated with each video matrix
  location (the video matrix memory must be 12 bits wide) which defines one
  of sixteen colors for each character.

                           CHARACTER DATA ADDRESS

     A13| A12| A11| A10| A09| A08| A07| A06| A05| A04| A03| A02| A01| A00
  ------+----+----+----+----+----+----+----+----+----+----+----+----+------
    CB13|CB12|CB11| D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | RC2| RC1| RC0

  STANDARD CHARACTER MODE (MCM = BMM = ECM = 0)

    In the standard character mode, the 8 sequential bytes from the
  character base are displayed directly on the 8 lines in each character
  region. A "0" bit causes the background #0 color (from register 33 ($21))
  to be displayed while the color selected by the color nybble (foreground)
  is displayed for a "1" bit (see Color Code Table).

                | CHARACTER |
     FUNCTION   |    BIT    |               COLOR DISPLAYED
  --------------+-----------+----------------------------------------------
    Background  |     0     |  Background #0 color
                |           |  (register 33 ($21)
    Foreground  |     1     |  Color selected by 4-bit color nybble

    Therefore, each character has a unique color determined by the 4-bit
  color nybble (1 of 16) and all characters share the common background
  color.

                                                           APPENDIX N   437

  MULTI-COLOR CHARACTER MODE (MCM = 1, BMM = ECM = 0 )

    Multi-color mode provides additional color flexibility allowing up to
  four colors within each character but with reduced resolution. The multi-
  color mode is selected by setting the MCM bit in register 22 ($16) to
  "1," which causes the dot data stored in the character base to be
  interpreted in a different manner. If the MSB of the color nybble is a
  "0," the character will be displayed as described in standard character
  mode, allowing the two modes to be inter-mixed (however, only the lower
  order 8 colors are available). When the MSB of the color nybble is a "1"
  (if MCM:MSB(CM) = 1) the character bits are interpreted in the multi-
  color mode:

                | CHARACTER  |
     FUNCTION   |  BIT PAIR  |               COLOR DISPLAYED
  --------------+------------+---------------------------------------------
    Background  |     00     |  Background #0 Color
                |            |  (register 33 ($21))
    Background  |     01     |  Background #1 Color
                |            |  (register 34 ($22)
    Foreground  |     10     |  Background #2 Color
                |            |  (register 35 ($23)
    Foreground  |     11     |  Color specified by 3 LSB
                |            |  of color nybble

  Since two bits are required to specify one dot color, the character is
  now displayed as a 4*8 matrix with each dot twice the horizontal size as
  in standard mode. Note, however, that each character region can now
  contain 4 different colors, two as foreground and two as background (see
  MOB priority).

  EXTENDED COLOR MODE (ECM = 1, Bmm = MCM = 0)

    The extended color mode allows the selection of individual, background
  colors for each character region with the normal 8*8 character
  resolution. This mode is selected by setting the ECM bit of register 17
  ($11) to "1". The character dot data is displayed as in the standard mode
  (foreground color determined by the color nybble is displayed for a "1"

  438   APPENDIX N

  data bit), but the 2 MSB of the character pointer are used to select the
  background color for each character region as follows:

       CHAR. POINTER  |
        MS BIT PAIR   |       BACKGROUND COLOR DISPLAYED FOR 0 BIT
  --------------------+----------------------------------------------------
           00         |  Background #0 color (register 33 ($21))
           01         |  Background #l color (register 34 ($22))
           10         |  Background #2 color (register 35 ($23))
           11         |  Background #3 color (register 36 ($24))

  Since the two MSB of the character pointers are used for color informa-
  tion, only 64 different character definitions are available. The 6566/
  6567 will force CB10 and CB9 to "0" regardless of the original pointer
  values, so that only the first 64 character definitions will be accessed.
  With extended color mode each character has one of sixteen individually
  defined foreground colors and one of the four available background
  colors.

  +-----------------------------------------------------------------------+
  | NOTE: Extended color mode and multi-color mode should not be enabled  |
  | simultaneously.                                                       |
  +-----------------------------------------------------------------------+

  BIT MAP MODE

    In bit map mode, the 6566/6567 fetches data from memory in a different
  fashion, so that a one-to-one correspondence exists between each
  displayed dot and a memory bit. The bit map mode provides a screen
  resolution of 320H * 200V individually controlled display dots. Bit map
  mode is selected by setting the BMM bit in register 17 ($11) to a "1".
  The VIDEO MATRIX is still accessed as in character mode, but the video
  matrix data is no longer interpreted as character pointers, but rather as
  color data. The VIDEO MATRIX COUNTER is then also used as an address to
  fetch the dot data for display from the 8000-byte DISPLAY BASE. The
  display base address is formed as follows:

     A13| A12| A11| A10| A09| A08| A07| A06| A05| A04| A03| A02| A01| A00
  ------+----+----+----+----+----+----+----+----+----+----+----+----+------
    CB13| VC9| VC8| VC7| VC6| VC5| VC4| VC3| VC2| VC1| VC0| RC2| RC1| RC0

                                                           APPENDIX N   439

  VCx denotes the video matrix counter outputs, RCx denotes the 3-bit
  raster line counter and CB13 is from register 24 ($18). The video matrix
  counter steps through the same 40 locations for eight raster lines, con-
  tinuing to the next 40 locations every eighth line, while the raster
  counter increments once for each horizontal video line (raster line).
  This addressing results in each eight sequential memory locations being
  formatted as an 8*8 dot block on the video display.

  STANDARD BIT MAP MODE (BMM =1, MCM = 0)

    When standard bit map mode is in use, the color information is derived
  only from the data stored in the video matrix (the color nybble is
  disregarded). The 8 bits are divided into two 4-bit nybbles which allow
  two colors to be independently selected in each 8*8 dot block. When a bit
  in the display memory is a "0" the color of the output dot is set by the
  least significant (lower) nybble (LSN). Similarly, a display memory bit
  of "1" selects the output color determined by the MSN (upper nybble).

      BIT    |            DISPLAY COLOR
  -----------+-------------------------------------------------------------
       0     |   Lower nybble of video matrix pointer
       1     |   Upper nybble of video matrix pointer

  MULTI-COLOR BIT MAP MODE (BMM = MCM = 1)

    Multi-colored bit map mode is selected by setting the MCM bit in
  register 22 ($16) to a "1" in conjunction with the BMM bit. Multi-color
  mode uses the same memory access sequences as standard bit map mode, but
  interprets the dot data as follows:

        BIT PAIR      |                   DISPLAY COLOR
  --------------------+----------------------------------------------------
           00         |  Background #0 color (register 33 ($21))
           01         |  Upper nybble of video matrix pointer
           10         |  Lower nybble of video matrix pointer
           11         |  Video matrix color nybble

  Note that the color nybble (DB11-DB8) IS used for the multi-color bit map
  mode. Again, as two bits are used to select one dot color, the horizontal

  440   APPENDIX N

  dot size is doubled, resulting in a screen resolution of 160H*200V.
  Utilizing multi-color bit map mode, three independently selected colors
  can be displayed in each 8*8 block in addition to the background color.

  MOVABLE OBJECT BLOCKS

    The movable object block (MOB) is a special type of character which can
  be displayed at any one position on the screen without the block
  constraints inherent in character and bit map mode. Up to 8 unique MOBs
  can be displayed simultaneously, each defined by 63 bytes in memory which
  are displayed as a 24*21 dot array (shown below). A number of special
  features make MOBs especially suited for video graphics and game
  applications.

                              MOB DISPLAY BLOCK
                        +--------+--------+--------+
                        |  BYTE  |  BYTE  |  BYTE  |
                        +--------+--------+--------+
                        |   00   |   01   |   02   |
                        |   03   |   04   |   05   |
                        |    .   |    .   |    .   |
                        |    .   |    .   |    .   |
                        |    .   |    .   |    .   |
                        |   57   |   58   |   59   |
                        |   60   |   61   |   62   |
                        +--------+--------+--------+

  ENABLE

    Each MOB can be selectively enabled for display by setting its corre-
  sponding enable bit (MnE) to "1" in register 21 ($15). If the MnE bit is
  "0," no MOB operations will occur involving the disabled MOB.

  POSlTlON

    Each MOB is positioned via its X and Y position register (see register
  map) with a resolution of 512 horizontal and 256 vertical positions. The

                                                           APPENDIX N   441

  position of a MOB is determined by the upper-left corner of the array. X
  locations 23 to 347 ($17-$157) and Y locations 50 to 249 ($32-$F9) are
  visible. Since not all available MOB positions are entirely visible on
  the screen, MOBs may be moved smoothly on and off the display screen.

  COLOR

    Each MOB has a separate 4-bit register to determine the MOB color. The
  two MOB color modes are:

  STANDARD MOB (MnMC = 0)

    In the standard mode, a "0" bit of MOB data allows any background data
  to show through (transparent) and a "1" bit is displayed as the MOB color
  determined by the corresponding MOB Color register.

  MULTI-COLOR MOB (MnMC = 1)

    Each MOB can be individually selected as a multi-color MOB via MnMC
  bits in the MOB Multi-color register 28 ($1C). When the MnMC bit is "1",
  the corresponding MOB is displayed in the multi-color mode. In the multi-
  color mode, the MOB data is interpreted in pairs (similar to the other
  multi-color modes) as follows:

        BIT PAIR      |                   COLOR DISPLAYED
  --------------------+----------------------------------------------------
           00         |  Transparent
           01         |  MOB Multi-color #0 (register 37 ($25))
           10         |  MOB Color (registers 39-46 ($27-$2E))
           11         |  MOB Multi-color #1 (register 38 ($26))

  Since two bits of data are required for each color, the resolution of the
  MOB is reduced to 12X21, with each horizontal dot expanded to twice
  standard size so that the overall MOB size does not change. Note that up
  to 3 colors can be displayed in each MOB (in addition to transparent) but
  that two of the colors are shared among all the MOBs in the multi-color
  mode.

  442   APPENDIX N

  MAGNIFICATION

    Each MOB can be selectively expanded (2X) in both the horizontal and
  vertical directions. Two registers contain the control bits (MnXE,MnYE)
  for the magnification control.

    REGISTER  |                        FUNCTION
  ------------+------------------------------------------------------------
     23 ($17) | Horizontal expand MnXE-"1"=expand; "0"=normal
     29 ($1D) | Vertical expand MnYE-"1"=expand; "0"=normal

  When MOBs are expanded, no increase in resolution is realized. The same
  24*21 array (12X21 if multi-colored) is displayed, but the overall MOB
  dimension is doubled in the desired direction (the smallest MOB dot may
  be up to 4X standard dot dimension if a MOB is both multi-colored and
  expanded).

  PRIORITY

    The priority of each MOB may be individually controlled with respect to
  the other displayed information from character or bit map modes. The
  priority of each MOB is set by the corresponding bit (MnDP) of register
  27 ($1B) as follows:

     REG BIT  |          PRIORITY TO CHARACTER OR BIT MAP DATA
  ------------+------------------------------------------------------------
        0     |  Non-transparent MOB data will be displayed (MOB in front)
        1     |  Non-transparent MOB data will be displayed only instead of
              |  Bkgd #0 or multi-color bit pair 01 (MOB behind)

                          MOB-DISPLAY DATA PRIORITY
                       +--------------+--------------+
                       |   MnDP = 1   |   MnDP = 0   |
                       +--------------+--------------+
                       |  MOBn        |  Foreground  |
                       |  Foreground  |  MOBn        |
                       |  Background  |  Background  |
                       +--------------+--------------+

                                                           APPENDIX N   443

  MOB data bits of "0" ("00" in multi-color mode) are transparent, always
  permitting any other information to be displayed.
    The MOBs have a fixed priority with respect to each other, with MOB 0
  having the highest priority and MOB 7 the lowest. When MOB data (except
  transparent data) of two MOBs are coincident, the data from the lower
  number MOB will be displayed. MOB vs. MOB data is prioritized before
  priority resolution with character or bit map data.

  COLLISION DETECTION

    Two types of MOB collision (coincidence) are detected, MOB to MOB
  collision and MOB to display data collision:

    1) A collision between two MOBs occurs when non-transparent output data
       of two MOBs are coincident. Coincidence of MOB transparent areas
       will not generate a collision. When a collision occurs, the MOB bits
       (MnM) in the MOB-MOB COLLISION register 30 ($1E) will be set to "1"
       for both colliding MOBS. As a collision between two (or more) MOBs
       occurs, the MOB-MOB collision bit for each collided MOB will be set.
       The collision bits remain set until a read of the collision
       register, when all bits are automatically cleared. MOBs collisions
       are detected even if positioned off-screen.
    2) The second type of collision is a MOB-DATA collision between a MOB
       and foreground display data from the character or bit map modes. The
       MOB-DATA COLLISION register 31 ($1F) has a 'bit (MnD) for each MOB
       which is set to "1" when both the MOB and non-background display
       data are coincident. Again, the coincidence of only transparent data
       does not generate a collision. For special applications, the display
       data from the 0-1 multicolor bit pair also does not cause a
       collision. This feature permits their use as background display data
       without interfering with true MOB collisions. A MOB-DATA collision
       can occur off-screen in the horizontal direction if actual display
       data has been scrolled to an off-screen position (see scrolling).
       The MOB-DATA COLLISION register also automatically clears when read.

  444   APPENDIX N

    The collision interrupt latches are set whenever the first bit of
   either register is set to "1". Once any collision bit within a register
   is set high, subsequent collisions will not set the interrupt latch
   until that collision register has been cleared to all "0s" by a read.

  MOB MEMORY ACCESS

    The data for each MOB is Stored in 63 consecutive bytes of memory. Each
  block of MOB data is defined by a MOB pointer, located at the end of the
  VIDEO MATRIX. Only 1000 bytes of the video matrix are used in the normal
  display modes, allowing the video matrix locations 1016-1023 (VM base+
  $3F8 to VM base+$3FF) to be used for MOB pointers 0-7, respectively. The
  eight-bit MOB pointer from the video matrix together with the six bits
  from the MOB byte counter (to address 63 bytes) define the entire 14-bit
  address field:

     A13| A12| A11| A10| A09| A08| A07| A06| A05| A04| A03| A02| A01| A00
  ------+----+----+----+----+----+----+----+----+----+----+----+----+------
     MP7| MP6| MP5| MP4| MP3| MP2| MP1| MP0| MC5| MC4| MC3| MC2| MC1| MC0

  Where MPx are the MOB pointer bits from the video matrix and MCx are the
  internally generated MOB counter bits. The MOB pointers are read from the
  video matrix at the end of every raster line. When the Y position
  register of a MOB matches the current raster line count, the actual
  fetches of MOB data begin. Internal counters automatically step through
  the 63 bytes of MOB data, displaying three bytes on each raster line.

  OTHER FEATURES

  SCREEN BLANKING

    The display screen may be blanked by setting the DEN bit in register
  17 ($11) to a "0". When the screen is blanked, the entire screen will be
  filled with the exterior color as set in register 32 ($20). When blanking
  is active, only transparent (Phase 1) memory accesses are required, per-
  mitting full processor utilization of the system bus. MOB data, however,
  will be accessed if the MOBs are not also disabled. The DEN bit must be
  set to "1" for normal video display.

                                                           APPENDIX N   445

  ROW/COLUMN SELECT

    The normal display consists of 25 rows of 40 characters (or character
  regions) per row. For special display purposes, the display window may be
  reduced to 24 rows and 38 characters. There is no change in the format of
  the displayed information, except that characters (bits) adjacent to the
  exterior border area will now be covered by the border. The select bits
  operate as follows:

    RSEL |      NUMBER OF ROWS        |  CSEL |     NUMBER OF COLUMNS
  -------+----------------------------+-------+----------------------------
     0   |          24 rows           |   0   |         38 columns
     1   |          25 rows           |   1   |         40 columns

  The RSEL bit is in register 17 ($11) and the CSEL bit is in register 22
  ($16). For standard display the larger display window is normally used,
  while the smaller display window is normally used in conjunction with
  scrolling.

  SCROLLING

    The display data may be scrolled up to one entire character space in
  both the horizontal and vertical direction. When used in conjunction with
  the smaller display window (above), scrolling can be used to create a
  smooth panning motion of display data while updating the system memory
  only when a new character row (or column) is required. Scrolling is also
  used to center a fixed display within the display window.

           BITS         |      REGISTER      |          FUNCTION
  ----------------------+--------------------+-----------------------------
         X2,X1,X0       |      22 ($16)      |     Horizontal Position
         Y2,Y1,Y0       |      17 ($11)      |     Vertical Position

  LIGHT PEN

    The light pen input latches the current screen position into a pair of
  registers (LPX,LPY) on a low-going edge. The X position register 19 ($13)
  will contain the 8 MSB of the X position at the time of transition. Since
  the X position is defined by a 512-state counter (9 bits) resolution to 2
  horizontal dots is provided. Similarly, the Y position is latched to its

  446   APPENDIX N

  register 20 ($14) but here 8 bits provide single raster resolution within
  the visible display. The light pen latch may be triggered only once per
  frame, and subsequent triggers within the same frame will have no effect.
  Therefore, you must take several samples before turning the light pen to
  the screen (3 or more samples, average), depending upon the
  characteristics of your light pen.

  RASTER REGISTER

    The raster register is a dual-function register. A read of the raster
  register 18 ($12) returns the lower 8 bits of the current raster position
  (the MSB-RC8 is located in register 17 ($11)). The raster register can be
  interrogated to implement display changes outside the visible area to
  prevent display flicker. The visible display window is from raster 51
  through raster 251 ($033-$0FB). A write to the raster bits (including
  RC8) is latched for use in an internal raster compare. When the current
  raster matches the written value, the raster interrupt latch is set.

  INTERRUPT REGISTER

    The interrupt register shows the status of the four sources of
  interrupt. An interrupt latch in register 25 ($19) is set to "1" when an
  interrupt source has generated an interrupt request. The four sources of
  interrupt are:

   LATCH |ENABLE|
    BIT  | BIT  |                       WHEN SET
  -------+------+----------------------------------------------------------
    IRST | ERST | Set when (raster count) = (stored raster count)
    IMDC | EMDC | Set by MOB-DATA collision register (first collision only)
    IMMC | EMMC | Set by MOB-MOB collision register (first collision only)
    ILP  | ELP  | Set by negative transition of LP input (once per frame)
    IRQ  |      | Set high by latch set and enabled (invert of /IRQ output)

    To enable an interrupt request to set the /IRQ output to "0", the
  corresponding interrupt enable bit in register 26 ($1A) must be set to
  "1". Once an interrupt latch has been set, the latch may be cleared only
  by writing a "1" to the desired latch in the interrupt register. This
  feature allows selective handling of video interrupts without software
  required to "remember" active interrupts.

                                                           APPENDIX N   447

  DYNAMIC RAM REFRESH

    A dynamic ram refresh controller is built in to the 6566/6567 devices.
  Five 8-bit row addresses are refreshed every raster line. This rate
  guarantees a maximum delay of 2.02 ms between the refresh of any single
  row address in a 128 refresh scheme. (The maximum delay is 3.66 ms in a
  256 address refresh scheme.) This refresh is totally transparent to the
  system, since the refresh occurs during Phase 1 of the system clock. The
  6567 generates both /RAS and /CAS which are normally connected directly
  to the dynamic rams. /RAS and /CAS are generated for every Phase 2 and
  every video data access (including refresh) so that external clock
  generation is not required.

  RESET

  THEORY OF OPERATION

  SYSTEM INTERFACE

    The 6566/6567 video controller devices interact with the system data
  bus in a special way. A 65XX system requires the system buses only during
  the Phase 2 (clock high) portion of the cycle. The 6566/6567 devices take
  advantage of this feature by normally accessing system memory during the
  Phase 1 (clock low) portion of the clock cycle. Therefore, operations
  such as character data fetches and memory refresh are totally transparent
  to the processor and do not reduce the processor throughput. The video
  chips provide the interface control signals required to maintain this bus
  sharing.
    The video devices provide the signal AEC (address enable control) which
  is used to disable the processor address bus drivers allowing the video
  device to access the address bus. AEC is active low which, permits direct
  connection to the AEC input of the 65XX family. The AEC signal is

  448   APPENDIX N

  normally activated during Phase 1 so that processor operation is not
  affected. Because of this bus "sharing", all memory accesses must be
  completed in 1/2 cycle. Since the video chips provide a 1-MHz clock
  (which must be used as system Phase 2), a memory cycle is 500 ns
  including address setup, data access and, data setup to the reading
  device.
    Certain operations of the 6566/6567 require data at a faster rate than
  available by reading only during the Phase 1 time; specifically, the ac-
  cess of character pointers from the video matrix and the fetch of MOB
  data. Therefore, the processor must be disabled and the data accessed
  during the Phase 2 clock. This is accomplished via the BA (bus available)
  signal. The BA line is normally high but is brought low during Phase 1 to
  indicate that the video chip will require a Phase 2 data access. Three
  Phase-2 times are allowed after BA low for the processor to complete any
  current memory accesses. On the fourth Phase 2 after BA low, the AEC
  signal will remain low during Phase 2 as the video chip fetches data. The
  BA line is normally connected to the RDY input of a 65XX processor. The
  character pointer fetches occur every eighth raster line during the
  display window and require 40 consecutive Phase 2 accesses to fetch the
  video matrix pointers. The MOB data fetches require 4 memory accesses as
  follows:

    PHASE |     DATA    |                    CONDITION
  --------+-------------+--------------------------------------------------
      1   | MOB Pointer |  Every raster
      2   | MOB Byte 1  |  Each raster while MOB is displayed
      1   | MOB Byte 2  |  Each raster while MOB is displayed
      2   | MOB Byte 3  |  Each raster while MOB is displayed

  The MOB pointers are fetched every other Phase 1 at the end of each
  raster line. As required, the additional cycles are used for MOB data
  fetches. Again, all necessary bus control is provided by the 6566/6567
  devices.

  MEMORY INTERFACE

    The two versions of the video interface chip, 6566 and 6567, differ in
  address output configurations. The 6566 has thirteen fully decoded

                                                           APPENDIX N   449

  addresses for direct connection to the system address bus. The 6567 has
  multiplexed addresses for direct connection to 64K dynamic RAMS. The
  least significant address bits, A06-A00, are present on A06-A00 while
  /RAS is brought low, while the most significant bits, A13-A08, are pres-
  ent on A05-A00 while /CAS is brought low. The pins A11-A07 on the 6567
  are static address outputs to allow direct connection of these bits to a
  conventional 16K (2K*8) ROM. (The lower order addresses require external
  latching.)

  PROCESSOR INTERFACE

    Aside from the special memory accesses described above, the 6566/6567
  registers can be accessed similar to any other peripheral device. The
  following processor interface signals are provided:

  DATA BUS (DB7-DB0)

    The eight data bus pins are the bidirectional data port, controlled by
  /CS, RW, and Phase 0. The data bus can only be accessed while AEC and
  Phase 0 are high and /CS is low.

  CHIP SELECT (/CS)

    The chip select pin, /CS, is brought low to enable access to the device
  registers in conjunction with the address and RW pins. /CS low is recog-
  nized only while AEC and Phase 0 are high.

  READ/WRITE (R/W)

    The read/write input, R/W, is used to determine the direction of data
  transfer on the data bus, in conjunction with /CS. When R/W is high ("1")
  data is transferred from the selected register to the data bus output.
  When R/W is low ("0") data presented on the data bus pins is loaded into
  the selected register.

  ADDRESS BUS (A05-A00)

    The lower six address pins, A5-A0, are bidirectional. During a pro-
  cessor read or write of the video device, these address pins are inputs.
  The data on the address inputs selects the register for read or write as
  defined in the register map.

  450   APPENDIX N

  CLOCK OUT (PH0)

    The clock output, Phase 0, is the 1-MHz clock used as the 65XX pro-
  cessor Phase 0 in. All system bus activity is referenced to this clock.
  The clock frequency is generated by dividing the 8-MHz video input clock
  by eight.

  INTERRUPTS (/IRQ)

    The interrupt output, /IRQ, is brought low when an enabled source of
  interrupt occurs within the device. The /IRQ output is open drain,
  requiring an external pull-up resistor.

  VIDEO INTERFACE

    The video output signal from the 6566/6567 consists of two signals
  which must be externally mixed together. SYNC/LUM output contains all the
  video data, including horizontal and vertical syncs, as well as the
  luminance information of the video display. SYNC/LUM is open drain,
  requiring an external pull-up of 500 ohms. The COLOR output contains all
  the chrominance information, including the color reference burst and the
  color of all display data. The COLOR output is open source and should be
  terminated with 1000 ohms to ground. After appropriate mixing of these
  two signals, the resulting signal can directly drive a video monitor or
  be fed to a modulator for use with a standard television.

                      SUMMARY OF 6566/6567 BUS ACTIVITY
  +-----+-----+-----+-----+-----------------------------------------------+
  | AEC | PH0 | /CS | R/W |                    ACTION                     |
  +-----+-----+-----+-----+-----------------------------------------------+
  |  0  |  0  |  X  |  X  |  PHASE 1 FETCH, REFRESH                       |
  |  0  |  1  |  X  |  X  |  PHASE 2 FETCH (PROCESSOR OFF)                |
  |  1  |  0  |  X  |  X  |  NO ACTION                                    |
  |  1  |  1  |  0  |  0  |  WRITE TO SELECTED REGISTER                   |
  |  1  |  1  |  0  |  1  |  READ FROM SELECTED REGISTER                  |
  |  1  |  1  |  1  |  X  |  NO ACTION                                    |
  +-----+-----+-----+-----+-----------------------------------------------+

                                                           APPENDIX N   451

                              PIN CONFIGURATION

                                +----+ +----+
                        D6   1 @|    +-+    |@ 40  Vcc
                                |           |
                        D5   2 @|           |@ 39  D7
                                |           |
                        D4   3 @|           |@ 38  D8
                                |           |
                        D3   4 @|           |@ 37  D9
                                |           |
                        D2   5 @|           |@ 36  D10
                                |           |
                        D1   6 @|           |@ 35  D11
                                |           |
                        D0   7 @|           |@ 34  A10
                                |           |
                      /IRQ   8 @|           |@ 33  A9
                                |           |
                        LP   9 @|           |@ 32  A8
                                |           |
                       /CS  10 @|           |@ 31  A7
                                |    6567   |
                       R/W  11 @|           |@ 30  A6("1")
                                |           |
                        BA  12 @|           |@ 29  A5(A13)
                                |           |
                       Vdd  13 @|           |@ 28  A4(A12)
                                |           |
                     COLOR  14 @|           |@ 27  A3(A11)
                                |           |
                     S/LUM  15 @|           |@ 26  A2(A10)
                                |           |
                       AEC  16 @|           |@ 25  A1(A9)
                                |           |
                       PH0  17 @|           |@ 24  A0(A8)
                                |           |
                      /RAS  18 @|           |@ 23  A11
                                |           |
                      /CAS  19 @|           |@ 22  PHIN
                                |           |
                       Vss  20 @|           |@ 21  PHCL
                                +-----------+
  452   APPENDIX N  (Multiplexed addresses in parentheses)

                              PIN CONFIGURATION

                                +----+ +----+
                        D6   1 @|    +-+    |@ 40  Vcc
                                |           |
                        D5   2 @|           |@ 39  D7
                                |           |
                        D4   3 @|           |@ 38  D8
                                |           |
                        D3   4 @|           |@ 37  D9
                                |           |
                        D2   5 @|           |@ 36  D10
                                |           |
                        D1   6 @|           |@ 35  D11
                                |           |
                        D0   7 @|           |@ 34  A13
                                |           |
                      /IRQ   8 @|           |@ 33  A12
                                |           |
                        LP   9 @|           |@ 32  A11
                                |           |
                       /CS  10 @|           |@ 31  A10
                                |    6567   |
                       R/W  11 @|           |@ 30  A9
                                |           |
                        BA  12 @|           |@ 29  A8
                                |           |
                       Vdd  13 @|           |@ 28  A7
                                |           |
                     COLOR  14 @|           |@ 27  A6
                                |           |
                     S/LUM  15 @|           |@ 26  A5
                                |           |
                       AEC  16 @|           |@ 25  A4
                                |           |
                       PH0  17 @|           |@ 24  A3
                                |           |
                      PHIN  18 @|           |@ 23  A2
                                |           |
                     PHCOL  19 @|           |@ 22  A1
                                |           |
                       Vss  20 @|           |@ 21  A0
                                +-----------+
                                                           APPENDIX N   453

                                REGISTER MAP
  +----------+------------------------------------------------------------+
  | 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 M1Xl 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 M7Xl M7X0  MOB 7 X-position  |
  | 15 ($0F) | M7Y7 M7Y6 M7Y5 M7Y4 M7Y3 M7Y2 M7Y1 M6Y0  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      |

  454   APPENDIX N

  | 24 ($18) | VM13 VM12 VM11 VM10 CB13 CB12 CB11  -    Memory Pointers   |
  | 25 ($19) | IRQ   -    -    -   ILP  IMMC IMBC IRST  Interrupt Register|
  | 26 ($1A) |  -    -    -    -   ELP  EMMC EMBC ERST  Enable Interrupt  |
  | 27 ($1B) | M7DP M6DP M5DP M4DP M3DP M2DP M1DP M0DP  MOB-DATA Priority |
  | 28 ($1C) | M7MC M6MC M5MC M4MC M3MC M2MC M1MC M0MC  MOB Multicolor Sel|
  | 29 ($1D) | M7XE M6XE M5XE M4XE M3XE M2XE M1XE M0XE  MOB X-expand      |
  | 30 ($1E) | M7M  M6M  M5M  M4M  M3M  M2M  M1M  M0M   MOB-MOB Collision |
  | 31 ($1F) | M7D  M6D  M5D  M4D  M3D  M2D  M1D  M0D   MOB-DATA Collision|
  | 32 ($20) |  -    -    -    -   EC3  EC2  EC1  EC0   Exterior Color    |
  | 33 ($21) |  -    -    -    -   B0C3 B0C2 B0C1 B0C0  Bkgd #0 Color     |
  | 34 ($22) |  -    -    -    -   B1C3 B1C2 B1C1 B1C0  Bkgd #1 Color     |
  | 35 ($23) |  -    -    -    -   B2C3 B2C2 B2C1 B2C0  Bkgd #2 Color     |
  | 36 ($24) |  -    -    -    -   B3C3 B3C2 B3C1 B3C0  Bkgd #3 Color     |
  | 37 ($25) |  -    -    -    -   MM03 MM02 MM01 MM00  MOB Multicolor #0 |
  | 38 ($26) |  -    -    -    -   MM13 MM12 MM11 MM10  MOB Multicolor #1 |
  | 39 ($27) |  -    -    -    -   M0C3 M0C2 M0C1 M0C0  MOB 0 Color       |
  | 40 ($28) |  -    -    -    -   M1C3 M1C2 M1C1 M1C0  MOB 1 Color       |
  | 41 ($29) |  -    -    -    -   M2C3 M2C2 M2C1 M2C0  MOB 2 Color       |
  | 42 ($2A) |  -    -    -    -   M3C3 M3C2 M3C1 M3C0  MOB 3 Color       |
  | 43 ($2B) |  -    -    -    -   M4C3 M4C2 M4C1 M4C0  MOB 4 Color       |
  | 44 ($2C) |  -    -    -    -   M5C3 M5C2 M5C1 M5C0  MOB 5 Color       |
  | 45 ($2D) |  -    -    -    -   M6C3 M6C2 M6C1 M6C0  MOB 6 Color       |
  | 46 ($2E) |  -    -    -    -   M7C3 M7C2 M7C1 M7C0  MOB 7 Color       |
  +----------+------------------------------------------------------------+

  +-----------------------------------------------------------------------+
  | NOTE: A dash indicates a no connect. All no connects are read as a    |
  | "1"                                                                   |
  +-----------------------------------------------------------------------+

                                                           APPENDIX N   455

                                 COLOR CODES
  +--------+--------+--------+--------+--------+--------+-----------------+
  |   D3   |   D2   |   D1   |   D0   |   HEX  |   DEC  |      COLOR      |
  +--------+--------+--------+--------+--------+--------+-----------------+
  |    0   |    0   |    0   |    0   |    0   |    0   |    BLACK        |
  |    0   |    0   |    0   |    1   |    1   |    1   |    WHITE        |
  |    0   |    0   |    1   |    0   |    2   |    2   |    RED          |
  |    0   |    0   |    1   |    1   |    3   |    3   |    CYAN         |
  |    0   |    1   |    0   |    0   |    4   |    4   |    PURPLE       |
  |    0   |    1   |    0   |    1   |    5   |    5   |    GREEN        |
  |    0   |    1   |    1   |    0   |    6   |    6   |    BLUE         |
  |    0   |    1   |    1   |    1   |    7   |    7   |    YELLOW       |
  |    1   |    0   |    0   |    0   |    8   |    8   |    ORANGE       |
  |    1   |    0   |    0   |    1   |    9   |    9   |    BROWN        |
  |    1   |    0   |    1   |    0   |    A   |   10   |    LT RED       |
  |    1   |    0   |    1   |    1   |    B   |   11   |    DARK GREY    |
  |    1   |    1   |    0   |    0   |    C   |   12   |    MED GREY     |
  |    1   |    1   |    0   |    1   |    0   |   13   |    LT GREEN     |
  |    1   |    1   |    1   |    0   |    E   |   14   |    LT BLUE      |
  |    1   |    1   |    1   |    1   |    F   |   15   |    LT GREY      |
  +--------+--------+--------+--------+--------+--------+-----------------+

  456   APPENDIX N

  APPENDIX O

  6581 SOUND INTERFACE DEVICE (SID)
  CHIP SPECIFICATIONS

  CONCEPT

    The 6581 Sound Interface Device (SID) is a single-chip, 3-voice elec-
  tronic music synthesizer/sound effects generator compatible with the 65XX
  and similar microprocessor families. SID provides wide-range, high-
  resolution control of pitch (frequency), tone color (harmonic content),
  and dynamics (volume). Specialized control circuitry minimizes software
  overhead, facilitating use in arcade/home video games and low-cost
  musical instruments.

  FEATURES

  o 3 TONE OSCILLATORS
        Range: 0-4 kHz
  o 4 WAVEFORMS PER OSCILLATOR
        Triangle, Sawtooth,
        Variable Pulse, Noise
  o 3 AMPLITUDE MODULATORS
        Range: 48 dB
  o 3 ENVELOPE GENERATORS
        Exponential response
        Attack Rate: 2 ms-8 s
        Decay Rate: 6 ms-24 s
        Sustain Level: 0-peak volume
        Release Rate: 6 ms-24 s
  o OSCILLATOR SYNCHRONIZATION
  o RING MODULATION
  o PROGRAMMABLE FILTER
        Cutoff range: 30 Hz-12 kHz
        12 dB/octave Rolloff
        Low pass, Bandpass,
        High pass, Notch outputs
        Variable Resonance

                                                           APPENDIX O   457

  o MASTER VOLUME CONTROL
  o 2 A/D POT INTERFACES
  o RANDOM NUMBER/MODULATION GENERATOR
  o EXTERNAL AUDIO INPUT

                             PIN CONFIGURATION

                                +----+ +----+
                     CAP1A   1 @|    +-+    |@ 28  Vdd
                                |           |
                     CAP1B   2 @|           |@ 27  AUDIO OUT
                                |           |
                     CAP2A   3 @|           |@ 26  EXT IN
                                |           |
                     CAP2B   4 @|           |@ 25  Vcc
                                |           |
                      /RES   5 @|           |@ 24  POT X
                                |           |
                        02   6 @|           |@ 23  POT Y
                                |           |
                       R/W   7 @|           |@ 22  D7
                                |    6581   |
                       /CS   8 @|    SID    |@ 21  D6
                                |           |
                        A0   9 @|           |@ 20  D5
                                |           |
                        A1  10 @|           |@ 19  D4
                                |           |
                        A2  11 @|           |@ 18  D3
                                |           |
                        A3  12 @|           |@ 17  D2
                                |           |
                        A4  13 @|           |@ 16  D1
                                |           |
                       GND  14 @|           |@ 15  D0
                                +-----------+

  458   APPENDIX O

                          [THE PICTURE IS MISSING!]

                             6581 BLOCK DIAGRAM

                                                           APPENDIX O   459

  DESCRIPTION

    The 6581 consists of three synthesizer "voices" which can be used
  independently or in conjunction with each other (or external audio
  sources) to create complex sounds. Each voice consists of a Tone
  Oscillator/Waveform Generator, an Envelope Generator and an Amplitude
  Modulator. The Tone Oscillator controls the pitch of the voice over a
  wide range. The Oscillator produces four waveforms at the selected
  frequency, with the unique harmonic content of each waveform providing
  simple control of tone color. The volume dynamics of the oscillator are
  controlled by the Amplitude Modulator under the direction of the Envelope
  Generator. When triggered, the Envelope Generator creates an amplitude
  envelope with programmable rates of increasing and decreasing volume. In
  addition to the three voices, a programmable Filter is provided for
  generating complex, dynamic tone colors via subtractive synthesis.
    SID allows the microprocessor to read the changing output of the third
  Oscillator and third Envelope Generator. These outputs can be used as a
  source of modulation information for creating vibrato, frequency/filter
  sweeps and similar effects. The third oscillator can also act as a random
  number generator for games. Two A/D converters are provided for inter-
  facing SID with potentiometers. These can be used for "paddles" in a
  game environment or as front panel controls in a music synthesizer. SID
  can process external audio signals, allowing multiple SID chips to be
  daisy-chained or mixed in complex polyphonic systems.

  SID CONTROL REGISTERS

    There are 29 eight-bit registers in SID which control the generation of
  sound. These registers are either WRITE-only or READ-only and are listed
  below in Table 1.

  460   APPENDIX O

                         Table 1. SID Register Map            WO=WRITE-ONLY
                                                              RO=READ-ONLY
    REG#                      DATA
    (HEX) D7    D6    D5    D4    D3    D2    D1    D0   REG NAME       REG
                                                         Voice 1       TYPE
   0 00   F7    F6    F5    F4    F3    F2    F1    F0   FREQ LO         WO
   1 01   F15   F14   F13   F12   F11   F10   F9    F8   FREQ HI         WO
   2 02   PW7   PW6   PW5   PW4   PW3   PW2   PW1   PW0  PW LO           WO
   3 03    -     -     -     -   PW11  PW10   PW9   PW8  PW HI           WO
   4 04  NOISE PULSE  SAW TRIANG TEST  RING  SYNC  GATE  CONTROL REG     WO
   5 05  ATK3  ATK2  ATK1  ATK0  DCY3  DCY2  DCY1  DCY0  ATTACK/DECAY    WO
   6 06  STN3  STN2  STN1  STN0  RLS3  RLS2  RLS1  RLS0  SUSTAIN/RELEASE WO

                                                         Voice 2
   7 07   F7    F6    F5    F4    F3    F2    F1    F0   FREQ LO         WO
   8 08   F15   F14   F13   F12   F11   F10   F9    F8   FREQ HI         WO
   9 09   PW7   PW6   PW5   PW4   PW3   PW2   PW1   PW0  PW LO           WO
  10 0A    -     -     -     -   PW11  PW10   PW9   PW8  PW HI           WO
  11 0B  NOISE PULSE  SAW TRIANG TEST  RING  SYNC  GATE  CONTROL REG     WO
  12 0C  ATK3  ATK2  ATK1  ATK0  DCY3  DCY2  DCY1  DCY0  ATTACK/DECAY    WO
  13 0D  STN3  STN2  STN1  STN0  RLS3  RLS2  RLS1  RLS0  SUSTAIN/RELEASE WO

                                                         Voice 3
  14 0E   F7    F6    F5    F4    F3    F2    F2    F1   FREQ LO         WO
  15 0F   F15   F14   F13   F12   F11   F10   F9    F8   FREQ HI         WO
  16 10   PW7   PW6   PW5   PW4   PW3   PW2   PW1   PW0  PW LO           WO
  17 11    -     -     -     -   PW11  PW10   PW9   PW8  PW HI           WO
  18 12  NOISE PULSE  SAW TRIANG TEST  RING  SYNC  GATE  CONTROL REG     WO
  19 13  ATK3  ATK2  ATK1  ATK0  DCY3  DCY2  DCY1  DCY0  ATTACK/DECAY    WO
  20 14  STN3  STN2  STN1  STN0  RLS3  RLS2  RLS1  RLS0  SUSTAIN/RELEASE WO

                                                         Filter
  21 15    -     -     -     -     -    FC2   FC1   FC0  FC LO           WO
  22 16  FC10   FC9   FC8   FC7   FC6   FC5   FC4   FC3  FC HI           WO
  23 17  RES3  RES2  RES1  RES0 FILTEX FILT3 FILT2 FILT1 RES/FILT        WO
  24 18  3OFF   HP    BP    LP   VOL3  VOL2  VOL1  VOL0  MODE/VOL        WO

                                                         Misc.
  25 19   PX7   PX6   PX5   PX4   PX3   PX2   PX1   PX0  POT X           RO
  26 1A   PY7   PY6   PY5   PY4   PY3   PY2   PY1   PY0  POT Y           RO
  27 1B   O7    O6    O5    O4    O3    O2    O1    O0   OSC3/RANDOM     RO
  28 1C   E7    E6    E5    E4    E3    E2    E1    E0   ENV3            RO

                                                           APPENDIX O   461

  SID REGISTER DESCRIPTION

  VOICE 1

  FREQ LO/FREQ HI (Registers 00,01)

    Together these registers form a 16-bit number which linearly controls
  the frequency of Oscillator 1 . The frequency is determined by the
  following equation:

                       Fout = (Fn*Fclk/16777216) Hz

    Where Fn is the 16-bit number in the Frequency registers and Fclk is
  the system clock applied to the 02 input (pin 6). For a standard 1.0-MHz
  clock, the frequency is given by:

                       Fout = (Fn*0.059604645) Hz

    A complete table of values for generating 8 octaves of the equally
  tempered musical scale with concert A (440 Hz) tuning is provided in
  Appendix E. It should be noted that the frequency resolution of SID is
  sufficient for any tuning scale and allows sweeping from note to note
  (portamento) with no discernable frequency steps.

  PW LO/PW HI (Registers 02,03)

    Together these registers form a 12-bit number (bits 4-7 of PW HI are
  not used) which linearly controls the Pulse Width (duty cycle) of the
  Pulse waveform on Oscillator 1. The pulse width is determined by the
  following equation:

                            PWout = (PWn/40.95) %

  Where PWn is the 12-bit number in the Pulse Width registers.
    The pulse width resolution allows the width to be smoothly swept with
  no discernable stepping. Note that the Pulse waveform on Oscillator 1
  must be selected in order for the Pulse Width registers to have any au-
  dible effect. A value of 0 or 4095 ($FF) in the Pulse Width registers
  will produce a constant DC output, while a value of 2048 ($800) will
  produce a square wave.

  462   APPENDIX O

  CONTROL REGISTER (Register 04)

    This register contains eight control bits which select various options
  on Oscillator 1.
    GATE (Bit 0): The GATE bit controls the Envelope Generator for Voice 1.
  When this bit is set to a one, the Envelope Generator is Gated
  (triggered) and the ATTACK/DECAY/SUSTAIN cycle is initiated. When the bit
  is reset to a zero, the RELEASE cycle begins. The Envelope Generator
  controls the amplitude of Oscillator I appearing at the audio output,
  therefore, the GATE bit must be set (along with suitable envelope pa-
  rameters) for the selected output of Oscillator 1 to be audible. A de-
  tailed discussion of the Envelope Generator can be found at the end of
  this Appendix.
    SYNC (Bit 1): The SYNC bit, when set to a one, synchronizes the
  fundamental frequency of Oscillator 1 with the fundamental frequency of
  Oscillator 3, producing "Hard Sync" effects.
    Varying the frequency of Oscillator 1 with respect to Oscillator 3 pro-
  duces a wide range of complex harmonic structures from Voice I at the
  frequency of Oscillator 3. In order for sync to occur, Oscillator 3 must
  be set to some frequency other than zero but preferably lower than the
  frequency of Oscillator 1. No other parameters of Voice 3 have any effect
  on sync.
    RING MOD (Bit 2): The RING MOD bit, when set to a one, replaces the
  Triangle waveform output of Oscillator 1 with a "Ring Modulated"
  combination of Oscillators 1 and 3. Varying the frequency of Oscillator 1
  with respect to Oscillator 3 produces a wide range of non-harmonic
  overtone structures for creating bell or gong sounds and for special ef-
  fects. In order for ring modulation to be audible, the Triangle waveform
  of Oscillator 1 must be selected and Oscillator 3 must be set to some
  frequency other than zero. No other parameters of Voice 3 have any effect
  on ring modulation.
    TEST (Bit 3): The TEST bit, when set to a one, resets and locks Oscil-
  lator 1 at zero until the TEST bit is cleared. The Noise waveform output
  of Oscillator 1 is also reset and the Pulse waveform output is held at a
  DC level. Normally this bit is used for testing purposes, however, it can
  be used to synchronize Oscillator 1 to external events, allowing the
  generation of highly complex waveforms under real-time software control.

                                                           APPENDIX O   463

    (Bit 4): When set to a one, the Triangle waveform output of Oscillator
  1 is selected. The Triangle waveform is low in harmonics and has a
  mellow, flute-like quality.
    (Bit 5): When set to a one, the Sawtooth waveform output of Oscillator
  1 is selected. The Sawtooth waveform is rich in even and odd harmonics
  and has a bright, brassy quality.
    (Bit 6): When set to a one, the Pulse waveform output of Oscillator 1
  is selected. The harmonic content of this waveform can be adjusted by the
  Pulse Width registers, producing tone qualities ranging from a bright,
  hollow square wave to a nasal, reedy pulse. Sweeping the pulse width in
  real-time produces a dynamic "phasing" effect which adds a sense of
  motion to the sound. Rapidly jumping between different pulse widths can
  produce interesting harmonic sequences.
    NOISE (Bit 7): When set to a one, the Noise output waveform of
  Oscillator 1 is selected. This output is a random signal which changes at
  the frequency of Oscillator 1. The sound quality can be varied from a low
  rumbling to hissing white noise via the Oscillator 1 Frequency registers.
  Noise is useful in creating explosions, gunshots, jet engines, wind, surf
  and other unpitched sounds, as well as snore drums and cymbals. Sweeping
  the oscillator frequency with Noise selected produces a dramatic rushing
  effect.
    One of the output waveforms must be selected for Oscillator 1 to be
  audible, however, it is NOT necessary to de-select waveforms to silence
  the output of Voice 1. The amplitude of Voice 1 at the final output is a
  function of the Envelope Generator only.

  +-----------------------------------------------------------------------+
  | NOTE: The oscillator output waveforms are NOT additive. If more than  |
  | one output waveform is selected simultaneously, the result will be a  |
  | logical ANDing of the waveforms. Although this technique can be used  |
  | to generate additional waveforms beyond the four listed above, it must|
  | be used with care. If any other waveform is selected while Noise is   |
  | on, the Noise output can "lock up " If this occurs, the Noise output  |
  | will remain silent until reset by the TEST bit or by bringing RES     |
  | (pin 5) low.                                                          |
  +-----------------------------------------------------------------------+

  464   APPENDIX O

  ATTACK/DECAY (Register 05)

    Bits 4-7 of this register (ATK0-ATK3) select 1 of 16 ATTACK rates for
  the Voice 1 Envelope Generator. The ATTACK rate determines how rapidly
  the output of Voice 1 rises from zero to peak amplitude when the Envelope
  Generator is Gated. The 16 ATTACK rates are listed in Table 2.
    Bits 0-3 (DCY0-DCY3) select 1 of 16 DECAY rates for the Envelope
  Generator. The DECAY cycle follows the ATTACK cycle and the DECAY rate
  determines how rapidly the output fails from the peak amplitude to the
  selected SUSTAIN level. The 16 DECAY rates are listed in Table 2.

  SUSTAIN/RELEASE (Register 06)

    Bits 4-7 of this register (STN0-STN3) select 1 of 16 SUSTAIN levels for
  the Envelope Generator. The SUSTAIN cycle follows the DECAY cycle and the
  output of Voice 1 will remain at the selected SUSTAIN amplitude as long
  as the Gate bit remains set. The SUSTAIN levels range from zero to peak
  amplitude in 16 linear steps, with a SUSTAIN value of 0 selecting zero
  amplitude and a SUSTAIN value of 15 ($F) selecting the peak amplitude. A
  SUSTAIN value of 8 would cause Voice I to SUSTAIN at an amplitude one-
  half the peak amplitude reached by the ATTACK cycle.
    Bits 0-3 (RLS0-RLS3) select 1 of 16 RELEASE rates for the Envelope
  Generator. The RELEASE cycle follows the SUSTAIN cycle when the Gate bit
  is reset to zero. At this time, the output of Voice 1 will fall from the
  SUSTAIN amplitude to zero amplitude at the selected RELEASE rate. The 16
  RELEASE rates are identical to the DECAY rates.

  +-----------------------------------------------------------------------+
  | NOTE: The cycling of the Envelope Generator can be altered at any     |
  | point via the Gate bit. The Envelope Generator can be Gated and       |
  | Released without restriction. For example, if the Gate bit is reset   |
  | before the envelope has finished the ATTACK cycle, the RELEASE cycle  |
  | will immediately begin, starting from whatever amplitude had been     |
  | reached. if the envelope is then Gated again (before the RELEASE cycle|
  | has reached zero amplitude), another ATTACK cycle will begin, starting|
  | from whatever amplitude had been reached. This technique can be used  |
  | to generate complex amplitude envelopes via real-time software        |
  | control.                                                              |
  +-----------------------------------------------------------------------+

                                                           APPENDIX O   465

                           Table 2. Envelope Rates
  +-----------------+--------------------------+--------------------------+
  |      VALUE      |        ATTACK RATE       |    DECAY/RELEASE RATE    |
  +-----------------+--------------------------+--------------------------+
  |   DEC   (HEX)   |       (Time/Cycle)       |       (Time/Cycle)       |
  +-----------------+--------------------------+--------------------------+
  |     0    (0)    |            2 ms          |            6 ms          |
  |     1    (1)    |            8 ms          |           24 ms          |
  |     2    (2)    |           16 ms          |           48 ms          |
  |     3    (3)    |           24 ms          |           72 ms          |
  |     4    (4)    |           38 ms          |          114 ms          |
  |     5    (5)    |           56 ms          |          168 ms          |
  |     6    (6)    |           68 ms          |          204 ms          |
  |     7    (7)    |           80 ms          |          240 ms          |
  |     8    (8)    |          100 ms          |          300 ms          |
  |     9    (9)    |          250 ms          |          750 ms          |
  |    10    (A)    |          500 ms          |          1.5 s           |
  |    11    (B)    |          800 ms          |          2.4 s           |
  |    12    (C)    |            1 s           |            3 s           |
  |    13    (D)    |            3 s           |            9 s           |
  |    14    (E)    |            5 s           |           15 s           |
  |    15    (F)    |            8 s           |           24 s           |
  +-----------------+--------------------------+--------------------------+

  +-----------------------------------------------------------------------+
  | NOTE: Envelope rates are based on a 1.0-MHz 02 clock. For other 02    |
  | frequencies, multiply the given rate by 1 MHz/02. The rates refer to  |
  | the amount of time per cycle. For example, given an ATTACK value of 2,|
  | the ATTACK cycle would take 16 ms to rise from zero to peak amplitude.|
  | The DECAY/RELEASE rates refer to the amount of time these cycles would|
  | take to fall from peak amplitude to zero.                             |
  +-----------------------------------------------------------------------+

  VOICE 2

    Registers 07-$0D control Voice 2 and are functionally identical to reg-
  isters 00-06 with these exceptions:

    1) When selected, SYNC synchronizes Oscillator 2 with Oscillator 1.
    2) When selected, RING MOD replaces the Triangle output of Oscillator 2
       with the ring modulated combination of Oscillators 2 and 1.

  466   APPENDIX O

  VOICE 3

    Registers $0E-$14 control Voice 3 and are functionally identical to
  registers 00-06 with these exceptions:

    1) When selected, SYNC synchronizes Oscillator 3 with Oscillator 2.
    2) When selected, RING MOD replaces the Triangle output of Oscillator 3
       with the ring modulated combination of Oscillators 3 and 2.

    Typical operation of a voice consists of selecting the desired parame-
  ters: frequency, waveform, effects (SYNC, RING MOD) and envelope rates,
  then gating the voice whenever the sound is desired. The sound can be
  sustained for any length of time and terminated by clearing the Gate bit.
  Each voice can be used separately, with independent parameters and
  gating, or in unison to create a single, powerful voice. When used in
  unison, a slight detuning of each oscillator or tuning to musical
  intervals creates a rich, animated sound.

  FILTER

  FC LO/FC HI (Registers $15,$16)

    Together these registers form an 11-bit number (bits 3-7 of FC LO are
  not used) which linearly controls the Cutoff (or Center) Frequency of the
  programmable Filter. The approximate Cutoff Frequency ranges from 30
  Hz to 12 KHz.

  RES/FILT (Register $17)

    Bits 4-7 of this register (RES0-RES3) control the resonance of the
  filter. Resonance is a peaking effect which emphasizes frequency com-
  ponents at the Cutoff Frequency of the Filter, causing a sharper sound.
  There are 16 resonance settings ranging linearly from no resonance (0) to
  maximum resonance (15 or $F). Bits 0-3 determine which signals will be
  routed through the Filter:
    FILT 1 (Bit 0): When set to a zero, Voice 1 appears directly at the
  audio output and the Filter has no effect on it. When set to a one, Voice
  1 will be processed through the Filter and the harmonic content of Voice
  1 will be altered according to the selected Filter parameters.
    FILT 2 (Bit 1): Same as bit 0 for Voice 2.
    FILT 3 (Bit 2): Same as bit 0 for Voice 3.
    FILTEX (Bit 3): Same as bit 0 for External audio input (pin 26).

                                                           APPENDIX O   467

  MODE/VOL (Register $18)

    Bits 4-7 of this register select various Filter mode and output
  options:
    LP (Bit 4): When set to a one, the Low-Pass output of the Filter is
  selected and sent to the audio output. For a given Filter input signal,
  all frequency components below the Filter Cutoff Frequency are passed
  unaltered, while all frequency components above the Cutoff are attenuated
  at a rate of 12 dB/Octave. The Low-Pass mode produces fullbodied sounds.
    BP (Bit 5): Same as bit 4 for the Bandpass output. All frequency
  components above and below the Cutoff are attenuated at a rate of 6
  dB/Octave. The Bandpass mode produces thin, open sounds.
    HP (Bit 6): Same as bit 4 for the High-Pass output. All frequency
  components above the Cutoff are passed unaltered, while all frequency
  components below the Cutoff are attenuated at a rate of 12 dB/Octave.
  The High-Pass mode produces tinny, buzzy sounds.
    3 OFF (Bit 7): When set to a one, the output of Voice 3 is disconnected
  from the direct audio path. Setting Voice 3 to bypass the Filter
  (FILT 3 = 0) and setting 3 OFF to a one prevents Voice 3 from reaching
  the audio output. This allows Voice 3 to be used for modulation purposes
  without any undesirable output.

  +-----------------------------------------------------------------------+
  | NOTE: The Filter output modes ARE additive and multiple Filter modes  |
  | may be selected simultaneously. For example, both LP and HP modes can |
  | be selected to produce a Notch (or Band Reject) Filter response. In   |
  | order for the Filter to have any audible effect, at least one Filter  |
  | output must be selected and at least one Voice must be routed through |
  | the Filter. The Filter is, perhaps, the most important element in SID |
  | as it allows the generation of complex tone colors via subtractive    |
  | synthesis (the Filter is used to eliminate specific frequency         |
  | components from a harmonically rich input signal). The best results   |
  | are achieved by varying the Cutoff Frequency in real-time.            |
  +-----------------------------------------------------------------------+

    Bits 0-3 (VOL0-VOL3) select 1 of 16 overall Volume levels for the final
  composite audio output. The output volume levels range from no output (0)
  to maximum volume (15 or $F) in 16 linear steps. This control can be used
  as a static volume control for balancing levels in multi-chip systems or
  for creating dynamic volume effects, such as Tremolo. Some Volume level
  other than zero must be selected in order for SID to produce any sound.

  468   APPENDIX O

  MISCELLANEOUS

  POTX (Register $19)

    This register allows the microprocessor to read the position of the
  potentiometer tied to POTX (pin 24), with values ranging from 0 at
  minimum resistance, to 255 ($FF) at maximum resistance. The value is
  always valid and is updated every 512 (02 clock cycles. See the Pin
  Description section for information on pot and capacitor values.

  POTY (Register $1A)

    Same as POTX for the pot tied to POTY (pin 23).

  OSC 3/RANDOM (Register $1B)

    This register allows the microprocessor to read the upper 8 output bits
  of Oscillator 3. The character of the numbers generated is directly re-
  lated to the waveform selected. If the Sawtooth waveform of Oscillator 3
  is selected, this register will present a series of numbers incrementing
  from 0 to 255 ($FF) at a rate determined by the frequency of Oscillator
  3. If the Triangle waveform is selected, the output will increment from 0
  up to 255, then decrement down to 0. If the Pulse waveform is selected,
  the output will jump between 0 and 255. Selecting the Noise waveform
  will produce a series of random numbers, therefore, this register can be
  used as a random number generator for games. There are numerous timing
  and sequencing applications for the OSC 3 register, however, the chief
  function is probably that of a modulation generator. The numbers
  generated by this register can be added, via software, to the Oscillator
  or Filter Frequency registers or the Pulse Width registers in real-time.
  Many dynamic effects can be generated in this manner. Siren-like sounds
  can be created by adding the OSC 3 Sawtooth output to the frequency
  control of another oscillator. Synthesizer "Sample and Hold" effects can
  be produced by adding the OSC 3 Noise output to the Filter Frequency
  control registers. Vibrato can be produced by setting Oscillator 3 to a
  frequency around 7 Hz and adding the OSC 3 Triangle output (with proper
  scaling) to the Frequency control of another oscillator. An unlimited
  range of effects are available by altering the frequency of Oscillator 3
  and scaling the OSC 3 output. Normally, when Oscillator 3 is used for
  modulation, the audio output of Voice 3 should be eliminated (3 OFF = 1).

                                                           APPENDIX O   469

  ENV 3 (Register $1C)

    Same as OSC 3, but this register allows the microprocessor to read the
  output of the Voice 3 Envelope Generator. This output can be added to the
  Filter Frequency to produce harmonic envelopes, WAH-WAH, and similar
  effects. "Phaser" sounds can be created by adding this output to the
  frequency control registers of an oscillator. The Voice 3 Envelope
  Generator must be Gated in order to produce any output from this regis-
  ter. The OSC 3 register, however, always reflects the changing output of
  the oscillator and is not affected in any way by the Envelope Generator.

  SID PIN DESCRIPTION

  CAP1A,CAP1B, (Pins 1,2)/ CAP2A,CAP2B (Pins 3,4)

    These pins are used to connect the two integrating capacitors required
  by the programmable Filter. C1 connects between pins 1 and 2, C2 between
  pins 3 and 4. Both capacitors should be the some value. Normal operation
  of the Filter over the audio range (approximately 30 Hz-12 kHz) is
  accomplished with a value of 2200 pF for C1 and C2. Polystyrene
  capacitors are preferred and in complex polyphonic systems, where many
  SID chips must track each other, matched capacitors are recommended.
    The frequency range of the Filter can be tailored to specific applica-
  tions by the choice of capacitor values. For example, a low-cost game may
  not require full high-frequency response. In this case, larger values
  for C1 and C2 could be chosen to provide more control over the bass
  frequencies of the Filter. The maximum Cutoff Frequency of the Filter is
  given by:

                             FCmax = 2.6E-5/C

  Where C is the capacitor value. The range of the Filter extends 9 octaves
  below the maximum Cutoff Frequency.

  RES (Pin 5)

    This TTL-level input is the reset control for SID. When brought low for
  at least ten 02 cycles, all internal registers are reset to zero and the
  audio output is silenced. This pin is normally connected to the reset
  line of the microprocessor or a power-on-clear circuit.

  470   APPENDIX O

  02 (Pin 6)

    This TTL-Level input is the master clock for SID. All oscillator
  frequencies and envelope rates are referenced to this clock. 02 also
  controls data transfers between SID and the microprocessor. Data can only
  be transferred when (02 is high. Essentially, (02 acts as a high-active
  chip select as far as data transfers are concerned. This pin is normally
  connected to the system clock, with a nominal operating frequency of 1.0
  MHz.

  R/W  (Pin 7)

    This TTL-level input controls the direction of data transfers between
  SID and the microprocessor. If the chip select conditions have been met,
  a high on this line allows the microprocessor to Read data from the
  selected SID register and a low allows the microprocessor to Write data
  into the selected SID register. This pin is normally connected to the
  system Read/Write line.

  CS (Pin 8)

    This TTL-Level input is a low active chip select which controls data
  transfers between SID and the microprocessor. CS must be low for any
  transfer. A Read from the selected SID register can only occur if CS is
  low, 02 is high and R/W is high. A Write to the selected SID register can
  only occur if CS is low, (02 is high and R/W is low. This pin is normally
  connected to address decoding circuitry, allowing SID to reside in the
  memory map of a system.

  A0-A4 (Pins 9-13)

    These TTL-Level inputs are used to select one of the 29 SID registers.
  Although enough addresses are provided to select 1 of 32 registers, the
  remaining three register locations are not used. A Write to any of these
  three locations is ignored and a Read returns invalid data. These pins
  are normally connected to the corresponding address lines of the micro-
  processor so that SID may be addressed in the same manner as memory.

  GND (Pin 14)

    For best results, the ground line between SID and the power supply
  should be separate from ground lines to other digital circuitry. This
  will minimize digital noise at the audio output.
                                                           APPENDIX O   471

  D0-D7 (Pins 15-22)

    These bidirectional lines are used to transfer data between SID and the
  microprocessor. They are TTL compatible in the input mode and capable of
  driving 2 TTL loads in the output mode. The data buffers are usually in
  the high-impedance off state. During a Write operation, the data buffers
  remain in the off (input) state and the microprocessor supplies data to
  SID over these lines. During a Read operation, the data buffers turn on
  and SID supplies data to the microprocessor over these lines. The pins
  are normally connected to the corresponding data lines of the micro-
  processor.

  POTX,POTY (Pins 24,23)

    These pins are inputs to the A/D converters used to digitize the posi-
  tion of potentiometers. The conversion process is based on the time con-
  stant of a capacitor tied from the POT pin to ground, charged by a
  potentiometer tied from the POT pin to +5 volts. The component values are
  determined by:

                                RC = 4.7E-4

  Where R is the maximum resistance of the pot and C is the capacitor.
    The larger the capacitor, the smaller the POT value jitter. The recom-
  mended values for R and C are 470 komhs and 1000 pF. Note that a separate
  pot and cap are required for each POT pin.

  VCC (Pin 25)

    As with the GND line, a separate +5 VDC line should be run between SID
  Vcc and the power supply in order to minimize noise. A bypass capacitor
  should be located close to the pin.

  EXT IN (Pin 26)

    This analog input allows external audio signals to be mixed with the
  audio output of SID or processed through the Filter. Typical sources in-
  clude voice, guitar, and organ. The input impedance of this pin is on the
  order of 100 kohms. Any signal applied directly to the pin should ride at
  a DC level of 6 volts and should not exceed 3 volts p-p. In order to pre-

  472   APPENDIX O

  vent any interference caused by DC level differences, external signals
  should be AC-coupled to EXT IN by an electrolytic capacitor in the 1-10
  uF range. As the direct audio path (FILTEX=0) has unity gain, EXT IN can
  be used to mix outputs of many SID chips by daisy-chaining. The number of
  chips that can be chained in this manner is determined by the amount of
  noise and distortion allowable at the final output. Note that the output
  Volume control will affect not only the three SID voices, but also any
  external inputs.

  AUDIO OUT (Pin 27)

    This open-source buffer is the final audio output of SID, comprised of
  the three SID voices, the Filter and any external input. The output level
  is set by the output Volume control and reaches a maximum of 2 volts p-p
  at a DC level of 6 volts. A source resistor from AUDIO OUT to ground is
  required for proper operation. The recommended resistance is 1 kohm for
  a standard output impedance.
    As the output of SID rides at a 6-volt DC level, it should be AC-
  coupled to any audio amplifier with an electrolytic capacitor in the 1-10
  uF range.

  VDD (Pin 28)

    As with Vcc, a separate +12 VDC line should be run to SID VDD and a
  bypass capacitor should be used.

  6581 SID CHARACTERISTICS

  ABSOLUTE MAXIMUM RATINGS

  +--------------------------+------------+-----------------+-------------+
  |          RATING          |   SYMBOL   |      VALUE      |    UNITS    |
  +--------------------------+------------+-----------------+-------------+
  |  Supply Voltage          |    VDD     |   -0.3 to +17   |     VDC     |
  |  Supply Voltage          |    VCC     |   -0.3 to +7    |     VDC     |
  |  Input Voltage (analog)  |    Vina    |   -0.3 to +17   |     VDC     |
  |  Input Voltage (digital) |    Vind    |   -0.3 to +7    |     VDC     |
  |  Operating Temperature   |    Ta      |      0 to +70   |   Celsius   |
  |  Storage Temperature     |    Tstg    |   -55 to +150   |   Celsius   |
  +--------------------------+------------+-----------------+-------------+

                                                           APPENDIX O   473

   ELECTRICAL CHARACTERISTICS (Vdd=12 VDC+-5%, Vcc=5 VDC+-5%,
     Ta=0 to 70 Celsius)

  +------------------------------------------+----+-----+---+-------+-----+
  |             CHARACTERISTIC               SYMBOL MIN |TYP|  MAX  |UNITS|
  +------------------------------------------+----+-----+---+-------+-----+
  | Input High Voltage (RES, 02, RIN, CS,    | Vih|  2  | - |  Vcc  | VDC |
  | Input Low Voltage  A0-A4, D0-D7)         | Vil|-0.3 | - |  0.8  | VDC |
  +------------------------------------------+----+-----+---+-------+-----+
  | Input Leakage Current (RES, 02, R/W, CS, | Iin|  -  | - |  2.5  |  uA |
  |                       A0-A4; Vin=0-5 VDC)|    |     |   |       |     |
  | Three-State (Off)     (D0-D7; Vcc=max)   |Itsi|  -  | - |  10   |  uA |
  +------------------------------------------+----+-----+---+-------+-----+
  | Input Leakage Current Vin=0.4-2.4 VDC    |    |     |   |       |     |
  +------------------------------------------+----+-----+---+-------+-----+
  | Output High Voltage   (D0-D7; Vcc=min,   | Voh| 2.4 | - |Vcc-0.7| VDC |
  |                       I load=200 uA)     |    |     |   |       |     |
  +------------------------------------------+----+-----+---+-------+-----+
  | Output Low Voltage    (D0-D7; Vcc=max,   | Vol| GND | - |  0.4  | VDC |
  |                       I load=3.2 mA)     |    |     |   |       |     |
  +------------------------------------------+----+-----+---+-------+-----+
  | Output High Current   (D0-D7; Sourcing,  | Ioh| 200 | - |   -   |  uA |
  |                       Voh=2.4 VDC)       |    |     |   |       |     |
  +------------------------------------------+----+-----+---+-------+-----+
  | Output Low Current    (D0-D7; Sinking,   | Iol| 3.2 | - |   -   |  mA |
  |                       Vol=0.4 VDC)       |    |     |   |       |     |
  +------------------------------------------+----+-----+---+-------+-----+
  | Input Capacitance     (RES, 02, R/W, CS, | Cin|  -  | - |  10   |  pF |
  |                       A0-A4, D0-D7)      |    |     |   |       |     |
  +------------------------------------------+----+-----+---+-------+-----+
  | Pot Trigger Voltage   (POTX, POTY)       |Vpot|  -  Vcc/2   -   | VDC |
  +------------------------------------------+----+-----+---+-------+-----+
  | Pot Sink Current      (POTX, POTY)       |Ipot| 500 | - |   -   |  uA |
  +------------------------------------------+----+-----+---+-------+-----+
  | Input Impedance       (EXT IN)           | Rin| 100 |150|   -   |kohms|
  +------------------------------------------+----+-----+---+-------+-----+
  | Audio Input Voltage   (EXT IN)           | Vin| 5.7 | 6 |  6.3  | VDC |
  |                                          |    |  -  |0.5|   3   | VAC |

  474   APPENDIX O

  +------------------------------------------+----+-----+---+-------+-----+
  | Audio Output Voltage  (AUDIO OUT; 1 kohm |    |     |   |       |     |
  |                       load, volume=max)  |Vout| 5.7 | 6 |  6.3  | VDC |
  |                       One Voice on:      |    | 0.4 |0.5|  0.6  | VAC |
  |                       All Voices on:     |    | 1.0 |1.5|  2.0  | VAC |
  +------------------------------------------+----+-----+---+-------+-----+
  | Power Supply Current  (VDD)              | Idd|  -  | 20|   25  |  mA |
  +------------------------------------------+----+-----+---+-------+-----+
  | Power Supply Current  (VCC)              | Icc|  -  | 70|  100  |  mA |
  +------------------------------------------+----+-----+---+-------+-----+
  | Power Dissipation     (Total)            | Pd |  -  |600| 1000  |  mW |
  +------------------------------------------+----+-----+---+-------+-----+

                                                           APPENDIX O   475

  6581 SID TIMING

                          [THE PICTURE IS MISSING!]

  READ CYCLE

  +----------+----------------------------+-------+-------+-------+-------+
  |  SYMBOL  |           NAME             |  MIN  |  TYP  |  MAX  | UNITS |
  +----------+----------------------------+-------+-------+-------+-------+
  |   Tcyc   |   Clock Cycle Time         |    1  |   -   |    20 |   uA  |
  |   Tc     |   Clock High Pulse Width   |  450  |  500  |10,000 |   ns  |
  |   Tr,Tf  |   Clock Rise/Fall Time     |   -   |   -   |    25 |   ns  |
  |   Trs    |   Read Set-Up Time         |    0  |   -   |   -   |   ns  |
  |   Trh    |   Read Hold Time           |    0  |   -   |   -   |   ns  |
  |   Tacc   |   Access Time              |   -   |   -   |   300 |   ns  |
  |   Tah    |   Address Hold Time        |   10  |   -   |   -   |   ns  |
  |   Tch    |   Chip Select Hold Time    |    0  |   -   |   -   |   ns  |
  |   Tdh    |   Data Hold Time           |   20  |   -   |   -   |   ns  |
  +----------+----------------------------+-------+-------+-------+-------+

  476   APPENDIX O

                          [THE PICTURE IS MISSING!]

  WRITE CYCLE

  +----------+----------------------------+-------+-------+-------+-------+
  |  SYMBOL  |           NAME             |  MIN  |  TYP  |  MAX  | UNITS |
  +----------+----------------------------+-------+-------+-------+-------+
  |   Tw     |   Write Pulse Width        |  300  |   -   |   -   |   ns  |
  |   Twh    |   Write Hold Time          |    0  |   -   |   -   |   ns  |
  |   Taws   |   Address Set-up Time      |    0  |   -   |   -   |   ns  |
  |   Tah    |   Address Hold Time        |   10  |   -   |   -   |   ns  |
  |   Tch    |   Chip Select Hold Time    |    0  |   -   |   -   |   ns  |
  |   Tvd    |   Valid Data               |   80  |   -   |   -   |   ns  |
  |   Tdh    |   Data Hold Time           |   10  |   -   |   -   |   ns  |
  +----------+----------------------------+-------+-------+-------+-------+

                                                           APPENDIX O   477

  EQUAL-TEMPERED MUSICAL SCALE VALUES

    The table in Appendix E lists the numerical values which must be stored
  in the SID Oscillator frequency control registers to produce the notes of
  the equal-tempered musical scale. The equal-tempered scale consists of an
  octave containing 12 semitones (notes): C,D,E,F,G,A,B and C#,D#,F#,G#,A#.
  The frequency of each semitone is exactly the 12th root of 2 times the
  frequency of the previous semitone. The table is based on a (02 clock of
  1.02 MHz. Refer to the equation given in the Register Description for use
  of other master clock frequencies. The scale selected is concert pitch,
  in which A-4 = 440 Hz. Transpositions of this scale and scales other than
  the equal-tempered scale are also possible.
    Although the table in Appendix E provides a simple and quick method for
  generating the equal-tempered scale, it is very memory inefficient as it
  requires 192 bytes for the table alone. Memory efficiency can be improved
  by determining the note value algorithmically. Using the fact that each
  note in an octave is exactly half the frequency of that note in the next
  octave, the note look-up table can be reduced from 96 entries to 12
  entries, as there are 12 notes per octave. If the 12 entries (24 bytes)
  consist of the 16-bit values for the eighth octave (C-7 through B-7),
  then notes in lower octaves can be derived by choosing the appropriate
  note in the eighth octave and dividing the 16-bit value by two for each
  octave of difference. As division by two is nothing more than a right-
  shift of the value, the calculation can easily be accomplished by a
  simple software routine. Although note B-7 is beyond the range of the
  oscillators, this value should still be included in the table for
  calculation purposes (the MSB of B-7 would require a special software
  case, such as generating this bit in the CARRY before shifting). Each
  note must be specified in a form which indicates which of the 12
  semitones is desired, and which of the eight octaves the semitone is in.
  Since four bits are necessary to select 1 of 12 semitones and three bits
  are necessary to select 1 of 8 octaves, the information can fit in one
  byte, with the lower nybble selecting the semitone (by addressing the
  look-up table) and the upper nybble being used by the division routine to
  determine how many times the table value must be right-shifted.

  478  APPENDIX O

  SID ENVELOPE GENERATORS

    The four-part ADSR (ATTACK, DECAY, SUSTAIN, RELEASE) envelope generator
  has been proven in electronic music to provide the optimum trade-off
  between flexibility and ease of amplitude control. Appropriate selection
  of envelope parameters allows the simulation of a wide range 2: of
  percussion and sustained instruments. The violin is a good example of a
  sustained instrument. The violinist controls the volume by bowing the
  instrument. Typically, the volume builds slowly, reaches a peak, then
  drops to an intermediate level. The violinist can maintain this level for
  as long as desired, then the volume is allowed to slowly die away. A
  "snapshot" of this envelope is shown below:

      PEAK AMPLITUDE ---      +  <- SUSTAIN  ->
                             / \     PERIOD
                           A/  D\      S         R
                           /     +------------+
                          /       INTERMEDIATE +
                         /            LEVEL      +
      ZERO AMPLITUDE ---+                           +--

    This volume envelope can be easily reproduced by the ADSR as shown
  below, with typical envelope rates:
                                                +
                                               / \
                                              /   +--------+
  ATTACK:  10 ($A)     500 ms                /              +
  DECAY:    8          300 ms             --+ A  D     S     R +-
  SUSTAIN: 10 ($A)
  RELEASE:  9          750 ms
                                        GATE+--------------+
                                          --+              +-----

    Note that the tone can be held at the intermediate SUSTAIN level for
  as long as desired. The tone will not begin to die away until GATE is
  cleared. With minor alterations, this basic envelope can be used for
  brass and woodwinds as well as strings.
    An entirely different form of envelope is produced by percussion in-
  struments such as drums, cymbals and gongs, as well as certain
  keyboards such as pianos and harpsichords. The percussion envelope is
  characterized by a nearly instantaneous attack, immediately followed by
  a decay to zero volume. Percussion instruments cannot be sustained at

                                                           APPENDIX O   479

  a constant amplitude. For example, the instant a drum is struck, the
  sound reaches full volume and decays rapidly regardless of how it was
  struck. A typical cymbal envelope is shown below:

  ATTACK:   0       2 ms                        +
  DECAY:    9     750 ms                        |+
  SUSTAIN:  0                                   |  +
  RELEASE:  9     750 ms                    ----+     +--
                                               A    D
    Note that the tone immediately begins to decay to zero amplitude after
  the peak is reached, regardless of when GATE is cleared. The amplitude
  envelope of pianos and harpsichords is somewhat more complicated, but can
  be generated quite easily with the ADSR. These instruments reach full
  volume when a key is first struck. The amplitude immediately begins to
  die away slowly as long as the key remains depressed. If the key is
  released before the sound has fully died away, the amplitude will
  immediately drop to zero. This envelope is shown below:

  ATTACK:   0       2 ms                        +
  DECAY:    9     750 ms                        |+
  SUSTAIN:  0                                   |  +
  RELEASE:  0       6 ms                    ----+  +-----
                                               A  D R
    Note that the tone decays slowly until GATE is cleared, at which point
  the amplitude drops rapidly to zero.
    The most simple envelope is that of the organ, When a key is pressed,
  the tone immediately reaches full volume and remains there. When the key
  is released, the tone drops immediately to zero volume. This envelope is
  shown below:
                                                +----+
  ATTACK:   0       2 ms                        |    |
  DECAY:    0       6 ms                        |    |
  SUSTAIN: 15 ($F)                              |    |
  RELEASE:  0       6 ms                    ----+    +---
                                               A   S  R
    The real power of SID lies in the ability to create original sounds
  rather than simulations of acoustic instruments. The ADSR is capable of
  creating envelopes which do not correspond to any "real" instruments. A
  good example would be the "backwards" envelope. This envelope is
  characterized by a slow attack and rapid decay which sounds very much

  480   APPENDIX O

  like an instrument that has been recorded on tape then played backwards.
  This envelope is shown below:                        S
                                                  +----------+
  ATTACK: 10 ($A) 500 ms                       A /           | R
  DECAY:   0        6 ms                        /            +
  SUSTAIN: 15 ($F)                             /              +
  RELEASE:  3      72 ms                    --+                 +--

    Many unique sounds can be created by applying the amplitude envelope of
  one instrument to the harmonic structure of another. This produces sounds
  similar to familiar acoustic instruments, yet notably different. In
  general, sound is quite subjective and experimentation with various
  envelope rates and harmonic contents will be necessary in order to
  achieve the desired sound.

                          [THE PICTURE IS MISSING!]

                        TYPICAL 6581/SID APPLICATION

                                                           APPENDIX O   481

  APPENDIX P

  GLOSSARY

  ADSR                  Attack/Decay/Sustain/Release envelope.
  attack                Rate at which musical note reaches peak volume.
  binary                Base-2 number system.
  Boolean operators     Logical operators.
  byte                  Memory location.
  CHROMA noise          Color distortion.
  CIA                   Complex Interface Adapter.
  DDR                   Data Direction Register.
  decay                 Rate at which musical note falls from peak
                        volume to sustain volume.
  decimal               Base-10 number system.
  e                     Mathematical constant (approx. 2.71828183).
  envelope              Shape of the volume of a note over time.
  FIFO                  First-In/First-Out.
  hexadecimal           Base-16 number system.
  integer               Whole number (without decimal point).
  jiffy clock           Hardware interval timer.
  NMI                   Non-Maskable Interrupt.
  octal                 Base-8 number system.
  operand               Parameter.
  OS                    Operating System.
  pixel                 Dot of resolution on the screen.
  queue                 Single-file line.
  register              Special memory storage location.
  release               Rate at which a musical note fails from
                        sustain volume to no volume.
  ROM                   Read-Only Memory.
  SID                   Sound Interface Device
  signed numbers        Plus or minus numbers.
  subscript             Index variable.
  sustain               Volume level for sustain of musical note.
  syntax                Programming sentence structure.
  truncated             Cut off, eliminated (not rounded).
  VIC-II                Video Interface Chip.
  video screen          Television set

  482   APPENDIX P

  INDEX

  Abbreviations, BASIC Commands, Statements, and Functions, x, 29, 31-34,
    374-375
  ABS function, 31, 35, 374
  Accessories, 335-371
  Accumulator, 213
  ACPTR, 272-274
  ADC, 232, 235, 254
  Addition, 3, 9-11, 16
  Addressing, 211, 215-217, 411-413
  A/D/S/R, 183-185, 189, 196-199
  AND, 232, 235, 254
  AND operator, 13-16, 31, 35-36, 374
  Animation, xiii, 153, 166
  Applications, xiii-xvi
  Arithmetic expressions, 10-12
  Arithmetic operators, 10-12, 16
  Arrays, 10-12, 44-45
  ASC function, 31, 37, 374
  ASCII character codes, 31, 38, 340, 374
  ASL, 232, 236, 254
  Assembler, 215, 218, 227, 310
  ArcTaNgent function, 31, 38, 374
  Attack, (see A/D/S/R)

  Bank selection, 101-102, 133
  BASIC abbreviations, 29, 31-34, 374-375
  BASIC commands, 31-34, 41, 58-60, 62, 81-82, 91
  BASIC miscellaneous functions, 31-34, 43-44, 49, 56-57, 61, 69, 70, 80,
    83-85, 89
  BASIC numeric functions, 31-35, 37-38, 42, 46-47, 49, 83-84, 88-89
  BASIC operators, 3, 9-15, 31-36, 63-64, 68, 92
  BASIC statements, 18-26, 31-34, 39-55, 57, 62-67, 69-79, 86-87, 92
  BASIC string functions, 31-34, 38, 56, 61, 79, 87, 89
  BASIC variables, 7-26
  BCC, 232, 236, 254
  BCS, 232, 236, 254
  BEQ, 226-227, 232, 237, 254
  Bibliography, 388-390
  Binary, 69, 92, 108, 112, 216-217
  Bit, 99-149, 290, 298, 300-301, 305, 343-357, 359

                                                                INDEX   483

  BIT, 232, 237, 254
  Bit map mode, 121-130
  Bit map mode, multicolor, 127-130
  Bit mapping, 121-130
  BMI, 232, 237, 254
  BNE, 226-227, 232, 238, 254
  Boolean arithmetic, 14
  BPL, 232, 238, 254
  Branches and testing, 226-227
  BRK, 232, 238, 254
  Buffer, keyboard, 93
  Business aids, xiii-xvi
  BVC, 232, 239, 254
  BVS, 232, 239, 254
  Byte, 9, 104, 108, 117-119, 124-127, 196, 213, 218-220, 222-227, 260-263,
    274, 278-279, 286, 292-293, 299, 307, 349, 357-359

  Cassette port, 337, 340-342
  Cassette, tape recorder, xiii, 39-41, 65-67, 81-82, 91, 187, 192, 283,
    293-294, 297, 320-321, 337-338, 340-342
  Character PEEKs and POKES, 104, 106, 109-111, 115, 118, 120-122, 127-130,
    134-137, 150, 154-155, 159-161, 165-166
  CHAREN, 260-261
  CHKIN, 272-273, 275
  CHKOUT, 272-273, 276
  CHRGET, 272-273, 307-308
  CHRIN, 272-273, 277-278
  CHROUT, 272-273, 278-279
  CHR$ function, 24, 31, 37-38, 45, 50, 55, 75-76, 93-94, 97, 120, 156,
    336-342, 374, 379-381
  CINT, 272-273, 280
  CIOUT, 272-273, 279-280
  CLALL, 272-273, 281
  CLC, 232, 239, 254
  CLD, 232, 240, 254
  CLI, 232, 240, 254
  Clock, 80, 89, 314, 329-332, 366, 406-408, 421-427, 431, 451
  Clock timing diagram, 406-408
  CLOSE, 272-273, 281-282
  CLOSE statement, 31, 39-41, 348, 354, 374
  CLR statement, 31, 39-40, 81, 109, 374
  CLRCHN, 272-273, 282

  484   INDEX

  CLR/HOME key, 220
  CLV, 232, 240, 254
  CMD statement, 31, 40-41, 374
  CMP, 232, 241, 254
  Collision detect, 144-145, 180
  Color adjustment, 113
  Color combinations chart, 152
  Color memory, 103
  Color register, 117, 120, 128, 135-136, 179
  Color screen, background, border, 115-119, 128, 135-137, 176, 179-180
  Commands, BASIC, 31-92
  Commodore magazine, xvii-xviii, 390
  Commodore 64 memory map, 310
  Complement, twos, 63-64
  Constants, floating-point, integer, string, 4-7, 46, 77-78
  CONTinue command, 31, 41-42, 46, 81, 86, 374
  ConTRoL key, 58, 72, 93-97, 171
  COSine function, 31-34, 42, 374
  CP/M, x, xiv, 368-371
  CPX, 227, 232, 241, 254
  CPY, 227, 232, 241, 254
  Crunching BASIC programs, 24-27, 156
  CuRSoR keys, 93-97, 336

  DATASSETTE(TM) recorder, (see cassette, tape recorder)
  DATA statement, 26, 31, 42-43, 76-77, 111-114, 164, 169, 174, 374
  DEC, 232, 242, 254
  Decay, (see AIDIS/R)
  DEFine FuNction statement, 31, 43-44, 374
  DELete key, 71-72, 95-96
  DEX, 226, 232 242, 254
  DEY, 226, 232: 242, 254
  DiMension statement, 9, 31, 44-45, 374
  Direct mode, 3
  Division, 3, 10-11

  Edit mode, 93-97
  Editor, screen, 93-97
  END statement, 32, 46, 79, 93, 374
  Envelope generator, (see A/D/S/R)
  EOR, 232, 243, 254
  Equal, not-equal-to signs, 3, 9-12

                                                                INDEX   485

  Error messages, 306, 400-401
  Expansion port(s), (also user port, serial port, RS-232 port), 335-371
  EXPonent function, 32, 46, 374
  Exponentiation, 5-6, 10, 12, 16

  Files (cassette), 40, 50, 55, 59-60, 65-66, 75, 84-85, 91, 337-338,
    340-342
  Files (disk), 40, 50, 55, 59-60, 65-66, 75, 84-85, 91, 337-338, 342
  Filtering, 183, 189, 199-202
  Fire button, joystick/paddle/lightpen, 328-329, 343-348
  FOR statement, 20-21, 32, 39, 47-48, 62-63, 77-78, 86, 110, 155-156,
    165-166, 169-171, 198-199, 309, 374
  Football, 45
  FREE function, 32, 49, 109, 374
  FuNction function, 32, 47, 374
  Functions, 31-34, 35, 37-38, 42, 46-47, 49, 56-57, 61, 69-70, 79-80,
    83-85, 87-90, 374-375

  Game controls and ports, 343-348
  GET statement, 22-24, 32, 37, 49-50, 93, 374-375
  GETIN, 272-273, 283
  GET# statement, 32, 37, 50, 55, 65, 341-342, 348, 374
  GOSUB statement, 32, 39, 51-52, 77, 79, 85, 374
  GOTO (GO TO) statement, 32, 37, 48, 52-53, 64, 77,  81, 86, 374
  Graphics keys, xiv-xv, 70-74, 95-96, 108-114
  Graphics mode, xiv-xv, 99-183
  Graphics mode, bit mapped, 121-130
  Graphics symbols, (see graphics keys)
  Greater than, equal to or, 3, 12-13, 16

  Hexadecimal notation, 101, 209, 215-218
  Hierarchy of operations, 16

  IEEE-488 interface, (see serial port)
  IF...THEN statement, 32, 46-47, 49, 52-53, 64, 70, 86, 172-173, 180, 374
  INC, 232, 243, 254
  Income/expense program, 20-21
  Indexed indirect, 224-225
  Indexing, 223-225
  Indirect indexed, 223-224
  INPUT statement, 18-22, 32, 45, 53-55, 93, 374
  INPUT# statement, 32, 55, 75, 86, 88, 90, 374
  INSerT key, 72, 95-96

  486   INDEX

  INTeger function, 32, 56, 80, 374
  Integer,, arrays, constants, variables, 4-5, 7-9
  INX, 226-227, 232, 243, 254
  INY, 226-227, 232, 244, 254
  IOBASE, 272-273, 284
  I/O Guide, 335-375
  IOINIT, 272-273, 285
  I/O Pinouts, 395-397
  I/O Ports, 214, 260, 335-375
  I/O Registers, 104-106, 212-214
  I/O Statements, 39, 50, 54-55, 65-67, 75
  IRQ, 308

  Joysticks, 343-345
  JMP, 228-230, 232, 244, 254, 270, 308
  JSR, 228-230, 233, 244, 255, 268, 270

  KERNAL, 2, 94, 209, 228-230, 308, 268-306, 348-358
  Keyboard, 93-98
  Keywords, BASIC, 29-92

  LDA, 218-220, 233, 245, 255
  LDX, 233, 245, 255
  LDY, 233, 246, 255
  LEFT$ function, 32, 56, 375
  LENgth function, 32, 57, 375
  Less than, equal to or, 3, 12-13, 16
  LET statement, 32, 57, 375
  LIST command, 32, 58, 375
  LISTEN, 272-273, 285
  LOAD, 272-273, 286
  LOAD command, 32, 59-60, 370, 375
  Loading programs from tape, disk, 59-60, 337-338, 340-342
  LOGarithm function, 32, 61, 375
  Lower case characters, 72-74, 105
  LPX (LPY), 348
  LSR, 233, 246, 255

  Machine language, 209-334, 411-413
  Mask, 92
  Mathematics formulas, 394
  Mathematical symbols, 3, 6-17, 394

                                                                INDEX   487

  MEMBOT, 272-273, 287
  Memory maps, 212, 262-267, 272-273,
    310-3@4
  Memory map, abbreviated, 212
  Memory reallocation, 101-103
  MEMTOP, 272-273, 288
  MID$ function, 33, 61, 375
  Modem, xiii-xviii, 339-340
  Modulation, 183, 207-208
  Multiplication, 3, 10-11
  Music, 183-208

  NEW command, 18, 33, 62, 111, 117, 185, 187,375
  NEXT command, 20-21, 33, 39, 47-48, 62-63, 77-78, 86, 110, 155-156,
    165-166, 169-171, 198-199, 309, 375
  NOP, 233, 246, 255
  NOT operator, 13-16, 33, 63-64, 375
  Note types, 190
  Numeric variables, 7-8, 26

  ON (ON...GOTO/GOSUB) statement, 33, 64,375
  OPEN, 272-273, 289
  OPEN statement, 33, 41, 65-67, 75-76, 85, 94, 337-339, 349-352, 375
  Operating system, 210-211
  Operators, arithmetic, 3, 9-12, 16
  Operators, logical, 13-16, 31-33, 35-37, 63-64, 68, 374-375
  Operators, relational, 3, 10-12, 16
  OR operator, 13-26, 33, 68, 101-102, 104, 106, 115, 118, 120, 122,
    126-127, 129, 134, 136-137, 375
  ORA, 233, 247, 255

  Parentheses, 3, 8, 30, 33, 83-84, 88, 375
  PEEK function, 33, 69, 93, 101-102, 104, 106, 108-111, 115, 118, 120-122,
    126-130, 134-137, 145, 150, 159-160, 176-177, 180, 185, 211, 361, 375
  Peripherals, (see I/O Guide)
  PHA, 233, 247, 255
  PHP, 233, 247, 255
  Pinouts, (also see I/O Pinouts), 363, 395-397
  PLA, 233, 248, 255
  PLOT, 273, 290
  PLP, 233, 248, 255

  488   INDEX

  POKE statement, 25, 33, 69-70, 94, 101-102, 104, 106, 109-111, 115-116,
    118, 120-123, 126-130, 134-137, 150, 153-161, 165-166, 168-170,
    172-173, 177-178, 180, 184-186, 194, 198-199, 204-205, 211, 220, 309,
    361, 375-376
  Ports, I/O, 214, 335-375, 395-397
  POSition function, 33, 70, 375
  Power/Play, xvi, 390
  PRINT statement, 13-15, 18-22, 25, 33-54, 56-61, 63, 68-75, 79-80,
    83-84, 87-89, 94-96, 109, 168, 171, 210, 213, 220, 375
  PRINT# statement, 33, 40-41, 75-76, 85, 94, 337, 340-341, 348, 353, 375
  Printer, xv, 338-339
  Program counter, 214
  Program mode, 3
  Prompt, 45

  Quotation marks, xi, 3, 23, 72, 95, 337
  Quote mode, 72-73, 95-96

  RAM, 49, 100-101, 104-105, 107-108, 110-111, 117, 122, 260-262, 269, 340
  RAMTAS, 273, 291
  Random numbers, 53, 80
  RaNDom function, 33, 43, 53, 80, 375
  Raster interrupt, 131, 150-152
  RDTIM, 273, 291
  READST, 273, 292
  READ statement, 33, 42, 76-77, 111, 170, 309,375
  Release, (see A/D/S/R)
  Register map, CIA chip, 428
  Register map, SID chip, 461
  Register map, VIC chip, 454-455
  REMark statement, 25-26, 33, 37-38, 41-42, 45-46, 50, 77-78, 93-95, 101,
    118, 198-199, 338, 340, 356, 375
  Reserved words, (see Keywords, BASIC)
  RESTOR, 273, 293
  RESTORE key, 22, 92, 126, 353
  RESTORE statement, 33, 78, 375
  RETURN key, 3, 18, 22, 41, 50-51, 74, 93-97,  154-155, 166, 217, 220,
    336-337, 370
  RETURN statement, 33, 51-52, 79, 85, 175, 375
  ReVerSe ON, OFF keys, 97
  RIGHT$ function, 33, 79, 375
  ROL, 233, 248, 255
  ROM, 261, 268-269

                                                                INDEX   489

  ROM, character generator, 103-111, 134
  ROR, 233, 249, 255
  RS-232C, 335, 348-359
  RTI, 233, 249, 255, 308
  RTS, 233, 249, 255
  RUN command, 33, 40, 59, 81, 113, 154, 375
  RUN/STOP key, 22, 41-42, 52, 58, 86, 92, 126, 220, 353

  SAVE, 273, 293-294
  SAVE command, 34, 81-82, 375
  SBC, 233, 250, 255
  SCNKEY, 273, 295
  SCREEN, 273, 295-296
  Screen editor, 2, 94-97, 211
  Screen memory, 102-103
  Scrolling, 128-130, 166
  SEC, 233, 250, 255
  SECOND, 273, 296
  SED, 233, 250, 255
  SEI, 233, 251, 255
  Serial port (IEEE-488), 262, 331, 333, 362-366, 432-433
  SETLFS, 273, 297
  SETMSG, 273, 298
  SETNAM, 273, 299
  SETTIM, 273, 299-300
  SETTMO, 273, 300-301
  SGN function, 34, 83, 109, 375
  SHIFT key, 4, 30, 72, 74, 94, 96-97, 168, 220
  SID chip programming, xiv, 183-208
  SID chip specifications, 457-481
  SID chip memory map, 223-328
  SiNe function, 34, 83, 375
  Sound waves, 186-187, 192-196
  SPaCe function, 27, 34, 83-84, 336, 375
  Sprites, x, xiv, 99-100, 131-149, 153-182
  Sprite display priorities, 144, 161, 179
  Sprite positioning, 137-143, 157-161, 177
  SQuare Root function, 34, 84, 375
  STA, 221, 233, 251, 255
  Stack pointer, 214, 222
  STATUS function, 34, 84-85, 354, 375
  Status register, 214, 354

  490   INDEX

  STEP keyword, (see FOR...TO), 34, 86
  STOP, 273, 301-302
  STOP command, 34, 41, 86, 375
  STOP key, (see RUN/STOP key)
  String arrays, constants, variables, 4, 6-9
  String expressions, 9, 17
  String operators, 9, 16-17
  STR$ function, 34, 87, 375
  STX, 233, 251, 255
  STY, 233, 252, 255
  Subroutines, 222, 228-229,  270, 307
  Subtraction, 3, 10-11, 16
  Sustain, (see A/D/S/R)
  SYS statement, 34, 87, 121, 307, 375

  TAB function, 27, 34, 45, 88, 336, 375
  TANgent function, 34, 88, 375
  TALK, 273, 302
  TAX, 233, 252, 255
  TAY, 233, 252, 255
  THEN keyword, (see IF...THEN), 34
  TIME function, 34, 89, 375
  TIME$ function, 34, 89, 375
  TKSA, 273, 302-303
  TO keyword, (see FOR...TO), 34
  TSX, 233, 253, 255
  TXA, 229, 233, 253, 255
  TXS, 233, 253, 255
  TYA, 229, 233, 253, 255

  UDTIM, 273, 303
  UNLSN, 273, 304
  UNTLK, 273, 304
  User port, 355, 359-362
  USR function, 34, 90, 307, 375

  VALue function, 34, 90, 375
  VECTOR, 273, 305-306
  VERIFY command, 34, 91, 375
  Vibrato, 203
  Voices, 187-191
  Volume control, SID, 186

                                                                INDEX   491

  WAIT statement, 13-14, 34, 92, 375

  XOR, (see WAIT statement), 13-14
  X index register, 213, 223-224

  Y index register, 214, 223-224

  Z-80, (see CP/M)
  Zero page, 221-222, 358-359

  492   INDEX

                      COMMODORE 64 QUICK REFERENCE CARD

  SIMPLE VARIABLES

  Type     Name     Range

  Real     XY       +-1.70141183E+38
                    +-2.93873588E-39
  Integer  XY%      +-32767
  String   XY$      0 to 255 characters

    X is a letter (A-Z), Y is a letter or number (0-9). Variable names
  can be more than 2 characters, but only the first two are recognized.

  ARRAY VARIABLES

  Type                  Name
  Single Dimension      XY(5)
  Two-Dimension         XY(5,5)
  Three-Dimension       XY(5,5,5)

  Arrays of up to eleven elements (subscripts 0-10) can be used
  where needed. Arrays with more than eleven elements need to be
  DIMensioned.

  ALGEBRAIC OPERATORS             RELATIONAL AND LOGICAL OPERATORS

  = Assigns value to variable     =   Equal
  - Negation                      <>  Not Equal To
  ^ Exponentiation                <   Less Than
  * Multiplication                >   Greater Than
  / Division                      <=  Less Than or Equal To
  + Addition                      >=  Greater Than or Equal To
  - Substraction                  NOT Logical "Not"
                                  AND Logical "And"
                                  OR  Logical "Or"
                                  Expression equals 1 if true, 0 if false

  SYSTEM COMMANDS

  LOAD"NAME"    Loads a program from tape
  SAVE"NAME"    Saves a program on tape
  LOAD"NAME",8  Loads a program from disk
  SAVE"NAME",8  Saves a program to disk
  VERIFY"NAME"  Verifies that program was SAVEd without errors
  RUN           Executes a program
  RUN xxx       Executes program starting at line xxx
  STOP          Halts execution
  END           Ends execution
  CONT          Continues program execution from line where
                program was halted
  PEEK(X)       Returns contents of memory location X
  POKE X,Y      Changes contents of location X to value Y
  SYS xxxxx     Jumps to execute a machine language program,
                starting at xxxxx
  WAIT X,Y,Z    Program waits until contents of location X,
                when EORed with Z and ANDed with Y, is nonzero.
  USR(X)        Passes value of X to a machine language subroutine.

  EDITING AND FORMATTING COMMANDS

  LIST          Lists entire program
  LIST A-B      Lists from line A to line B
  REM Message   Comment message can be listed but is ignored during
                program execution
  TAB(X)        Used in PRINT statement. Spaces X positions on screen
  SPC(X)        PRINTs X blanks on line
  POS(X)        Returns current cursor position
  CLR/HOME      Positions cursor to left corner of screen
  SHIFT+CLR/HOME Clears screen and places cursor in "Home" position
  SHIFT+INST/DEL Inserts space at current cursor position
  INST/DEL      Deletes character at current cursor position
  CTRL          When used with numeric color key, selects text color.
                May be used in PRINT statement.
  CRSR keys     Moves cursor up, down, left, right on screen
  Commodore Key When used with SHIFT selects between upper/lower case
                and graphic display mode.
                When used with numeric color key, selects optional
                text color

  ARRAYS AND STRINGS

  DIM A(X,Y,Z)  Sets maximum subscripts for A; reserves space for
                (X+1)*(Y+1)*(Z+1) elements starting at A(0,0,0)
  LEN(X$)       Returns number of characters in X$
  STR$(X)       Returns numeric value of X, converted to a string
  VAL(X$)       Returns numeric value of X$, up to first
                non-numeric character
  CHR$(X)       Returns ASCII character whose code is X
  ASC(X$)       Returns ASCII code for first character of X$
  LEFT$(A$,X)   Returns leftmost X characters of A$
  RIGHT$(A$,X)  Returns rightmost X characters of A$
  MID$(A$,X,Y)  Returns Y characters of A$ starting at character X

  INPUT/OUTPUT COMMANDS

  INPUT A$ or A PRINTs "?" on screen and waits for user to enter
                a string or value
  INPUT "ABC";A PRINTs message and waits for user to enter value.
                Can also INPUT A$
  GET A$ or A   Waits for user to type one-character value; no
                RETURN needed
  DATA A,"B",C  Initializes a set of values that can be used by
                READ statement
  READ A$ or A  Assigns next DATA value to A$ or A
  RESTORE       Resets data pointer to start READing the DATA list again
  PRINT"A= ";A  PRINTs string "A=" and value of A
                ";" suppresses spaces - "," tabs data to next field
  PROGRAM FLOW

  GOTO X        Branches to line X
  IF A=1 TO 10  IF assertion is true THEN execute following part of
                statement. IF false, execute next line number
  FOR A=1 TO 10 STEP 2   Executes all statements between FOR and
                         corresponding NEXT, with A going from 1 to 10
                         by 2. Step size is 1 unless specified
  NEXT A        Defines end of loop. A is optional
  GOSUB 2000    Branches to subtoutine starting at line 2000
  RETURN        Marks end of subroutine. Returns to statement following
                most recent GOSUB
  ON X GOTO A,B Branches to Xth line number on list. If X=1 branches
                to A, etc.
  ON X GOSUB A,B Branches to subroutine at Xth line number in list

          ABOUT THE COMMODORE 64 PROGRAMMER'S REFERENCE GUIDE...

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

        Game cartridge compability... spectacular sound... arcade
        style graphics... and high caliber computing capabilities
        make Commodore 64 the most advanced personal computer in
        its class for home, business and educational use.

        The COMMODORE 64 PROGRAMMER'S REFERENCE GUIDE tells you
        everything you need to know about your Commodore 64. The
        perfect companion to your Commodore 64 User's Guide, this
        manual presents detailed information on everything from
        graphics and sound to advanced machine language techniques.
        This book is a must for everyone from the beginner to the
        advanced programmer.

        For the beginner, the most complicated topics are explained
        with many sample programs and an easy-to-read writing style.
        For the advanced programmer, this book has been subjected
        to heavy pre-testing with your needs in mind. And it's
        designed so that you can easily get the most out of your
        Commodore 64's extensive capabilities.

                               C= COMMODORE
                                  COMPUTER

                    COMMODORE BUSINESS MACHINES (UK) LTD.
                               675 Ajax Avenue
                                Trading Estate
                          Slough, Berkshire SL1 4BG
                                   ENGLAND

        9.95 pounds/22056                        ISBN 0-672-22056-3

  *********

    The end of the Project 64 etext of the Commodore 64 Programmer's
  Reference Guide, first edition.

  *********