home *** CD-ROM | disk | FTP | other *** search
Text File | 2019-04-13 | 191.1 KB | 4,259 lines |
- @(#)top:
- ########
- ##################
- ###### ######
- #####
- ##### #### #### ## ##### #### #### #### #### #### #####
- ##### ## ## #### ## ## ## ### ## #### ## ## ##
- ##### ######## ## ## ## ##### ## ## ## ## ##
- ##### ## ## ######## ## ## ## ### ## ## #### ## ##
- ##### #### #### #### #### ##### #### #### #### #### #### ######
- ##### ##
- ###### ###### Issue #12
- ################## Version 1.1b
- ######## March 1996
-
- -------------------------------------------------------------------------
-
- @(#)contents: Table of Contents
-
-
- Features
- 6. "Polygonamy": A Study in 3 Dimensions by Stephen Judd
- (Reference: polygon)
- Did you ever feel real time 3 Dimensional graphics was just asking
- too much from a Commodore 64? Well, ask no more, as Stephen shows
- us just hoiw it can be done. The 64 steps up to the challenge of
- displaying correctly rendered shaded 3D polygons right before your
- very eyes.
- 9. Underneath the Hood of the SuperCPU by Jim Brain
- (Reference: cmdcpu)
- Delve into the technical details of this new accelerator
- under development by CMD. Jim will explain its advantages
- over existing offering, epxlain the features it provides, and
- dispel some myths about the unit.
-
- Columns
- 4. Hi Tech Trickery by Doug Cotton
- (Reference: trick)
- Trying to switch from 128 mode to 64 mode on a C128 without
- human intervwention is triccky. Doing it on modified KERNAL ROMs
- is doubly so. Doug details a routine that will work regardless of
- the ROM in use.
- 12. Hacking Graphics by Harsfalvi Levente
- (Reference: gfx)
- All you Commodore Plus/4 lovers, listen up. Harsfalve delves into
- the Commodore Plus/4 TED chip, explains its many functions and
- details its various registers. Do you know all the things the TED
- chip does in addition to handle video. Now you'll know.
-
- Departments
- 1. The (cough,cough) Hacking Editor
- (Reference: editor)
- 2. Input/Output
- (Reference: io)
- 3. Newsfront
- (Reference: news)
- 5. Hacking the Mags
- (Reference: mags)
- 7. UseNuggets
- (Reference: usenet)
- 8. FIDO's Nuggets
- (Reference: fido)
- 10. Hack Surfing
- (Reference: surf)
- 11. Commodore Trivia
- (Reference: trivia)
- 13. ? DS, DS$: rem The Error Channel
- (Reference: error)
- 14. The Next Hack
- (Reference: next)
- 15. Hacking the Code
- (Reference: code)
-
- -------------------------------------------------------------------------
-
- @(#)legal: Commodore Hacking Legal Notice
-
- Commodore and the respective Commodore product names are trademarks or
- registered trademarks of ESCOM GmbH. Commodore hacking is in no way
- affiliated with ESCOM GmbH, owners of said trademarks. Commodore Hacking is
- published 4 times yearly by:
-
- Brain Innovations Inc.
- 602 N. Lemen
- Fenton MI 48430
-
- The magazine is published on on-line networks free of charge, and a nominal
- fee is charged for alternate mediums of transmission.
-
- Permission is granted to re-distribute this "net-magazine" or "e-zine" in its
- entirety for non-profit use. A charge of no more than US$5.00 may be
- charged by redistribution parties to cover printed duplication and no more
- than US$10.00 for other types of duplication to cover duplication and media
- costs for this publication. If this publications is included in a for-profit
- compilation, this publication must be alternately available separately or as
- part of a non-profit compilation.
-
- This publication, in regards to its specific ordering and compilations of
- various elements, is copyright(c) 1995 by Brain Innovations, Incorporated,
- unless otherwise noted. Each work in this publication retains any and all
- copyrights pertaining to the individual work's contents. For
- redistribution rights to individual works, please contact the author of said
- work or Brain Innovations, Inc.
-
- Brain Innovations, Inc. assumes no responsibility for errors or omissions in
- editorial, article, or program listing content.
-
- -------------------------------------------------------------------------
-
- @(#)info: Commodore Hacking Information
-
- Commodore Hacking is published via the Internet 4 times yearly, and is
- presented in both ISO-8859-1 and HTML versions. This and previous issues can
- be found at the Commodore Hacking Home Page
- (http://www.msen.com/~brain/chacking/), as well as via FTP
- (ftp://ccnga.uwaterloo.ca/pub/cbm/hacking.mag/)
-
- In addition, the Commodore Hacking mail server can be used to retrieve each
- issue. To request a copy of an issue, please send the following electronic
- mail message:
-
- To: brain@mail.msen.com
- Subject: MAILSERV
- Body of Message:
-
- help
- catalog
- send c=hacking12.txt
- quit
-
- To retrieve a PKZIP 1.01 archive of the individual articles in Commodore
- Hacking, request the file c=hacking12.zip
-
- To subscribe to the Commodore Hacking and receive new issues as
- they are published, add the following command to you MAILSERV message
- prior to the quit command:
-
- subscribe c=hacking Firstname Lastname msglen
-
- (msglen is largest size of email message in line you can receive. Each
- line is roughly 50 characters, so 600 lines is about 30000 bytes. When
- in doubt, choose 600)
-
- example:
-
- subscribe c=hacking Jim Brain 600
-
- Although no fee is charged for this magazine, donations are gladly accepted
- from corporate and individual concerns. All monies will be used to defray
- any administrative costs, subscribe to publications for review, and
- compensate the individual authors contributing to this issue.
-
- Any persons wishing to author articles for inclusion in Commodore Hacking are
- encouraged to view the submission guidelines on the WWW
- (http://www.msen.com/~brain/pub/c-hacking-submit.txt) or via the MAILSERV
- server (send c-hacking-submit.txt).
-
- =========================================================================
-
- @(#)rch: Reading C=Hacking
-
- Starting with Issue 11 of Commodore Hacking, the new QuickFind indexing
- system is utilized to aid readers of the text version in navigating the
- magazine. At the top of each article or other important place in the
- magazine, a word prefixed with a special string is present. (See the
- title of this article for an example. Throughout the magazine, if an
- article is mentioned, it will be followed by a reference string. For
- example, if we mentioned this article, we would add (Reference: rch) after
- the name. By using your favorite editor's search function and searching
- for the string after the word "Reference:", prefixed by the magic prefix
- string, will move you directly to the article of choice. To merely skip to
- the next article in the magazine, search only for the magic prefix string.
-
- Some handy indexing strings possibly not referenced anywhere are:
-
- top top of issue
- bottom bottom of issue
- contents table of contents
- legal legal notice
-
- For those with access to a UNIX system, the command "what" can be
- run on the issue, which will result in all the article titles being
- printed.
-
- A slightly different magic prefix string "@(A)" is used to delimit
- sub-topics or main heading in articles. The text after the magic string
- differs depending on article content. For the Input/Output column
- (Reference: io), the text after the magic prefix will either be "c" for
- comment, or "r" for response. In features and columns, a number after
- the prefix indicates the ordinal of that heading or sub-topic in the
- article. If a specific sub-topic is referenced elsewhere in the article,
- a sub-topic reference will be indicated. A reference to "@(A)r" would
- be written as "(SubRef: r)".
-
- As time goes on, the role of this indexing system will be expanded and
- changed to ease navigation of the text version, but minimize the clutter
- added by these extra items.
-
- =========================================================================
-
- @(#)editor: The Hacking Editor
- by Jim Brain (brain@mail.msen.com)
-
- Speed and the Web. The owners are asking about it. The developers are
- looking into it. The market is readying itself for it. No, not the PC
- market, I'm referring to the Commodore 8-bit market. The same market
- usually referred to as "mature". The same market usually referred to with
- a condescending tone. Well, mature we might be, but isn't that considered
- a good thing? People are supposed to mature as they grow older. As such,
- they are revered and looked up to. What parallels can we draw here?
-
- If you haven't anything about the planned introduction of the CMD SuperCPU
- 20 MHz accelerator cartridges for the C64 and C128, shame on you! You
- need to stay in touch more. For those who have, let's not overdo the
- hype. CMD isn't the first to produce such a cartridge, but they will be
- the first to introduce 20 MHz as a speed option. C128 users will rejoice
- as the first 128 mode accelerator ships from CMD. When this happens,
- performance approaching that of the venerable Intel 80386 will be as
- close as the on/off switch.
-
- The explosion of interest in the Internet and the World Wide Web is
- changing the way people view computers. Until recently, it seemed that
- people thought only computer systems including a 32 or 64 bit CPU,
- multiple megabytes of RAM, gigabyte hard drives, infinite resolution
- monitors and million bit sound cards were worth owning. Commodore
- owners have felt the sting of ridicule as they continually take blow
- after blow for remaining loyal to a machine with much to offer. Well,
- be patient, because 1996 might be the year of the "network computer", a
- smaller comuter system that trades all the fancy features of bloated PCs
- for a smaller size, cost, and a connection to the Internet. Big names
- like IBM, Oracle and Apple are pushing this idea, which would bring to
- market systems with modest RAM, small drives, television displays, and
- small operating systems. Does this idea sound familiar? It should, as
- it describes many features of Commodore 8-bit systems. No, the CBM
- 8-bit still lacks a few items present in the IBM/Apple/Oracle designs,
- but the bulk of features are already available on your so called
- "obsolete" CBM machine. Don't gloat yet, as there's much to do, but
- if your friends tout the benefits of such a machine, gently remind them
- that you own of of the first and best, a Commodore 8-bit.
-
- Enjoy YOUR magazine,
-
- Jim Brain (brain@mail.msen.com)
- editor
-
- ============================================================================
-
- @(#)io: Input/Ouput
-
- Obviously, Commodore Hacking depends on the comments and article submissions
- from the Commodore community to flourish. Everyone sees the articles, but
- let's not forget those comments. They are very helpful, and every attempt
- is made to address concerns in them. Address any comments, concerns, or
- suggestions to:
-
- Commodore Hacking
- 602 N. Lemen
- Fenton, MI 48430
- brain@mail.msen.com (Internet)
-
- @(A)c: Time Travellin'
-
- From: Robin Harbron <rfharbro@flash.lakeheadu.ca>
-
- Dear C=Hacking,
- I was looking at the Commodore Hacking page (fantastic magazine) and
- noticed that the "Publishing Schedule for 95-96" has 1995 for all the
- dates, while I assume that the last 4,5,or 6 probably should be 1996.
- Thanks for everything!
-
- Robin
-
- @(A)r:
- Yep, we must have just returned from our time travel experiments when we
- wrote that in the WWW pages. Note that the magazine was correct, but the
- home was in error. Oh well.
-
- @(A)c: Run (Down) the Software
-
- From: sis319@educ.di.unito.it
-
- Dear C=Hacking,
- I really appreciate the work you are doing with the Commodore Hacking
- on-line magazine. I like the new look and the new features you added, such
- as newsfront and hacking the mags.
-
- I would like to see on the magazine some reviews about the latest and more
- interesting PD and Shareware software (with a list of FTP sites where these
- are available) and hardware products.
-
- Please note that Commodore Hacking is the only Commodore magazine I can
- easily find here in Italy, because all the Italian magazine there were are
- dead and all the foreign magazines that were distributed, such as "RUN",
- "Compute!'s Gazette", "64'er" are either dead or no longer distributed.
-
- @(A)r:
- We appreciate your comments about the new look of C=Hacking. As for the
- inclusion of reviews, we're looking into it. it's not that we don't want
- to do it, just that we need to schedule the reviews (Commodore Hacking
- shouldn't do all of them, as that creates bias), and determining what
- software is worthy of review. Look for some reviews in upcoming issues.
-
- @(A)c: Separate But Equal
-
- From: alan.jones@qcs.org (Alan Jones)
-
- Dear C=Hacking,
- I like your new version of C=Hacking. I like the idea of including
- relevant news and summaries of other magazines and disks. Size should not
- be a constraint, although you should publish early when it exceeds some
- critical size. Don't scrimp on source code listings and uuencoded files!
- There is no other publication for this sort of bulky technical stuff.
- It would also be wonderfull if we could get an apropriate means for
- including diagrams or pictures, viewable by C64/128 users. I would REALLY
- like to have the C64/128 html viewer/printer that you mentioned. You may
- not know it but we came very close to having Al Angers Tower article
- submitted to C=Hacking in place of _Commodore World_, but C=Hacking could
- not really handle drawings and photos.
-
- I have been separating C=Hacking into separate articles and files, archiving
- them and placing the archive(s) on a local BBS. This compacts the length
- and makes it easier to read and use. I try to make C=Hacking easy to
- download and use locally, but I still want to keep it as whole and original
- as possible.
-
- @(A)r:
- Alan, we're glad you approve of the new format. We're going to try to keep
- the size so that it will always fit onto 2 1541 disk sides. C=Hacking
- is still working on the HTML viewer, but it's taking a back seat to other
- more pressing issues. We'll have it finished at some point, and start
- distributing the magazine that way as well. As for your separation, we
- appreciate the work you've done to make C=Hacking easier to distribute.
- With issue #12, we are offering an archive of all the article in separate
- files. The archival method has not been chosen just yet, but look on the
- C=Hacking MAILSERV server for the file.
-
- Late news: check Commodore Hacking Information (Reference: info) for
- more information of retrieving an archive of the individual articles.
-
- @(A)c: Enquiring Minds Wanna Know!
-
- From: Peter Hofman <HOFMAN%NLEV00@btmv56.se.bel.alcatel.be>
-
- Dear C=Hacking
- I would like to make a suggestion for your "Commodore Hacking E-Zine" page.
- Maybe you could add a link to a page with some info about the next issue of
- Commodore Hacking, so people know what will be in the next issue. The reason
- why I make this suggestion is that I read the other issues, and I am very
- curious, what will be published.
-
- @(A)r:
- Good suggestion. So good, in fact, that we implemented it. Mind you, we
- can't completely predict the future, so the information in the link may
- not exactly reflect the contents of the issue when it is published, but
- we'll try to keep the two in sync.
-
- @(A)c: Pulling It Out of the Closet
-
- From: bloodbane@rlion.com (Jeffrey S Cotterman)
-
- Dear C=Hacking,
- Well, I was just writing to say I think you did a great job on C=
- Hacking... I am throughly amazed by the support and the interest in
- the Commodores. I have a Vic-20, C-64, C-128, and an Amiga 1000.
- I have not used any of them in a long time, I have two Beamers that I
- use more. However seeing all this stuff makes me want to turn them back
- on. (Actually I use the 64 quite a bit for playing games, plus the
- 1702 monitor works great with a Super Nintendo!) I used to be quite
- proficient at the 64, but it is slipping. I will try to get my butt
- back in gear so maybe I can post an article or two.... Geesh, and just
- last year I got rid of all my Run and Compute's Gazette magazines....
- Oh well I will look through the cobwebs and see what I can come up
- with. Anyway, congrats on the mag, I think it's going great.
-
- @(A)r:
- We appreciate the thanks. And, if we can get one person to pull a C64
- or other CBM machines out of the closet and turn it back on through what we
- do, it is worth it.
-
- @(A)c: C=Hacking Flunked Geography
-
- From: Peter Karlsson <dat95pkn@idt.mdh.se>
-
- Dear C=Hacking,
- I saw your mention of Atta Bitar in Commodore Hacking.
-
- German? Heheheh... :-)
-
- Anyway, the English information page is available now, but not much will=20
- be in English (sorry). It is a Swedish paper :)
-
- From: Erik Paulsson <ep@algonet.se>
-
- Dear C=Hacking,
- I'm the editor of the Swedish mag Atta Bitar (8 bitter), so I thought I
- should drop you a line.
-
- I really like the "new" C= Hacking it's really great, keep up the good work!
-
- One small comment regarding Atta Bitar, it's not in German, it's in swedish.
- I just thought you should know...
-
- @(A)r:
- Picky, picky, picky. It's not like we would react that way if you said
- Commodore Hacking came from CANADA. Wait, hold it.... I guess we would.
- Correction made. Thanks for the update, and if we ever learn Swedish, we'll
- try to read it again. (Anyone want to translate for us?)
-
- =========================================================================
-
- @(#)news: Newsfront
-
- * Matthew Desmond, the author of Desterm, has recently resurfaced and
- states that he is once again working on something. Although Commodore
- Hacking discourages hourds from emailing him to ask about Desterm
- progress, Matt's email address is mdesmond@ionline.net, for those
- who wish to register Desterm or express their support.
-
- * Speaking of email addresses, LOADSTAR will be changing theirs. As
- the online service GEnie has recently been purchased and new fares
- have been put in place, LOADSTAR finds its monthly bill rising too
- high for pleasure. As of March, 1996, the Internet address for
- LOADSTAR will be loadstar@softdisk.com.
-
- * While we're on the subject of email addresses, CMD has expanded their
- set of Internet email address contacts in order to better support its
- online users. The following addresses are now valid:
-
- Email Address Usage
-
- cmd.sales@the-spa.com Questions relating to product prices,
- catalog requests, ordering onformation,
-
- cmd.support@the-spa.com Technical questions concerning CMD products.
-
- cmd.cw@the-spa.com Questions or comments relating to Commodore
- World magazine.
-
- doug.cotton@the-spa.com superceded the cmd-doug@genie.geis.com address
- previously used for all CMD inquires. Should
- be used items not applicable to the above
- addresses
-
- cmd.cac@the-spa.com Direct link to Charles A. Christianson, VP of
- Sales and Marketing. Again, shuld be used for
- items not applicable to above email addresses.
-
- * We're not done yet, as COMMODORE CEE has recently moved its office and
- is now at:
-
-
- COMMODORE CEE
- 5443 College Oak Drive #26
- Sacramento, CA 95841
- Jack Vanderwhite@cee-64.wmeonlin.sacbbx.com (Contact)
- ceejack@crl.com (Contact)
- Jack Vanderwhite, editor.
- Fidonet: 1:203/999
- (916) 339-3403 (Bulletin Board System)
-
- * The Commodore Zone. No, it's not an alternate universe, but a magazine
- for the Commodore gamer and/or demo fan. Each issue's 40 pages is full
- of reviews, interviews with top programmers, and an exclusive comic
- strip done by Alf Yngve. Accompanying each issue is a 5.25" disk or
- tape containing game demos, demos, and full games. Free software is
- often included.
-
- More information can be obtained through:
-
- Commodore Zone
- 34 Portland Road
- Droitwich
- Worcestershire
- WR9 7QW
- England
-
- Copies are available for UK3.00. Make checks payable to Binary
- Zone PD.
-
- * Also in the magazine front, Computer Workshops, Inc. is planning a
- World Wide Web magazine to feature gaming. The blurb follows:
-
- CWI is working on a new Web magazine to feature the newest and
- hottest in c64/128 Gaming. But, before we can do that, we need
- your help. Send us what you're working on, or, if you're a
- programmer with something for review, send us that too! Also,
- if you've got a product you'd like to advertise, we'd like to
- hear that too (a la Yahoo).
-
- Send it to either, or both:
-
- spectre@deepthought.armory.com
-
- Computer Workshops/Cameron Kaiser
- ATTN: Commodore Gamer
- 3612 Birdie Drive
- La Mesa, CA 91941-8044
-
- (Please don't send binaries to the spectre@ address.)
-
- Thanks for your support, and barring any unforseen difficulties,
- Commodore Gamer should be ready to premiere in about two months.
-
- Cameron Kaiser
-
- * The December 10, 1995 edition of the Waco Tribune Herald put one of our
- own in the spotlight. The headline read "'Antique' PCs have loyal
- fans here, elsewhere." and was written by Sherry W. Evans,
- Tribune-Herald staff writer. The Commodore user taking the spotlight
- was Karen Allison, known on the FIDO network. Sharing the spotlight
- with Karen was Brad Jackson, of Commodore Country, who said that
- a C64 was raced against an Intel 386 using identical programs, and
- the 64 won. Allison claims in the article that "the challenge is finding
- creative ways to solve problems since Commies have had no ... support..."
- Allison indirectly mentioned GeoFAX, the GEOS Fax program, and a low
- cost Tax program she uses to pay the IRS every year. Allison, a diehard
- "Commie", explained in the article that "(People who use IBMs) all
- think my Commodore can't do much and is just a toy. But for a toy,
- this computer does pretty good."
-
- * For those good with an assembler and the VIC/SID registers, Driven
- Magazine is sponsoring a 4K Demo competition. The deadline is July
- 1st 1996. Although the program must run on an NTSC 64, PAL programmers
- are encouraged to enter. The entries will be released as a group at the
- close of the contest, and entrants can re-use their entries. The
- complete rules follow:
-
- 4k Demo Contest Rules
-
- - 1 file only (no secondary loading)
- - max file size is $1000 bytes
- - must be started with BASIC 'run'
- - 1 demo per coder; multiple entries per group are allowed.
- Multiple coders can collaborate on a single demo, so long
- as there remains only 1 demo per coder.
- - credits for all parts of an entry must be given at time of entry;
- if a particular credit is unknown, mark it as "unknown"
- - demos will be evaluated on NTSC c64.
-
- Anything not specifically denied above is allowed; e.g. packing +
- crunching, use or non-use of music or graphics, entries by PAL
- sceners, etc.
-
- Deadline = July 1.
-
- Entries need to go to coolhand:
-
- coolhand@kaiwan.com
-
- or postal mail to:
-
- Bill Lueck
- 17411 Mayor Lane
- Huntington Beach, California, 92647
- USA
-
- Evaluators will be selected shortly, but will include Coolhand and 2-3
- other non-demomaking NTSC demo enthusiasts.
-
- There will be categories for evaluation, but there will not be separate
- winners - the scores from the categories will be added together. The
- categories will be announced after the evaluation team is established,
- but they will include design, originality, technical difficulty,
- artistic impact, and best overall impact, etc (all tentative at this
- time).
-
- * Bo Zimmerman has put his Commodore 128 on the net. No, he didn't
- log into some Internet service from his 128, he actually PUT it on
- the 'Net. Running the BBS program called "Zelch", the machine can be
- accessed by telntting to 147.26.162.107 and giving "zelch" as the
- login. Bo warns that the system is running off a single 1571 at 2400
- bps, so don't hog the system, OK.
-
- For the technical types, the 128 is connected to the serial port
- of a Linux PC hooked up the Internet. Nonetheless, we're getting
- closer to the standalone CBM Internet server.
-
- * In the March 1996 issue of _Next Generation_ magazine, on pages 31
- and 32, NG published a very unflattering definition of the Commodore
- 64 as part of their: "The Next Generation 1996 Lexicon A to Z:
- A definitive guide to gaming terminology". Among other things, the
- definition's writer confused the Apple II with the Commodore 64 and
- stated that the C64 could not display lowercase, a common problem
- on early Apples. The writer was biased in favor of the Apple II line,
- but evidently had never used a C64 or never owned an early Apple II.
- In either case, the fervor caused by the definition sparked an outrage
- in the USENET newsgroup comp.sys.cbm. See UseNuggets (Reference: usenet)
- for the scoop.
-
- If you would like to write to _Next Generation_, even though the
- article claimed no comments would be heard on the subject, or to
- request a copy of the article, their address is:
-
- Editorial:
-
- Email: ngonline@imagine-inc.com
- Fax: (415) 696-1678
- Phone: (415) 696-1688
-
- Subscriptions:
-
- Email: ngsubs@aol.com
- Phone: (415) 696-1661
-
- Post Office Mail:
-
- Next Generation
- Imagine Publishing, Inc.
- 1350 Old Bayshore Highway, Suite 210
- Burlingame, CA 94010
-
- =========================================================================
-
- @(#): trick: RUN64: Moving to 64 Mode
- by Doug Cotton (doug.cotton@the-spa.com)
-
- Reprinted with permission. Copyright (c) 1996 Creative Micro Designs, Inc.
-
- Various routines have been used over the years to allow programs to move
- from 128 mode to 64 mode without user intervention. With the advent of
- modified Kernal ROMs (JiffyDOS, RAMLink, and others) many of the methods
- that work on stock machines have either failed to do the job completely,
- and in some cases fail all together.
-
- RUN64 is the answer to those users looking to worm their way into
- 64 mode without having to be concerned with the different Kernal ROMs. The
- program is presented here in two ways: as a BASIC program that will move to
- 64 mode and load the program you request, and as assembly language source
- for ML programmers.
-
- BASIC Notes: The BASIC version uses the ML code produced by the
- assembly language source. This is found in the data statements beginning at
- line 660. When you run it, the program will ask for the file name, device
- number, and file load type (BASIC or ML). The first two parameters should
- be self-explanatory, but the load type may confuse you. If the file you're
- loading is itself a small loader (1, 2 or 3 blocks) then it will almost
- always be an ML program. Likewise, if you usually load the file with a
- ",8,1" at the end of the load statement, it's ML. If you're loading a
- larger file, or a file that you normally load with just a ",8", then use
- the BASIC option.
-
- Also, if you remove the REM instructions from lines 150 through 180
- the program becomes a dedicated loader. Just specify the file name and
- other options within those lines.
-
- @(A): How The Routine Works
-
- RUN64 performs its trick by masquerading as a cartridge. When started,
- the code copies the payload routines into $8000, with the special header
- that signifies a cartridge is present. It then resets the system. The
- system initializes and checks for a cartridge. When it finds the payload
- routines, it executes them just like it would any cartridge. The
- pseudo-cartridge routines then switch out BASIC, call the remainder of
- the KERNAL init routines, switch BASIC in, call some BASIC init routines,
- set the "load" and "run" lines on screen, dump some "returns" into the
- keyboard buffer, and finally jump into the BASIC interpreter.
-
- @(A): Assembly Language Notes:
-
- The source code is pretty well documented, and ML programmers should have
- little trouble figuring out what everything does. Take note of the Buddy
- Assembler .off pseudo-op used a few lines below the code label. This
- adjusts all fixed references within the code that follows it to execute
- properly at $8000.
-
- The code uses some indirect vectors (ibv, ibr and ibm) to overcome not
- having an indirect jsr opcode, and switches out BASIC ROM temporarily since
- the KERNAL finishes intializing by indirectly jumping through the address
- at $a000. Since the target application hasn't been loaded yet, the code
- must put its own address at $a000 to regain control.
-
- To use the routine, just set up a file name at filename, put a
- device number in $ba, set the load type in sa1flag, then execute the
- routine.
-
-
- 100 rem run64.bas (c) 1996 creative micro designs, inc.
- 110 :
- 120 print "{CLEAR/HOME}run64"
- 130 print
- 140 :
- 150 rem f$="filename" : rem filename
- 160 rem dv=peek(186) : rem device number (8, 9, 10, etc.)
- 170 rem l$="a" : rem load type (a=basic, b=ml [,1])
- 180 rem goto 310
- 190 :
- 200 input "filename";f$
- 210 input "{2 SPACES}device";dv$ : if dv$="" then 230
- 220 poke 186,val(dv$)
- 230 dv = peek(186)
- 240 print
- 250 print "select a or b"
- 260 print "{2 SPACES}a.
- load";chr$(34);f$;chr$(34);",";right$(str$(dv),len(str$(dv))-1)
- 270 print "{2 SPACES}b.
- load";chr$(34);f$;chr$(34);",";right$(str$(dv),len(str$(dv))-1);",1"
- 280 get l$ : if l$<>"a" and l$<>"b" then goto 280
- 290 print
- 300 print l$;" selected"
- 310 print
- 320 print "going to 64 mode!"
- 330 :
- 340 : rem poke in main ml
- 350 :
- 360 i = 6144
- 370 read d
- 380 if d = -1 then 450
- 390 poke i,d
- 400 i = i + 1
- 410 goto 370
- 420 :
- 430 : rem poke in filename
- 440 :
- 450 for i = 0 to len(f$)-1
- 460 : poke 6356+i, asc(mid$(f$,i+1,1))
- 470 next i
- 480 poke 6356+i,0
- 490 :
- 500 : rem poke in device number
- 510 :
- 520 if dv$="" then 570
- 530 poke 186,val(dv$)
- 540 :
- 550 : rem check load type
- 560 :
- 570 poke 6324,0
- 580 if l$="b" then poke 6324,1
- 590 :
- 600 : rem sys to ml
- 610 :
- 620 sys6144
- 630 :
- 640 : rem ml data
- 650 :
- 660 data 32,115,239,160,0,185,22,24
- 670 data 153,0,128,200,208,247,165,186
- 680 data 141,157,128,76,77,255,9,128
- 690 data 9,128,195,194,205,56,48,169
- 700 data 0,141,4,128,120,169,0,141
- 710 data 22,208,32,132,255,32,135,255
- 720 data 169,230,133,1,169,43,141,0
- 730 data 160,169,128,141,1,160,76,248
- 740 data 252,169,231,133,1,32,148,128
- 750 data 32,151,128,32,154,128,162,0
- 760 data 189,159,128,240,6,32,210,255
- 770 data 232,208,245,162,0,189,190,128
- 780 data 240,6,32,210,255,232,208,245
- 790 data 162,0,189,180,128,240,6,32
- 800 data 210,255,232,208,245,173,158,128
- 810 data 240,10,169,44,32,210,255,169
- 820 data 49,32,210,255,169,145,32,210
- 830 data 255,32,210,255,173,157,128,133
- 840 data 186,162,0,189,185,128,240,6
- 850 data 157,119,2,232,208,245,173,158
- 860 data 128,208,2,169,4,133,198,76
- 870 data 157,227,108,149,227,108,152,227
- 880 data 108,155,227,0,0,17,17,68
- 890 data 86,61,80,69,69,75,40,49
- 900 data 56,54,41,58,76,79,65,68
- 910 data 34,0,34,44,68,86,0,13
- 920 data 82,213,13,0,70,73,76,69
- 930 data 78,65,77,69,0,-1
-
-
-
- ; RUN64.SRC
- ; Doug Cotton & Mark Fellows
- ; (c) 1996 Creative Micro Designs, Inc.
- ;
- .org $1800
- .obj run64.obj
-
- run64 jsr $ef73 ; go slow
- ;
- ldy #0 ; copy cartridge
- - lda code,y ; code to $8000
- sta $8000,y
- iny
- bne -
- ;
- lda $ba ; get device number
- sta dvtemp ; and store it
- ;
- jmp $ff4d ; go 64
- ;
- code .byt $09,$80 ; cold start
- .byt $09,$80 ; warm start
- .byt $c3,$c2,$cd,$38,$30 ; cbm80
- ;
- .off $8009 ; offset code
- ;
- lda #$00 ; disable
- sta $8004 ; cartridge code
- sei ; disable interrupts
- ;
- lda #$00 ; zero out
- sta $d016 ; VIC control Register
- ;
- jsr $ff84 ; initialize I/O
- jsr $ff87 ; initialize RAM
- lda #$e6 ; switch in RAM
- sta $01 ; at $A000
- lda #<reenter ; set up return vector
- sta $a000 ; at $A000 to bypass
- lda #>reenter ; BASIC statup during
- sta $a001 ; initialization
- ;
- jmp $fcf8 ; let Kernal finish up
- ;
- reenter lda #$e7 ; back from Kernal, set
- sta $01 ; $A000 back to ROM
- ;
- jsr ibv ; initialize vectors
- jsr ibr ; initialize RAM
- jsr ibm ; initialize memory
- ;
- ldx #$00 ; output screen text
- - lda part1,x ; to form LOAD statement
- beq +
- jsr $ffd2
- inx
- bne -
- ;
- + ldx #$00 ; print filename to be
- - lda filename,x ; loaded at end of
- beq + ; LOAD statement
- jsr $ffd2
- inx
- bne -
-
- ;
- + ldx #$00 ; print device
- - lda part2,x ; variable at end
- beq + ; of LOAD statement
- jsr $ffd2
- inx
- bne -
- ;
- + lda sa1flag ; check secondary
- beq + ; address flag for load
- lda #',' ; type, and print a
- jsr $ffd2 ; comma and a 1 at end
- lda #'1' ; of LOAD statement if
- jsr $ffd2 ; load type is ML
- ;
- + lda #$91 ; print two CRSR up
- jsr $ffd2
- jsr $ffd2
- ;
- lda dvtemp ; get device number
- sta $ba ; and store
- ;
- + ldx #$00 ; put [RETURN]rU[RETURN]
- - lda keydata,x ; into keyboard buffer
- beq +
- sta $0277,x
- inx
- bne -
- ;
- + lda sa1flag ; get load type and
- bne + ; branch if it is ML (1)
- lda #$04 ; if not ML, change .A
- + sta $c6 ; store kybd buffer NDX
- ;
- jmp $e39d ; enter BASIC
- ;
- ibv jmp ($e395) ; initialize vectors
- ibr jmp ($e398) ; initialize RAM
- ibm jmp ($e39b) ; initialize memory
- ;
- dvtemp .byt $00 ; device number temp
- sa1flag .byt $00 ; load type (1=ML,
- ; 0=BASIC)
- ;
- part1 .byt $11,$11 ; 2 CRSR up
- .byt 'dv=peek(186):load'
- .byt $22 ; quote
- .byt $00
- ;
- part2 .byt $22 ; quote
- .byt ',dv'
- .byt $00
- ;
- keydata .byt $0d ; [RETURN]
- .byt 'rU' ; shortcut for RUN
- .byt $0d ; [RETURN]
- .byt $00
- ;
- filename .byt 'filename' ; name of file to load
- .byt $00 ; 00 byte must follow filename!
- ;
- .end
-
- =========================================================================
-
- @(#)mags: Hacking the Mags
-
- Not everything good and/or technical comes from Commodore Hacking, which
- is as it should be. (I still think we have the most, though...) Thus,
- let's spotlight some good and/or technical reading from the other
- Commodore publications.
-
- If you know of a magazine that you would like to see summarized here, let
- C=Hacking know about it. These summaries are only limited by Commodore
- Hacking's inability to purchase subscriptions to all the Commodore
- publications available. We are very grateful to those publications that
- send complimentary copies of their publications for review.
-
- @(A): COMMODORE CEE
- At press time, Issue #5 was in the works, so we'll detail the contents
- next time. However, see Newsfront (Reference: news) for address changes
- for COMMODORE CEE.
-
- @(A): Commodore 128/64 Power User Newsletter (CPU)
- A while back, Gosser Games, Ltd., Inc. sent us a sample issue of this
- publication, which is published exclusively with a Commodore 128
- machine, much like the defunct dieHard. For those just getting into
- the BBS arena, the "Cyberspace Cowboy", R.J. Smulkowski, previously
- writing this article in dieHard, has moved his column to CPU. The
- content is light, but useful, and a godsend for new users. Reviews
- of GeoFAX and "Radio Controlled Flight Simulator" also grace the
- pages. Printed on regular bond at 7" by 9", the 16 page publication
- is small but full of potential.
-
- @(A): Commodore World
- If you remember last time we spoke of Commodore World, we asked the
- rhetorical question: What's up with those funky graphics? We didn't
- expect an answer, but editor Doug Cotton called to explain the curious
- eye-catchers. He also mentioned that asst. editor Jenifer Esile was
- having trouble creating them now that we made fun of them. We're sorry
- Jenifer. We want you to continue, since they save us the cost of
- commercial inkblot cards for our self-psycho-analysis sessions here
- at Hacking Headquarters. (just joshing, we can be so mean sometimes).
- Speaking of Jenifer, we're not sure when she started, but the last few
- issues seem more colorful. Sure, content is great, but packaging is
- everything. We've even caught PC-centric folks perusing our copy.
- Kudos to CMD for that effect.
-
- Obviously, Commodore World iisn't for all, but the content is
- consistent. Issues 11 and 12 are no exception. In issue 11, Doug
- tackles high level serial bus routines and includes ML source,
- Gaelyne Moranec shares some useful WWW pages, and Jim Butterfield
- explains the nasty NULL character and its implications. Of special
- interest in this issue is the two page spread on changing device
- numbers on the pesky 1541 drives. The article is worthy of archival
- for reference. CMD also takes time to note that the SuperCPU cartridge
- will contain a 65C816 8/16 bit CPU, not the earlier mentioned 65C02
- 8-bit CPU.
-
- Issue 12 should be subtitled the "SuperCPU" issue. We think its
- great, but it's definitely not subtle. Doug Cotton and Mark Fellows
- preview the unit while Jim Brain details the CPU inside it. CMD
- ntes that the 10 MHz version has been scrapped, but the 128 version
- has been added, dealying introduction until April for the 64 version.
- C=H was hoping to review a prototype unit this issue, but we'll do it
- next time. Jason Compton and Katherine Nelson describe HTML, the
- markup language for World Wide Web pages, and Jim Butterfield explains
- using KERNAL devices 0 (keyboard) and 3 (screen). For those wanting
- to run a Bulletin Board System, Max Cottrell describes how to ensure
- success. Of special interest in this issue is a photo of the prototype
- accelerator. We won't even hint of our opinions on this round of
- funky graphics....
-
- @(A): Driven
- Driven #11 waxes somewhat philosophic about the demo scene in 1995. The
- tone expresses a tinge of disappoinment with the hope that 1996 will
- be a better year for demos. This issue also ushers in Driven's first
- crack at covering the PAL scene. As part of the 1995 year-end review,
- a complete list of releases is given. In the news section, Charles
- Christianson's blurb on the CMD SuperCPU is reprinted, and King Fisher
- of Triad discusses the origins of the demo scene in "Cyberpunk".
-
- If you've ever wondered what goes on inside the mind of a demo "scene"
- programmer, Driven #12 will fill you in. Interviews with Phantom of
- the group FOE and Zyron of F4CG are included, both telling it as it is.
- For those wanting to set up or design a BBS system Mitron takes a look
- at CNET DS2 and details some general guidelines on how the networking
- code works. Of special note is a review of this issue's Polygonamy
- sample code (Reference: polygon).
-
- @(A): LOADSTAR
- Issue 139 starts off with the announcement that LOADSTAR is taking over
- the dieHard Spinner disk subscriptions, as reported in C=H#11. File
- Base 64 from John Serafino will be useful for anyone organizing their
- disk collection. Fender Tucker claims it is better than DCMR, the
- supposed standard. Jeff Jones cooks up the "Ultimate INPUT" for people
- wanting the perfect BASIC INPUT routine. The claims are substantial and
- Jeff delivers. The included LOADSTAR LETTER #29 contains another
- article in the Internet series.
-
- As we started Issue 140, we noticed something was different. We
- couldn't place it at first, but then Jeff alerted us to the change.
- LOADSTAR now has highlighted words in the text, and the color scheme
- can be changed and saved. Nice for the eyes. In addition, LS#140 can
- mark up text using highlights, bold, and underline on printers that
- support such features. Bob Markland presents a ML module that
- provides better random numbers, and Fender Tucker challenges
- programmers ML programmers to write a routine that searches an in
- memory dictionary for a word. Speed is the key. C=H gets some space,
- as Issue 11 is reprinted in the 3.5" version. Of particular note to
- programmers is Don Forsythe's "Hidden Clocks" article that describes
- in detail the CIA TOD clocks and their bugs, err "features".
-
- It's funny, but the LOADSTAR LETTER #40 that comes with LS #140 is
- subtitled "Special Commodore Hacking Issue". We were expecting C=H
- articles, but that shows just how egotistical we can be. Jeff Jones
- filled the issue with rumors of new products, handy tips, and
- information about CMD's SuperCPU. Of particular interest is the
- information about Craig Bruce modifying his Swiftlink to do 115,200 bps.
-
- Right before we went to press, issue 141 showed up in the mailbox. #141
- starts off with the changes of operation since LOADSTAR publication
- was taken over by J & F Publishing. The first is their new address:
-
- LOADSTAR
- 606 Common Street
- Shreveport, LA 71101
-
- Also, they say checks should now be made out to LOADSTAR, not Softdisk.
-
- For all you TUI (Text User Interface) folks, Jeff Jones goes over how
- to create "buttons" that depress on screen when activated. Source code
- is provided as well, which is rare for LOADSTAR. Of particular interest
- to us was Terry Flynn's "Virtual Optics" slideshow. Hard to describe,
- it displays impossible constructions and 3D illusions. Even C=H gets
- some space, as issues 3 and 4 are available on the 3.5" disk version.
- Jim Brain supplies article 4 in the Internet series on LOADSTAR LETTER
- #31, included with the issue. Of special note is LOADSTAR's new
- Internet address, given in the LL as loadstar@softdisk.com. See
- Newsfront (Reference: news) for more information.
-
- @(A): LOADSTAR 128
- We loaded up LS128 #30 for a look-see. Dave's Term, the 128
- Telecommunications Program presented in the last 4 issues, seems to be
- one focus of this issue. Don Graham supplies a keyboard overlay and
- macros for the terminal program, while David Jensen includes a spell
- checker. In the issue as well is ZED, the 128 editor of editors from
- Craig Bruce.
-
- @(A): Vision
- At press time, Issue #8 was in the works, so we'll detail the contents
- next time.
-
- Other magazines not covered in this rundown include:
-
- * _The Underground_
- * _Gatekeeper_
- * _Commodore Network_
- * _64'er_
- * _Atta Bitar_ (_8 bitter_)
- * _Commodore Zone_
- * _Commodore Gazette_
-
- In addition, others exist that C=Hacking is simply not aware of. As soon
- as we can snag a copy of any of these, or get the foreign language ones
- in English :-), we will give you the scoop on them.
-
- ============================================================================
-
- @(#): Polygonamy: A Study in 3 Dimensions
- by Stephen L. Judd (sjudd@nwu.edu)
-
- We've been making some pretty small potatoes for a while now, so
- the time has come for a little more ambition and challenge. I decided to
- think up a real challenge, containing problems that I had no idea how to
- solve, and see what I could come up with.
-
- I set out to create a 3D virtual world for the C64, e.g. a space
- populated with various three-dimensional objects, which I could wander around
- in. I wanted it to be full-screen 320x200 hires bitmapped. Furthermore, I
- wanted the objects to be solid, and since there are only two colors I
- wanted to be able to put patterns on the faces. I also wanted it to
- translate nicely to the 128's VDC chip, in 2MHz mode. Finally, naturally, I
- wanted the program to be fast. This was the framework in which I placed
- myself, and a few other ideas presented themselves along the way. The
- outcome of all of this is Polygonamy.
-
- Just a brief history of this project: I have wanted to do a 3D
- world for a very long time, and have been thinking about it for some
- time in the back of my head; my imagination was probably first fired
- the first time I played Elite. I wrote down the necessary equations one
- afternoon last summer, for a high school student I was teaching, and
- the equations are very simple. I took a break to get some work of
- measureable value accomplished, but in October I began work on the graphics
- algorithm. I worked steadily on this for two months, and in December I
- finally began to code the graphics. In mid-January, I got them to work.
- Adding the rest took a few weekends more. I have about 128 pages of notes,
- analytical calculations, and BASIC test programs in my C64 notebook (which
- is, I think, a nice number of pages to have :). My original plans were
- to place five objects in the world, but time and memory constraints whittled
- that down to three. One of my disks self-destructed about the day I was
- ready to finish, so I had to reconstruct a bunch of tables, but other than
- that I finally managed to finish it up, albeit with a few rough edges ;).
-
- Although the concepts from previous articles are used as a solid
- foundation, the code is almost 100% from scratch -- I only borrowed a
- tiny piece of code from an earlier program, and even that I modified
- somewhat.
-
- One caveat before we begin: I am primarily interested in the
- challenge of designing the algorithms, which means I like to come up
- with my own solutions. Thus, you may find more efficient methods
- in a graphics book or perhaps in someone else's code; I have examined
- neither, so I have no idea what the relative merit of my algorithms
- may be. These are simply my solutions to challenges placed before me.
- And if you know of a better way to do things, please feel free to email
- me!
-
- Furthermore, I consider the code a test of the theory. Some of my
- assumptions work and some do not, and these will be considered at the end
- of this article.
-
- Finally, I am not including the source code. For one thing, it is big.
- Like, _HUGE_, man. I had to split it up when I ran out of editor memory
- on my 128 (which, incidentally, forced me to figure out Merlin 128's very
- cool and very powerful linker feature). I will include numerous code
- fragments in assembly and BASIC which demonstrate all the important
- concepts.
-
- By the way, if you are interested in measuring frame rates, you can
- use the first object. Every full 360 degree revolution is 128 frames.
- So time how long it takes to complete a full rev (or maybe several), and
- divide that number into 128, to get an idea of frames per second.
- For a rundown of frame rates for stock and SuperCPU operation, see
- "Underneath the Hood of the SuperCPU" (Reference: cmdcpu) found
- elsewhere in thi issue.
-
- Some brief acknowledgements: This project would not have happened without
- the extremely powerful macro and linking capabilities of the Merlin 128
- assembler, by Glen Bredon. It would have been _really_ tough without
- JiffyDOS and my FD-2000, from CMD. I used my Action Replay extensively
- for debugging, and without the excellent documentation for the 64, such as
- the PRG and Mapping the 64, this would have been a nightmare. Finally, I
- must acknowledge my friend George Taylor; a few days before I was all
- finished I explained some routines to him, and he made a great suggestion
- which made my fast fill routine blaze.
-
- Okay, WAY too much talk. There are a ton of issues involved with this
- project so let's just wade in hip-deep and deal with them as they come.
-
- @(A): The Equations
- -------------
-
- First some relaxing abstraction. In previous articles we have discussed
- how to project an object in three dimensions through the origin into a
- plane. We have also discussed rotations in three dimensions. In
- principle, then, we have all the mathematics we need to do a 3D world.
-
- But we should be thoughtful. Let's say we're standing in the world and
- turn to the right; we can either rotate ourselves, and change the
- direction we are looking, or we can rotate the world around us, so that
- we are always looking 'forward'. This may bother you on physical grounds,
- but the two are mathematically equivalent. Given the way we have derived
- our projection routines, it should be clear that we want to rotate the
- objects in the world around us.
-
- (Or, to put it another way, we are at the center of the world, and the
- world revolves around us.)
-
- We have another issue: how do we know when an object is visible or not?
- How do we know when we've bumped into an object (or blown it out of the
- sky :)? Moreover, if we have ten objects, and each object has six points,
- it would be a real drag to have to rotate all sixty points, especially
- if none of the objects were even visible.
-
- It should be clear that we really want to define every object relative
- to some center of the object. So we keep track of the center of each
- object, and rotate and translate the centers, and only calculate the
- full object if it is visible. We of course want to define the object
- relative to this center.
-
- What happens to this center when we translate or rotate the world?
-
- Let's simplify our model a little bit and only deal with rotations about
- one axis, e.g. we are driving a tank and can move forwards and backwards,
- and turn left or right. The generalization to other axes is very
- straightforward, but this way we can think in two dimensions instead
- of three.
-
- First we need to agree on a coordinate system. For my system I let the
- x-axis go _up_ a page of paper, the y-axis comes up out of the page, and
- the z-axis goes from left to right. Thus, I am standing on the paper in
- the x-z plane, at the origin, with the y-axis extending upwards from me.
- If you still don't understand my orientation, draw a little picture.
-
- I am going to choose my orientation so that I am always looking straight
- down the x-axis, e.g. in the direction that x is increasing. Thus, if I
- walk forwards or backwards, this corresponds to decreasing or increasing
- the x-component of the center coordinate:
-
- let C=(cx,cy,cz)
- move forwards => cx=cx-1
- move backwards=> cx=cx+1
-
- So far so good. As always, draw a picture if you can't visualize it.
- That takes care of translations, what about rotations?
-
- We certainly know how to rotate points about the origin. In particular,
- if we have a point with coordinates (x1,z1) and rotate it clockwise by
- an angle s, we get the new point as follows:
-
- (x1,z1) -> (x1*cos(s)+z1*sin(s), z1*cos(s)-x1*sin(s))
-
- So that's easy enough. The problem is that we have this big object
- sitting around this point, and need to figure out what to do with it!
-
- Consider the following: let's say we have a line out some distance from
- the origin,
-
- X
- X
- | X
- z-axis ----O------------c---- c=center
- | X
- | X
- Origin X <---- line
-
- and we rotate it by some amount theta about the origin:
-
- X
- XX
- Xc c=rotated center
- | XX
- z-axis ---O------------XX-
- | X
- XX
-
- You can see (from my incredible ASCII artwork) that the line is now at an
- angle with respect to the origin.
-
- Imagine that we draw a line from the origin to the center of the point,
- in the first picture (or get a pencil and paper and actually do it), so
- that we have the letter "T" laying on its side. Now we rotate this "T"
- by some angle theta, so that the top of the "T" -- our line -- has now
- been rotated.
-
- The stem of the "T" meets the top of the "T" at the center point c. Drop
- a line from the rotated center straight down to the z-axis, and call this
- line l2. Since the T is at a right angle, and we have rotated it by an
- angle theta, the angle between our line and the z-axis is 90-theta. But
- this means that the angle between our line (the top of the "T") and the
- line l2 is just theta.
-
- Thus, if we rotate the center by an amount theta, all we have to do
- is rotate the object by an amount theta *about the center*, and our
- perspectives will all be correct. How is that for simple? It should
- be clear now that this works no matter where the "center" of the object
- is chosen. Thus, our center is not some physical center of the object,
- but rather the center of rotation of the object.
-
- Since this is true of rotations about any axis, we now know how to
- generalize to higher dimensions.
-
- Note further that we can now implement local rotations -- that is, let's
- say the object is a tank, and this tank turns independently of whether
- or not we turn. Piece of cake.
-
- You can also see that the rotations are cumulative. If we turn to the
- left, and then turn left again, we can simply apply two rotations to the
- points of the object. In fact, if we turn left, move forwards, and then
- move left again, we still apply just two rotations to the points of the
- object; the center, however, has moved.
-
- This is quite important, as it allows us to measure an object's relative
- rotation to us, whether or not it is visible. Remember that we only
- want to rotate the points that define an object when the object is
- visible. We never actually change the points which define an object.
- Instead, we track how much the object needs to rotate, and rotate the
- original points by that amount.
-
- The center of the object will change with each rotation and translation.
- We never change how we define an object about this center, though. We
- simply apply a rotation to the original points when appropriate. The
- object centers must be kept track of because they can undergo translation
- as well as rotation.
-
- To summarize then: we define each object relative to a center of
- rotation. The center determines where the object is located in the
- world, and allows us to operate on centers when we need to rotate or
- translate the world. It also lets us perform local operations on an
- object, so that we could, for instance, have a spinning cube located
- inside our world. If an object's center is visible then we can consider
- the object to be visible, and plot it.
-
- Whoops -- what does it mean to be 'visible'? Well, think about yourself.
- You can see things when they are in front of you. Or, to be more
- precise, you have a field of vision. Perhaps a decent model of this
- would be a cone. I think a better model, certainly one which is
- easier to deal with computationally, is the intersection of two planes:
- a pyramid. Anything which lies within this pyramid we consider visible,
- and anything which lies outside we consider not visible.
-
- Two-dimensionally, we draw a little wedge extending from the origin.
- Anything within the wedge we count as visible, and anything outside
- of it we count as not visible. The sides of this wedge are two lines,
- with equal but opposite slope (i.e. slope=+/-m).
-
- \ Visible /
- \ View / Outside of visual area
- \Area /
- \ /
- \ /
- * <--- Me
-
- Probably lines at some angle are more reasonable than others. But I'm a
- simple guy, and the two simplest lines I can draw are at 45 degree angles
- from the axis, so their slope is +/-1. Thus, any points which lie
- between the lines x+z=0 and x-z=0 are visible. If the center of an
- object is within this area, we will consider the object visible. That
- is, if cx+cz>0 and cx-cz>0 the object is visible.
-
- One last thing: if we are too close to the object, we either want to
- bump into it (i.e. not move) or else not display it. So we also need to
- check if cx<x0 for some x0.
-
- We are now in a position to write some simple code. I wrote the
- following in evil Microsoft QBasic, but BASIC7.0 on the 128 would work
- just as well, although you need to change the variables (I didn't have my
- 128 handy, otherwise I would have written this on the 128):
-
- @(A): Polygon Prototype Code
-
- SCREEN 1 '320x200
-
- delta= 3 'Rotations will be in 3 degree increments
- rad= 3.1415926/180
- cdel= COS(rad*delta)
- sdel= SIN(rad*delta)
- theta=0
- d=-135
- x0= 60 'Bumped into the object?
- REM z0 y0 would be 160,100 to place the object in the center
- REM of the screen
- y0= 170 'I want the bottom of screen to be ground
- z0= 160
-
- REM Set up the object
- REM Tetrahedron: 0,sqrt(3),0 0,0,1 0,0,-1 2,0,0
- DIM obx(4), oby(4), obz(4)
-
- obx(1)= 0
- oby(1)= 50*SQR(3)
- obz(1)= 0
- obx(2)= 0
- oby(2)= 0
- obz(2)= 50
- obx(3)= 0
- oby(3)= 0
- obz(3)= -50
- obx(4)= 100
- oby(4)= 0
- obz(4)= 0
-
- cx= 100
- cy= -10
- cz= 0
-
- REM Get input
- main:
-
- DO
- a$=INKEY$
- LOOP UNTIL a$<>""
-
- IF a$="[" THEN cx=cx-20
- IF a$="/" THEN cx=cx+20
- IF a$=";" THEN GOSUB rotl
- IF a$="'" THEN GOSUB rotr
-
- IF cx<x0 THEN CLS: GOTO main:
- IF cx<cz OR cx+cz<0 THEN CLS: GOTO main:
-
- ctheta= COS(rad*theta)
- stheta= SIN(rad*theta)
-
- p1x= cx + ctheta*obx(1) + stheta*obz(1) 'Rotate and add to center
- p1y= cy + oby(1)
- p1z= cz + ctheta*obz(1) - stheta*obx(1)
- p1y= y0 + d*p1y/p1x 'Project and add offset
- p1z= z0 + d*p1z/p1x
- [... similar for p2x,p2y,p2z,...,p4x,p4y,p4z]
-
- CLS
- LINE (p1z, p1y)-(p2z, p2y)
- [... lines between p2-p3, p3-p1, p1-p4, p4-p2, p4-p3]
-
- GOTO main: 'Main loop
-
- REM rotate left
- rotl:
- theta= theta + delta
- blah= cdel*cx + sdel*cz
- cz= -sdel*cx + cdel*cz
- cx= blah
- RETURN
-
- rotr:
- theta= theta-delta
- blah= cdel*cx - sdel*cz
- cz= sdel*cx + cdel*cz
- cx= blah
- RETURN
-
- (You may note that cx=cx+20 is used for a translation, instead of cx=cx+1.
- This will be detailed later).
-
- So much for the easy part.
-
- @(A): Filling
- -------
-
- If there is one thing that the previous programs have taught us, it is
- that graphics are slow. At least, they are far and above the major thing
- slowing down the program, and deserve the most attention and thought for
- improvement. Moreover, because there is lots of looping involved, the
- elimination of just a few instructions can translate to thousands of
- cycles saved.
-
- We have examined several fill routines up to now, but neither of them is
- up to the task of Polygonamy. The cookie-cutter method is OK, but doesn't
- allow multiple objects, and certainly doesn't allow pattern fills. Using
- an EOR-buffer is just plain slow and inefficient and a big drag. So it's
- time to rethink this problem.
-
- Recall that on the 64 the bitmap screen is divided into 8x8 cells, which
- are arranged horizontally in rows. It's a pretty kooky way of doing
- things, but we shall overcome.
-
- First of all it should be clear that we want to fill from left to right
- (as opposed from top to bottom). We can then fill a byte at a time,
- instead of dinking in little pixels at a time.
-
- Previously we used a custom character set to plot into. One of the major
- reasons for doing so was to use Y as the Y-coordinate, so that storing a
- particular point was as simple as STA COLUMN,Y. We can still use this
- idea, but only within each row. That is, if we let Y=0..7, we can address
- each individual pixel-row within each 8x8 block row with an STA ADDRESS,Y.
-
- For real speed, we are going to want an unrolled fill routine. That is,
- we don't want to mess around with loop counters and updating pointers and
- such. Since there are 25 rows on the screen (25 times 8 = 200 pixels
- high) we are probably going to need 25 separate fill routines.
-
- I constructed my fill routine as follows:
-
- STA COL1,Y
- DEX
- BEQ :DONE
- STA COL2,Y
- DEX
- BEQ :DONE
- STA COL3,Y
- ... etc.
- :DONE RTS
-
- Thus X would be my counter into the number of columns to fill, A can
- contain our pattern to fill with, and Y can range from 0..7 to index the
- individual rows within the block. The first thing to notice is that each
- STA/DEX/BEQ code chunk is six bytes. So, all we need to do is calculate
- which row to start filling at, multiply by six, and add that number to
- the start of the fill routine. The idea is then to jump into the correct
- place in the fill, and let it fill the right number of columns, stored in
- X.
-
- There is a little problem though -- what we're talking about doing is an
- indirect JSR, and there is no such thing. But it's easy enough to fake,
- because we can use an indirect JMP. So a call to the fill routine would
- look like the following:
-
- ...
- JSR FILL
- ...
- FILL JMP (ADDRESS)
-
- where ADDRESS simply points to the correct entry point in the fill routine.
-
- Moreover, you may also note that 40 columns times 6 bytes/column is 240
- bytes, so that each little fill routine handily fits in a page. Thus,
- moving between rows in the bitmap corresponds to a simple decrement or
- increment of the high byte of the ADDRESS pointer.
-
- This was the state of things when, days before I was to be all done with
- Polygonamy, I mentioned it to my friend George Taylor, who suggested the
- following modification: instead of using X to count how many columns to
- fill, just make the fill routine:
-
- STA COL1,Y
- STA COL2,Y
- STA COL3,Y
- ...
-
- Then, insert an RTS into the right place in the routine. Thus, we
- calculate which column to stop filling at, multiply by three, and stick
- an RTS in the fill routine at that point. To fix it up we stick an
- STA ..,Y back on top of the RTS.
-
- I don't think you're going to make a fill routine faster than that :).
-
- Moreover, note that each fill routine takes up just 120 bytes, so we can
- now fit two fill routines in each page. I did not do this, but it is
- easy to do, and instantly frees up 25 pages.
-
- @(A): Filled Polygons
- ---------------
-
- I mean, hey, this _is_ "Polygonamy", so let's talk polygons, and lots of
- them.
-
- Clearly all that is needed to draw an object are the left and right
- endpoints of the object, since everything in-between will be filled.
-
- An observation to make is that if you take a slice out of a convex
- polygon, the slice will intersect the polygon at exactly two points.
- Another, more important, observation is to note that the highest and
- lowest point of a polygon will always be at a vertex. Finally, it is
- important to note that any vertex of a polygon has exactly two lines
- extending out of it, one to the left, and one to the right.
-
- Consider a piece of a polygon:
-
- \ /
- \ /
- \ /
- \ /
- \ /
- * <--- Vertex v0
-
- where the vertex v0 is the lowest point of the polygon. All that needs
- to be done is to move upwards (DEY), compute the left and right points
- of the polygon at that point, and then fill between the two (JSR FILL).
-
- The idea then is to start at the bottom (or the top) and to steadily move
- upwards while _simultaneously_ calculating the endpoints of the left and
- right lines, and filling in-between. But we need the equations of the
- left and right lines to do this.
-
- Now it's time for another observation. Let's say we have a polygon with
- n vertices v1, v2, ..., vn, and furthermore that as we move between these
- points we move around the polygon counter-clockwise. Thus v3 is to the
- right of v2, v1 is to the left of v2, v4 is to the right of v3, etc.
- For example:
-
- v1____v3
- \ /
- \/
- v2
-
- What happens if we rotate this polygon?
-
- v2____v1
- \ /
- \/
- v3
-
- The vertices have changed position, but *their order has not*. v3 is
- still to the right of v2, and v1 is still to the left.
-
- Now we have a real plan. We simply define the polygon as a list of
- points v1 v2 v3 ... vn. We then figure out which one is lowest, i.e. has
- the smallest (or greatest) y-coordinate, call this vertex vm (vmax). The
- endpoints of the left and right lines are vm-1,vm and vm,vm+1. So move
- along those lines until the next vertex is reached. At that point,
- recompute the appropriate line, and keep moving upwards until the top of
- the polygon is reached.
-
- Perhaps an example would be helpful:
-
- v1
- |\
- | \ v3
- | /
- |/
- v2
-
- v2 is the minimum. The left line has endpoints (v1,v2) and the right
- line has endpoints (v2,v3). We steadily move along the left and right
- lines as we creep upwards. At some point we hit v3, and at this point
- we compute a new equation for the right line, this time with endpoints
- (v3,v1). Now we continue to creep upwards and move along the left and
- right lines, until we hit v1, at which point we are finished.
-
- It is important to keep in mind that the order of the points never
- changes. We don't need to do anything complicated like sorting the
- points; we only need to find the lowest point, and branch left and right
- from there, keeping in mind that the points are cyclic (i.e. v1 is to the
- right of vn).
-
- It is now time to start thinking about code. One aspect of the fill
- routine we haven't considered is the clear. In the past the entire draw
- buffer was cleared and then the new stuff was drawn into it. But this
- seems like a bit of a waste; it seems wasteful to clear a bunch of memory
- that is just going to be overwritten again. So, as long as we can do it
- efficiently, it might be smart to combine the clear and fill routines.
-
- Here is how Polygonamy does it: If a line needs to be cleared, then it
- is cleared up to the edges of the object, but the part that is going to
- be filled is ignored. (It isn't clear if this provides any substantial
- efficiency gains, though).
-
- To see the status of a particular line, a table is used, containing a
- value for each Y-coordinate. If the entry is 255 then the line is clear,
- if it's 0 then the line has old junk in it, and if it's 1 then the line
- has new junk in it. Thus we only clear the line if its entry in the fill
- table is a zero.
-
- So a fill routine might flow like the following:
-
- let Y count from 7..0
-
- If we are at the left endpoint then recalculate the left line.
- If we are at the right endpoint the recalculate the right line.
- Update xleft & xright
- If line needs to be cleared then clear line.
- If the starting fill column is different than the previous fill
- column then update the pointers, etc.
- Plot the left and right endpoints (since the fill routine only plots
- eight bits at a time)
- Fill the in-between parts
- Update Y
- If Y passes through zero then update fill entry point, set Y=7 etc.
- Keep going until we reach the top
-
- The next thing to figure out is how to calculate the left and right
- lines. We do have the old line routine, which we could use to advance
- to the left and right endpoints, but clearly this isn't too efficient.
-
- The question is: if the y-coordinate increases by one, then how much does
- the x-coordinate increase by? The equation of a line is:
-
- (y-y0) = m*(x-x0) m=slope
-
- or
-
- change in y = m*change in x
-
- So, if the change in y is 1, then then the change in x is 1/m. All we
- need to do then is calculate the inverse-slope=dx/dy, where dx=x2-x1 and
- dy=y2-y1, and add this to the x-coordinate with each step in y.
-
- Isn't this a fraction? Sure, big deal. The fraction can be written
- as dx/dy = N + Rem/dy, where N is an integer, and Rem is the remainder,
- which is always less than dy. So to calculate x=x+dx/dy:
-
- x= x+N
- xrem= xrem+Rem
- If xrem>=dy then x=x+1:xrem=xrem-dy
-
- As usual, we want to start xrem at dy/2, which has the effect of rounding
- numbers up.
-
- 10 REM LINE ROUTINE TAKE TWO SLJ 11/24/95
- 12 REM ACTUALLY IT'S A FILL RTY NOW
- 15 GRAPHIC 1,1
- 20 X0=160:Y0=100
- 30 X1=5:Y1=-50:X2=7:Y2=11:XL=X1:YL=Y1:Y=Y1
- 35 X3=50:Y3=Y1:X4=X3+100:Y4=Y2:XR=X3:YR=Y3
- 40 D1=Y2-Y1+1:DX=X2-X1:LI=INT(DX/D1):LR=DX-LI*D1
- 45 TL=INT(D1/2)
- 46 D2=Y4-Y3+1:DX=X4-X3:RI=INT(DX/D2):RR=DX-RI*D2
- 48 TR=INT(D2/2)
- 50 DRAW1, X0+X1,Y0-Y1 TO X0+X2,Y0-Y2, X0+X3,Y0-Y3 TO X0+X4,Y0-Y4
- 60 REM MAIN LOOP
- 70 XR=XR+RI:TR=TR+RR:IF TR>=D2 THEN TR=TR-D2:XR=XR+1
- 75 DRAW1, X0+XL,Y0-Y TO X0+XR,Y0-Y
- 80 XL=XL+LI:TL=TL+LR:IF TL>=D1 THEN TL=TL-D1:XL=XL+1
- 90 REM DRAW1, X0+XL,Y0-Y TO X0+XR,T0-T
- 100 Y=Y+1:IF Y<=Y2 THEN 60
-
- In this program (x1,y1)-(x2,y2) is the left line, and (x3,y3)-(x4,y4) is
- the right line. The first thing to note is that in lines 40 and 46,
- Y=y2-y1+1. This issue was discussed in the very first C=Hacking
- 3D-graphics article. The problem is that although the line will be
- anatomically correct with DY=y2-y1, it will look silly. The easiest way
- to see this is to consider y2-y1=1, e.g. say we draw a line between
- (0,10) to (50,11). Ideally this line will consist of two line segments,
- one from (0,10) to (25,10) and the other from (26,11) to (50,11). But ifi
- we use DY=1 we will have one line segment from (0,10) to (50,10), and a
- single point at (50,11).
-
- Adding one to DY is just a simple cheat. Most of the time the lines will
- look just fine, but lines which have a slope near one will come out a bit
- wrong. The other, accurate solution, which was used in the first
- article, is more complicated to implement in this routine. Adding one to
- DY will also have a useful benefit which we shall shortly see.
-
- In line 50 above the boundaries of our object are drawn in, to check the
- accuracy of the algorithm.
-
- In lines 70-80 the right point is updated, then the thing is filled, then
- the left point is updated. This is because both lines are moving to the
- right, e.g. they both have positive slope. Think about how the line
- segments will be drawn; in general, we want to draw from the left end of
- the left line segment to the right end of the right line segment.
- (Sometimes this will look a little off where the two lines meet).
-
- Since the left and right lines can each have either positive or negative
- slopes, there are four possibilities: Plus-Plus, Plus-Minus, Minus-Minus,
- and Minus-Plus.
-
- Plus-Plus: Update right, fill, then update left
- Plus-Minus: Fill, update left, update right
- Minus-Minus:Update left, fill, update right
- Minus-Plus: Update left, update right, fill
-
- If this is still confusing, try out the above program with various left
- and right line segments, and these things will jump right out.
-
- Now we need to think about implementing this in assembly. Since this is
- being done in hires 320x200, the x-coordinate requires two bytes, and the
- y-coordinate requires one. We also need another byte to store the
- remainder portion of the x-coordinate.
-
- The most glaring question is the calculation of dx/dy: somehow we need a
- fast way of exactly dividing an eight bit number dy into a nine bit
- number dx. Recall that we always add one to dy, so that dy actually
- ranges from 2 to 200. Since the maximum value of dx is 320 or so, the
- largest value of dx/dy that we can have is 320/2 = 160. In other words,
- both the integer and remainder part of dx/dy will fit in a byte. Simply
- adding one to dy makes life pretty easy at this end.
-
- One very fast method of doing division is of course by using logarithms.
- But they have a problem with accuracy. One the other hand, one thing we
- know how to do very quickly is multiplication.
-
- This then is the plan: use logarithmic division to get an estimate for N,
- the integer part. Then calculate N*dy, compare with dx, and adjust the
- integer part accordingly.
-
- A quick reminder of how logarithms can be used for division:
-
- log(a/b) = log(a) - log(b)
- exp(log(x)) = x
-
- thus
-
- a/b = exp(log(a)-log(b)).
-
- How do we take the log of a 9-bit number? We don't. Instead, we
- construct a table of f(x)=log(2*x), and use, not x, but x/2, as a
- parameter. Remember that the logarithms merely give an estimate to the
- integer part.
-
- Moreover, if the tables are constructed carefully we can insure that the
- estimate for N is either exact or too small. Thus we only need to check
- for undershoots, which simplifies the calculation considerably. In
- particular, the tables were constructed as follows:
-
- 10 DIM L1%(160), L2%(200), EX%(255): C=255/LOG(160)
- 20 FOR I=1 TO 160
- 30 L1%(I)=INT(C*LOG(I))
- 40 NEXT
- 50 FOR I=2 TO 200
- 60 L2%(I)=INT(C*LOG(I/2)+0.5)
- 70 NEXT
- 80 FOR I=0 TO 255
- 90 EX%(I)=INT(EXP(I/C))
- 95 IF(I=129)OR(I=148)OR(I=153)OR(I=81)OR(I=98)THEN EX%(I)= EX%(I)-1
- 100 NEXT
- 110 L2%(3)=L2%(3)+1
-
- The constant C is needed obviously to improve accuracy (log(160) simply
- isn't a very large number). Note that I divided the arguments of the
- logarithms in half; instead of calculating 2*dx/dy I calculate dx/(dy/2),
- which is of course the same thing. This was done to make C work out.
- By 'fixing' the tables in this manner, exactly 3927 calculations will
- undershoot, which works out to about 6% of all possible calculations we
- may perform.
-
- The actual division routine works out pretty slick in assembly:
-
- DIVXY MAC ;Macro to compute 2*X/Y
- LDA LOG1,X ;This is the division part
- SEC
- SBC LOG2,Y
- BCS CONT
- LDX #00 ;dx/dy < 1
- LDA ]1 ;LDA dx, since dx is exactly the remainder
- BCC L2
- CONT
- TAX
- LDA EXP,X
- TAX ;X is now integer estimate
- STA MULT1
- EOR #$FF
- ADC #00 ;Carry is guaranteed set
- STA MULT2
- LDA ]1 ;ldxlo or rdxlo (i.e. low byte of dx)
- ADC (MULT2),Y
- SEC
- SBC (MULT1),Y ;Calculate remainder
- L2 CMP ]2 ;ldy or rdy (i.e. ]2 = dy)
- BCC DONE
- L1 INX ;Remainder is too large, so up int estimate
- SBC ]2 ;and subtract dy
- CMP ]2 ;Repeat until remainder<dy
- BCS L1
- DONE <<< ;Now X contains integer, A remainder
-
- Do you see how it works? First the initial guess N is calculated. If
- log(x) - log(y/2) is negative then dx/dy is less that one, so the
- remainder is simply dx and the integer part is zero. Otherwise,
- R= dx - N*dy is calculated. Since N always undershoots, dx-N*dy will
- always be positive, so the high byte of dx isn't needed. This quantity
- R is the remainder, so if it is larger than dy simply increase the
- integer estimate and subtract dy from R, and repeat if necessary.
-
- The end result then is a 9-bit/8-bit divide which takes 52 cycles
- in the best case. Pretty neat, huh? And quite adequate for our
- purposes.
-
- Wait just a minute there, bub... what about when dy=0? Consider what
- dy=0 means: it means that two vertices lie along the same line. That in
- turn means that the next vertex can be immediately skipped to. That is,
- simply move on to the next point in the list, be it to the right or to
- the left, if dy=0.
-
- Well, ah reckon that that just about completes the polygon fill routine.
- To summarize: start at the bottom (top, whatever) of the polygon.
- Calculate the "slopes" of the right and left lines from that point.
- Update the coordinates, fill the in-between parts, and plot the
- end-sections. Then update Y and keep going. If another vertex is hit,
- then recalculate the corresponding line.
-
- Alert people may have noticed that this algorithm translates very nicely
- to the 128's VDC chip.
-
- I should probably briefly mention the pattern fills. I use Y as an index
- to a pattern table, so it was very natural to use 8x8 character patterns.
- With different indexing of course more complicated patterns can be used.
- Moreover, it dawned on me that animated patterns were just as easy as
- normal ones, so I tried to think up a few interesting animated patterns
- (there are two in Polygonamy, each pattern is eight frames).
-
- So that's the graphics part, more or less.
-
- We ain't even CLOSE to being done yet.
-
- @(A): 3D Code
- -------
-
- Now it's FINALLY time to start writing the master program to control the
- 3D world. Luckily we have the BASIC program from waaaay up above to
- work from.
-
- First is to decide how angles will be measured. The smart thing to do is
- to let the angle variable vary between 0..127 or 0..255; that is, to
- measure angles in units of 2*pi/128 (or 2*pi/256). The reason this is
- smart is because the angle is now periodic, wrapping around 256. Angles
- can be added together without checking for overflow, etc. (257=1, 258=2,
- 259=3, etc.). Note that in previous programs I did a very dumb thing
- and let the angle variable vary from 0..119, so angles were measured in
- three degree increments, and I had to place all sorts of checks into the
- code. Polygonamy uses angle increments of delta=2*pi/128.
-
- Next there is the issue of cx=cx+20 instead of cx=cx+1. The problem is
- that if cx=cx+1 is used it takes forever to move around in the world.
- Moreover, the objects get really small at around cx=5000. What this
- means is that in the assembly version we can use a single byte for cx,
- and just treat each unit of cx as 20 "real world" units. That is, in
- the assembly program, we will keep track of cx/20 instead of cx.
-
- Sort-of.
-
- Consider the rotation which takes place when we turn left or right: the
- world is rotated through an angle delta=2*pi/128, so the calculation is:
-
- blah= cdel*cx + sdel*cz.
- cz= -sdel*cx + cdel*cz
-
- The problem is that sin(2*pi/128)=0.049 and cos(delta)=0.9988, which
- means that, in practice, cdel*cx=cx. Equally bad is that sdel*cz is very
- small when cz starts to get small (e.g. 10*sdel = 0.49). The result of
- this is that objects close to the origin (e.g. us) will not be rotated at
- all!
-
- Thus the centers need to be calculated more accurately. In particular, a
- second byte is needed to store the 'decimal' part of the center. To be
- precise, this second byte will contain the decimal part of the center
- times 256. This way we can add and subtract remainders and any over- or
- underflows will then affect the integer parts cx,cy,cz.
-
- Very quickly we should decide how to represent remainders of negative
- numbers. A number like -1.5 can be represented as -1 - 0.5, but it can
- just as well be represented as -2.0 + 0.5. By using the second method
- remainders are always positive, and that's the smart way to do things (if
- nothing else it lets the remainder be a fraction of 256, instead of a
- fraction of 128). It's also the way any computer will round: type
- INT(-1.5) and see what happens.
-
- further question arises about how to represent the centers, specifically,
- how do we represent an object which is behind us, e.g. has a negative
- value for cx. The normal way to represent negative numbers is of course
- to use 2's complement notation, but this has some disadvantages. One of
- them is multiplication: recall that in an earlier code some really fancy
- footwork needed to be done just to be able to multiply numbers between
- -64..64, and we certainly want the centers to range over more numbers
- than that. This gets worse if we decide to use more bits to represent
- the centers, as we must do if a larger world is constructed.
-
- Moreover, Polygonamy is an excuse for testing new and different ideas and
- investigating their strengths and limitations, so why not try something
- different. As I look through my notes I'm not really sure what motivated
- this choice, but how about the following: let's add 128 to all of our
- numbers.(I think this is called excess-128 notation). -2 will be
- represented as 126, -1 will be represented as 127, six will be
- represented as 134, etc.
-
- Shifting between the excess numbers and 'real' numbers is as simple as
- EOR #128. Recall that to multiply two numbers, let f(x)=x^2/4, so that
- a*b = f(a+b) - f(a-b). In the new system:
-
- xo = 128+x
- yo = 128+y
-
- which means:
-
- xo+yo = 256 + (x+y)
- 256+xo-yo = 256 + (x-y).
-
- The 256 added above can be thought of as the carry bit. What this means
- is that all that is needed is to construct a single function,
-
- f(x) = (x-256)^2
-
- where x=-255..255. We can now very quickly multiply signed numbers in
- the range -128..128, and with just a single (albeit 512 byte) table,
- using essentially the same multiplication procedure as before.
-
- Now the downside of this method: adding and subtracting excess-128
- numbers, and in particular checking for overflow.
-
- xo+yo = 256 + (x+y)
- if x+y >= 128 then we have overflow
- if x+y < -128 then we have underflow
-
- which implies:
-
- xo+yo >= 256+128 implies overflow
- xo+yo < 128 implies underflow
-
- with similar results for subtraction. Note also that after every
- addition or subtraction 128 needs to be either added or subtracted from
- the result, which either way corresponds to an EOR #$80. So it's a
- little more work to add numbers in this system. (Of course, adding
- normal numbers to excess-128 numbers is no problem, so INC and DEC work
- fine).
-
- Back to rotations. The most obvious thing to do is to create two tables:
-
- f(x) = (x-128)*cos(delta) + 128
- g(x) = (x-128)*sin(delta) + 128
-
- but remember that the remainders are also needed:
-
- fr(x) = 256*(remainder((x-128)*cos(delta)))
- gr(x) = 256*(remainder((x-128)*sin(delta)))
-
- Since remainders are always positive none of this excess-128 junk is
- needed. Note that we could also let f(x) and g(x) be 2's-complement
- tables, then convert from two's-complement into excess-128 after
- performing additions etc. The conversion is, what do you know, EOR #$80.
- This is the smarter thing to do, and an even smarter thing to do is to
- let the cosine table (f(x) above) to be in excess-128 format, and the
- sine table g(x) in 2's complement. This way the numbers can be added
- as normal, and no conversion need take place:
-
- * Compare to BaSiC subroutine rotl: above
-
- ROTL
- INC THETA
- LDY #NUMOBJS ;Y indexes the object
- DEY
-
- :LOOP LDX CX,Y ;center coordinate
- LDA CDEL,X ;CDEL = f(x) above
- LDX CZ,Y
- CLC
- ADC SDEL,X
- STA TEMP ;t1 = ci+si
- LDA CXREM,Y
- CLC
- ADC SDELREM,Y ;Add remainders
- BCC :CONT1
- INC TEMP
- CLC
- :CONT1 LDX CX,Y
- ADC CDELREM,X
- BCC :CONT2
- INC TEMP
- :CONT2 STA CXREM,Y
-
- LDX CZ,Y
- LDA CDEL,X
- LDX CX,Y
- SEC
- SBC SDEL,X
- STA TEMP2 ;t2=cz-si
- LDA CZREM,Y
- SEC
- SBC SDELREM,X
- BCS :CONT3
- DEC TEMP2
- :CONT3 LDX CZ,Y
- CLC
- ADC CDELREM,X
- BCC :CONT4
- INC TEMP2
- :CONT4 STA CZREM,Y
- LDA TEMP2
- STA CZ,Y
- LDA TEMP
- STA CX,Y
- DEY
- BPL :LOOP
-
- Well, that takes care of two lines of BASIC code :). As it turns out,
- using a single byte for the remainder does a pretty good job of holding
- the number. Rotating by 360 degrees one way, then rotating back again,
- produces a center which is within a few decimal places of the starting
- value.
-
- Next up: projections. The projection calcuation is:
-
- Proj(P) = d*(P+C)/(px+cx)
-
- where P=(px,py,pz) and C=(cx,cy,cz). In terms of the implementation, we
- want to calculate:
-
- d*((P-128) + s*(C-128)) / ((px-128) + s*(cx-128))
-
- where s=20, to translate C into the 'real world'. To calculate this,
- consider the following function:
-
- g(x) = r*d / (s*((px-128)/s + cx-128)) + 128
-
- where r is some scaling factor. The projection calculation then becomes:
-
- 1/r*( (g-128)*(P-128) + s*(g-128)*(C-128) )
-
- Thus we need some more tables, one of 1/(4r) * (256-x)^2, the other of
- s/(4r) * (256-x)^2, to do the multiplication. Furthermore a table of
- (x-128)/s would be pretty handy, and finally we need a table of
- g(x) = r*d/(s*(x-128)) + 128.
-
- The general outline of a program would be:
-
- Get keypress
- 1- If translate, then update all cx's (just some INCs and DECs)
- 2- If rotate left or right, then rotate world
- 3- Update angles for global & local rotation matrix (e.g. theta)
- 4- Figure out which objects to display/construct a list
- 5- Call each object in turn
- 6- Update bitmap: clear out remaining garbage and swap bitmaps
-
- Numbers 1 and 2 are done. In number three, by global matrix I mean the
- object rotation that results from us turning left or right. By local
- rotation I mean rotations independent of whether or not we turn. The
- local rotation allows e.g. the octahedron to spin around in Polygonamy.
-
- Figuring out which objects to display is easy: just check to make sure it
- lies within the viewing cone/pyramid, that we are not too close, etc. If
- an object is to be displayed, it needs to be placed in a list. I
- constructed the list to make sure that objects which are farther away are
- drawn first; that way objects can overlap one another correctly. This
- was done via a simple insertion sort -- i.e. bump up objects in the list
- until the right spot is reached to insert the object.
-
- We have most of the tools to deal with #5. Handling an object consists
- of rotating and projecting it, then displaying it. Rotation is the same
- as it has always been, albeit now involving sixteen bits, and projection
- is described above. Then each polygon needs to be drawn, by sticking the
- points of the polygon into the polygon list, setting up the fill pattern
- and the pointer to the minimum Y-value, and calling the polygon fill
- routine. Of course, if the face is hidden then we certainly don't want
- to plot it.
-
- The minimum y-value can be found very easily while inserting the points
- into the point list -- just keep track of ymax and compare to each point
- as it is inserted.
-
- We have discussed several methods of calculating hidden faces --
- cross-product, rotated normal, parallel faces -- each of which involves
- looking at a vector normal to the face, and either projecting it or
- taking the dot product with a vector going to the origin. What a big
- pain in the butt, especially since values can be sixteen-bits, etc.
-
- Did you ever stop to wonder about what happens to all the previous
- polygon-fill calculations if the point-list is entered in reverse order?
- Quite simply, left -> right and right -> left. And what happens when a
- face is invisible? The polygon is turned away from our eye. The points
- in the polygon, which go counter-clockwise around the polygon, will go
- clockwise when the polygon is turned around. (I should point out that at
- least in my code the points on the polygon are actually done in
- clockwise-order, since projection reverses the points).
-
- So, we have hidden-faces already built-in to the polygon plot routine!
- In essence, we simply don't plot any polygon which the routine will freak
- out on. We can of course be systematic about this; within the plot
- routine:
-
- - Calculate the left and right lines.
- - Take a trial step along the left and right lines
- - If xleft < xright then we are OK, otherwise punt.
-
- In principle we only need to do this on the first calculation, and use
- some properties of the lines to make things easier (for instance, if the
- left line is moving left and the right line is moving right, and they
- emanate from the same point, we know the polygon is visible).
- Unfortunately, nasty situations can arise, for instance when the left and
- right slopes have the same integer parts. So a check needs to be placed
- within the fill code to make sure the left point doesn't get ahead of the
- right point. This is unfortunate, as every cycle counts in the fill
- code, but luckily there is (was) a natural place to put in a quick check.
-
- All that is left then is #6: run through the fill table, and clear any
- lines that still have old junk in them. Since I used two bitmaps as a
- double-buffer, all that is left is to swap the bitmaps, and do it all
- again.
-
- Et voila.
-
- @(A): Analysis and Conclusions
- ------------------------
-
- As you can see, the program is not without its flaws. The biggest one,
- I think, deals with the projection. Recall that I calculate px/s, where
- s=20, and add it to cx. My feeling was that px was going to be very
- small compared with cx, and so not modify the projection by much. But
- either this is a bad assumption, or the rotations are all screwed up,
- because certain rotations look a bit goofy. For instance, when you walk
- up close to the octahedron it starts to get jumpy, or wobbly. I note
- further that when you are far away from an object it looks much better,
- so that might be a way to fudge around the problem (e.g. make the value
- of d in the projection much larger).
-
- Speaking of rotations, the 'funky shake' which used to plague the old
- programs has now been fixed. For instance, a rotation in the y-direction
- would work well but at some point it would appear to start rotating
- backwards, then start going the right way again. The problem was due to
- an overflow in the calculation of the rotation matrix, in a term that
- looked like(sin(t1) + sin(t2) - sin(t3) - sin(t4))/4, and the solution is
- to split such terms into two, e.g. (sin(t1)+sin(t2))/4 -
- (sin(t3)+sin(t4))/4.
-
- Speaking further of rotations, I find the current system of rotation and
- projection unsatisfying, in particular too slow. Notice how much the
- program slows down when all three objects are visible; some 40 points
- are being rotated, both locally and globally, at this point. It is
- possible to reduce the number of matrix multiplications from 9 to 8 (and
- even lower, with lots of extra overhead), but I find this unsatisfying.
- A better method is needed...
-
- There is another bug somewhere in the global rotations which sometimes
- causes the objects to wander around -- occasionally I can get the ship or
- the octahedron to move close to the pyramid. Also, when you are really
- close to an object and turn, you might notice the curious effect of the
- object rotating by small amounts, and then jumping position by a large
- amount. This is due to the 'units of 20' that are used in the program;
- the remainder part of (cx,cy,cz) needs to be used here, and then the
- display will be smooth as well.
-
- Of course, if multicolor mode was used many of the calculations would be
- much simpler, since the screen x-coordinate would only require one byte
- instead of two.
-
- The program should be made more efficient memory-wise of course. Shoving
- the fill routines for each buffer together would help out, and a system
- for rotating points out of a list, similar to that used in the last 3D
- program, would greatly streamline things (although it would be a tad
- slower).
-
- There is still a minor bug or two in the fill routine, which causes
- little blue chunks to be taken off the ends of some polygons, but I
- didn't feel like tracking it down.
-
- Note that although Polygonamy only lets you run around in a plane,
- running around in a full three dimensions is quite simple to add. And,
- although there are only three objects in the world, it is all set up to
- deal with a lot more. In summary, I see no major problems standing
- in the way of doing reasonably fast 3D graphics on the 64.
-
- The object file for this article is available in "Hacking the Code"
- (Reference: code, SubRef: polycode) found elsewhere in this issue.
-
- ============================================================================
-
- @(#)usenet: UseNuggets
-
- COMP.SYS.CBM: The breeding ground of programmers and users alike. Let's
- see what topics are showing up this month:
-
- @(A): What is the HECK is BCD?
- As most ML programmers know, the 65XX CPU line has a arithmetic mode
- called "decimal mode", and is used to manipulate Binary Coded Decimal
- numbers (BCD). BCD numbers treat each nybble as a decimal digit.
- Possibel values for a byte than ar $00 to $99. Some fool asked on the
- group what earthly use BCD has on the 65XX CPU. Well, among other things,
- Willem-Jan Monsuwe shared this tidbit:
-
- I recall someone asking what the use of BCD (Binary Coded
- Decimal) was. I have here a 99-byte program that uses it to
- print out a number stored in the memory in decimal, with a
- maximum of more than 10^500 digits, Within 5 seconds ;).
- What's the use ?? Well, you can impress your friends by
- calculating the answer to the chessboard-problem ( 2^64
- - 1 or 0xFFFFFFFFFFFFFFFF ) within 0.06 of a second. Oh,
- and the maximum is pretty easy to overcome, with a slight
- code change, if anyone needs numbers greater than, oh,
- 509 digits.. ;)
-
- * = $1000
-
- SNUM = $1100
- BUFF = $1200
-
- PRINT = $FFD2
-
- SNUMPTR = $FB
- SNUMBF = $FC
- BUFFEND = $FD
-
- LDA #0
- TAX
- CLRBUFF STA BUFF,X
- INX
- BNE CLRBUFF
- SED
- STA BUFFPTR
- LDY #210
- STY SNUMPTR
- BYTELOOP LDA SNUM,Y
- STA SNUMBF
- LDY #8
- BITLOOP ASL SNUMBF
- LDX #0
- ADDLOOP LDA BUFF,X
- ADC BUFF,X
- STA BUFF,X
- INX
- BCS ADDLOOP
- CPX BUFFEND
- BCC ADDLOOP
- STX BUFFEND
- DEY
- BNE BITLOOP
- DEC SNUMPTR
- LDY SNUMPTR
- CPY #$FF
- BNE BYTELOOP
- CLD
- LDA #13
- JSR PRINT
- DEX
- LDA BUFF,X
- AND #$F0
- BEQ LOWNYB
- PRINTLOOP LDA BUFF,X
- LSR
- LSR
- LSR
- LSR
- CLC
- ADC #48
- JSR PRINT
- LOWNYB LDA BUFF,X
- AND #$0F
- CLC
- ADC #48
- JSR PRINT
- DEX
- CPX #$FF
- BNE PRINTLOOP
-
- @(A): Commodore's Can't Compute! (or can they?)
- OK, try the following on your beloved 128:
-
- print 23.13 - 22.87 hit RETURN
-
- Do you get .260000005?
-
- The resuling thread after this question was posed started to lean in the
- direction of attacking the arithmetic units of BASIC in the Commodore
- 8-bit machines. Then an eloquent post from Alan Jones
- (alan.jones@qcs.org) started to set the record straight. We can't
- express it any better than Alan:
-
- Recently, the C64/128 floating point arithmetic has been maligned
- here. The C64/128 has good floating point math. It uses 5 byte reals
- with a 4 byte (32 bit) mantissa. There are no bugs in the basic FP
- arithmetic. The reals ARE limited in range and precision. They are
- more useful than compters using 32 bit reals, but not up to IEEE
- standard arithmetic. IEEE FP arithmetic (double and extended
- precision...) would be much slower than our existing FP routines. Of
- course it might be possible to interface a hardware FPU to the new
- Super64/128CPU (65816).
-
- The other C64/128 FP routines, such as SIN, EXP, and functions that use
- them are not accurate to full 32 bit FP precision. When used with
- care, they are often accurate enough for engineering work.
-
- The most annoying inaccuracy may be the conversion between binary FP
- and decimal for I/O. BASIC only prints 9 decimal digits of a FP
- number, but our binary FP number has about 9.6 decimal digits of
- precision. What you see is not what you have! Of course there are
- some simple tricks that you can use to print the FP number with more
- decimal precision, and you could do I/O using HEX notation. If you
- save intermediate results for later use, make sure you write the FP
- values as binary rather than ASCII (converted to decimal).
-
- If you do accounting type stuff with dollars and cents, using binary FP
- with its limited precision and rounding can be anoying. If your
- results are off one penny, all of your work will be suspect. Our 6502
- family of CPUs also has decimal arithmetic. It can do decimal
- arithmetic exactly, although you may have to program it yourself. I
- think the Paperclip word Processor will do simple calculations with up
- to 40 decimal digits of precision.
-
- If you are using 64+ bit FP you can compute some things in a fast and
- sloppy manner. Some programs that work OK on an IBM PC or workstation
- need more careful attention when coded for a C64/128.
-
- Some numbers can not be represented exactly in binary FP formats of any
- precision. If you want to calculate:
-
- a:=(1/3)*(1/5)*(1/7)*(1/11)
-
- You should code it as:
-
- a:=1/(3*5*7*11)
-
- Aside from being faster, it is more accurate.
-
- There are many tips for preserving numerical accuracy in computations.
- There are often interesting tradoffs between computation speed, memory
- usage, and accuracy and stability. There are even some C64/128
- specific tips. (e.g. we usually store a real value in 5 bytes of
- memory but push it onto a stack as 6 bytes when we want to use it.)
-
- This is not intended to be a Commodore FP tutorial. It is reminder
- that the C64/128 can be used for "heavy math", and there are no bugs
- in the Commodore +, -, *, /, Floating Point arithmetic routines. It
- uses 32 binary bit mantisa FP reals with proper rounding.
- Simple examples can always be contrived to demonstrate a perceived FP
- bug by computer illiterates(?).
-
- Alan got his dig in at the end there. That post, and others like it,
- pretty much squelched the arithmetic discussion. But, as is usually the
- case, we all learned a neat trick along the way. Peter Karlsson shared
- his easy way of determining whether his programs are running on a C64 or
- C128 by issueing the following statement:
-
- C=64+64*INT(.1+.9)
-
- Since the 64 and 128 differ ever so slightly in their arithmetic
- routines, the above line gives 64 on a C64 and 128 on a C128.
-
- @(A): We need another OS!
- It all started when Benjamin Moos posted a message in the newsgroup
- mentioning that he had been off the net for a while but was returning
- and wondered whether anyone would want him to finish work on a C++ based
- comiler for the GEOS 2.0 environment. Of course, everyone was for that,
- but Moos continued on, asking if there was any interest in an alternate
- OS for the 64 or 128. Moos mentioned that he had been also working on
- Common Graphic OPerating Environment (CGOE), and was thinking about
- finishing the project, which would provide a C= graphics character
- based graphic windowing system that would allow all 64 programs to run
- in the 128 80 column screen in 40 column windows.
-
- Well, that brought out some friendly debate, to state the obvious. Part
- of the group posted words of encouragement, noting that we need to
- support those programming for the environment. The other half of
- the camp echoed the words of Patrick Leung, who expressed concern that
- there are many programmers in the arena that are doing the same thing
- separately. He encouraged programmers to consolidate features and code
- bases to arrive at robust full-featured programs instead of fragile bare-
- bones applications that single programmers can't support. ACE, Craig
- Bruce's UNIX-like OS detailed in earlier C=Hacking issues, was brought
- up by some, who asked that programmers heed Leung's advice and build
- modules for the already supported ACE environment.
-
- Perhaps J. Shell has the best idea, as he is planning to set up an
- interactive WWW site to allows programmers to work with him to build
- COMMIX System II (CX2). The site will allow programmers to bring new
- ideas to the table and have them rapidly incorported into the design.
- We'll see if Mr. Shell can deliver on this neat idea.
-
- Going full circle, Benjamin Moos reponded to some of the posts, saying
- that the OS work was going to be placed on the shelf for now, as many
- had expressed interest in the C++ like compiler. However, he did say
- that work would begin again at a later date, but no decision was made
- as to how he will proceed.
-
- @(A): The "More Power" Swiftlink
- Ever striving to squeeze the most performance out of his C128 system,
- Craig Bruce modified his Swiftlink and lived to tell about it in the
- newsgroup.. Basically, after researching the data sheets for the 6551
- ACIA IC used in the SL, Craig noted that Dr. Evil Labs (the original
- creators of the SL) had used a double speed crystal to up the 19,200
- bps maximum in the ACIA to 38,400 bps. The IC claims that any baud
- rate up to 125,000bps can be achieved with the IC, given the correct
- crystal frequency. Well, another feature of the 6551 is to use the
- crystal frequency/16 as the bps rate, which is 230,400 bps or the
- stock crystal. Too fast for the IC. However, by replacing the
- crystal ( a 3.6864 MHz unit) with a 1.8432 MHz unit, the 1/16 speed
- becomes 115,200. That speed, less than 125,000 bps, is the standard
- top frequency for IBM UARTs and is supported by most newer modems.
- Craig verified that his 2MHz 128 can keep up with the extra data
- that his modofoed SL allows him to receive, but not always. he
- claims that every once in a while, the systm gets choked up and
- crashes, so he is working on solutions. Understandably, one will need
- very tight terminal program code to keep up with this speed, but it
- will fit nicely with the SuperCPU.
-
- As with all things, there is a downside in that 19,200 becomes the
- next lower bps rate. 38,400 is gone forever. Craig speculated that
- perhaps a switch could be installed, but wasn't sure of the effects.
-
- @(A): The Eternal Problem
- Although this didn't receive much discussion, C=Hacking feels many users
- can relate. How many have ever went into the local CompUSA of local
- computer store and asked to look at modems, printers, or SCSI drives,
- only to hear the dreaded laugh and chide that you should "buy a REAL
- computer", or watch the quizzical look of the sales person as they exclaim
- "You can't hook that up to a Commodore!" We particularly enjoyed the
- ending to the lament that appeared in the newsgroup:
-
- When someone keeps an old car around, babies it, works on it,
- adds to it, drives it around in style, no one says "Look at
- this dummy driving an out-dated gas guzzler that can't even do
- 80, and gets atrocious gas mileage. The frame is archaic.
- The windows aren't electric. Why doesn't he upgrade?". Nah..
- they are 'enthusiasts of classic automobiles'.
-
- Well, ... we are "enthusiasts of a classic computer".
-
- ============================================================================
-
- @(#)fido: FIDO's Nuggets
-
- The CBM and CBM-128 FIDONet echoes. The place where Commodore users
- unite. Let's what things they discussed over the past month or two:
-
- @(A): UNZIP 2 or not UNZIP 2?
- For a while now, Commodore users have been able to uncompress
- archives created with the popular PKZIP 1.01 compression program
- by PKWare or one of its clones. Well, PKWare upped the ante and
- upgraded the PKZIP product to version 2, and that left a bunch of
- Commodore users compressed! The easy solution is to ask all
- archive creators to not use version 2 of the ZIP product, but that
- presents a problem. Most of the FIDONet crowd reads their mail
- offline via popular programs like QWKIE 3.1 on the 64 or QWKRR128
- 4.3 on the 128. The programs work by retrieving a COMPRESSED
- packet of news and mail from a BBS. Well, it turns out that BBS
- systems have migrated over to the new version of ZIP, and some
- refuse to offer ZIP version 1 as an optional compression method
- for retrieval packets. So, the FIDONet crowd, including David
- Schmoll and others, have been working on or searching for a way
- to bring PKZIP 2 functionality to the 64. Some thought it was a
- done deal when a FIDNetter contacted Info-Zip, the authors of a
- free clone of PKZIP 2 by the same name. They were told the source
- code was available. The catch, it is written in C, and so far,
- no compilation on the 64 or 128 has been successful.
-
- @(A): QWKIE v3.1 FREE!
- Many C64 users have delighted over the use of QWKIE v3.1 to read
- offline news and mail. However, many had been unable to register
- the product. The mystery was solved as of late a letter by the
- author was read that stated that he was ceasing support for the
- product and had placed it into the public domain. As well,
- interested programmers could contact him about source code. So,
- QWKIE FREE, a patched version of the program that is marked as
- registered, was uplodade to the many CBM BBS systems for users to
- enjoy.
-
- @(A): That Darn Internet!
- As of late, many FIDONet regulars have been diappointed in the
- trafiic flow on the CBM echoes. They blame the growing
- popularity of the Internet as one reason the amount of messages
- has dwindled. Almost immediately, reasons why FIDONet is still
- useful started popping up in the echoes. Many claim that the
- Internet and FIDONet are complementary for the Commodore user, and
- that both resources are needed. Others, however, stressed that
- FIDONet is still the most useful. While C=Hacking isn't going
- to cast a vote here, we do hope that interest in the echoes stays
- high, as some only have access to FIDONet, and Commodore support
- should be on every network.
-
- @(A): Let's Randomize
- Some soul on the echo was looking for a way to generate a random
- number from 2 to 350. Well, always eager to help, many FIDONetters
- came to the rescue, with varying degrees of complexity.
-
- The first post, by Ken Waugh, included the text from one of
- Rick Kepharts WWW Site pages that explained, in two BASIC lines or
- less, how to create a set of 255 nonrepeating random numbers.
-
- Then, ever the guru, George Hug, of 2400 bps on a 64 fame, described
- a method to find random numbers based on "linear maximal length
- shift registers", complete with 3 part article on the method. Wow!
- needless to say, the method looks promising, but was probably more
- than what the original author was looking for. Nonetheless, the
- treatise looks worthy of inclusion in an upcoming C=Hacking issue.
-
- @(A): Catch the Wave!
- By now, most know that Maurice Randall, the author of GeoFAX, has been
- working on a GEOS telecommunications program that will operate at the
- 14,400 bps or better mark. It's been discussed in both USENET and
- FIDONet before, but Gaelyne Moranec reopened the discussion with a
- statement that World Wide Web page viewing support might possibly
- be incoporated and under test. Mr. Randall was hoping to add such
- support at some time, but it was unclear when. It looks like sooner
- rather than later.
-
- @(A): Who's First?
- Rod Gasson posed an interesting question on FIDONet a while back. He
- asked which CPU was in control of the 128 when it is first powere up.
- The abvious answer of "the 8502" was given many times over, but Rod
- finally noted that it is, in fact, the Z-80 in the system that gains
- control of the system first. Herman Yan supplied the relevant page
- from the C128 Programmer's Reference Guide that explains the
- reasons. If you want to know more, check out page 576 in the manual.
-
- @(A): Desterm Confusion
- Many in the 128 arena use a telecommunications program called Desterm,
- by Matt Desmond. At present, there are two versions of the shareware
- application out, 2.00 that works on all drives except the RAMLink, and
- 2.01 that works with RAMLink, but has bugs not present in 2.00. So,
- which to use? That questions gets asked in verious forms in the echoes
- repeatedly. That, coupled with the inability to find Mr. Desmond for
- a while, the supposed hand-over of the code to Steve Cuthbert, and the
- recent emergence of Matt (Reference: news) added to the confusion. The
- current thinking is that Matt will be working on a new release of
- Desterm that will include CTS/RTS support (the present version only
- supports XON/XOFF flow control) and some bug fixes. Somehow, the
- rumor that Matt will add Z-modem capabilities keeps pooping up, but
- Matt has denied any such work. He merely doesn;t see a need, since
- add in modules can be created to do this.
-
- So, that gives you a glimpse into the world of FIDO, the wonder dog of
- networks. C=Hacking laments that their own FIDO feed has been
- experiencing problems as of late, so we too may have missed some juicy
- tidbits. We'll catch them later on, though.
-
- Here, boy....
-
- =========================================================================
-
- @(#)cmdcpu: Underneath the Hood of the SuperCPU
- by Jim Brain
-
- Does your mind go blank when you hear about the SuperCPU? With all the
- mention of it in magazines and newsletters, are you left wondering how
- much of the discussion is hype and how much is true? Are you worried
- that this latest attempt is just another design destined for failure
- like the others before it? Well, if so, then you're not alone. With
- the reputation accelerator cartridges and their manufacturers have
- acquired over the years, you are wise to be concerned. Judge for
- yourself, as we peer under the hood of the Creative Micro Designs
- SuperCPU accelerator cartridges.
-
- Note: The information contained in this article has been gleaned from
- talks with CMD, Mr. Charlie Christianson's post to comp.sys.cbm,
- responses to USENET posts by Mr. Doug Cotton, and information from Commodore
- World Issue #12. While general information is not likely to change,
- some details discussed in this article may differ slightly from those
- incorporated in the final product.
-
- @(A): What's An Accelerator?
-
- Did you know a Commodore 64 CPU executes things at 1 MHz? A tiny clock
- inside the 64 ticks off 1 million "cycles" per second, and instructs
- the CPU to move forward one cycle at a time. The CPU, in turn,
- either executes an internal operation, reads from memory, or writes
- to memory during that cycle. These operations are concatenated to
- form funtions, which is the smallest piece of work a programmer can
- ask the CPU to perform. These function are called instruction, and
- take an average of 3 cycles each to perform. So, the typical C64
- CPU does 333,333 things a second. The C128 fares a bit better, as it
- can run twice as fast when in "fast" mode. In either case, there is
- an upper bound on the amount of useful work each CPU can do in a
- amount of time.
-
- An accelerator increases that amount of work done by substituting a
- faster CPU and clock speed for the 1 MHz 64 CPU. The ratio of
- increase should be as easy to determine as dividing the new clock
- frequency by 1 MHz for a 64. If this were true, an accelerator that
- runs at 4 Mhz would execute things at 4 times the speed of a stock 64.
- Sadly, this is not true, since not all parts of the system can be sped
- up to the higher frequency. So, the accelerator runs at full speed while
- it utilizes ICs designed for the faster clock speed, and slows down when
- it must "talk" with ICs like the SID and VIC-II in the 64, which run only
- at the slow 1 MHz clock speed.
-
- Most accelerators are produced as large cartridges that plug into the
- expansion port of the computer system. Some require special wires be
- attached to internal components, while others do not.
-
- @(A) The New Kid on the Block
-
- In mid 1995, Creative Micro Designs, after having evaluated the FLASH 8
- accelerator from Europe with only mild success, noted that there might
- possibly be a market for a speedy accelerator that would run GEOS and
- other useful applications in the USA. After surveying the readership
- of Commodore World, the Internet, and FIDONet, CMD decided that interest
- in such a unit was forthcoming. Shortly thereafter, the SuperCPU
- announcement was made.
-
- As development work ensued, progress reports and preliminary information
- about the product surfaced from CMD. The first items involved the processor
- choice, which was originally the 65C02S but is now its bigger brother, the
- 16 bit 65C816S. Another piece of information involved the case, which is
- an enclosure 6" wide by 2" deep by 3" wide. This enclosire contains
- a circuit board protruding from the front of the unit that will plug into
- the Commodore 64 or 128 expansion port. In back, a complementary card
- edge connector is provided to pass signals through the cartridge. This
- will allow users to attach other expansion port cartidges to the
- system. On top sit three switches, described below.
-
- The first switch enables or disables the SuperCPU unit. The second switch
- enables or disables JiffyDOS, which is built into the unit. The third
- switch determines the speed of the unit. This third switch has three
- positions. The first position forces the accelerator to operate at 1
- MHz speed (the same speed as the stock C64). The second position allows
- the programmer to change the speed via a register in the SuperCPU memory
- map. The third position locks the SuperCPU into 20 MHz mode, regardless
- of register settings.
-
- The use of the CMD SuperCPU will be straightforward. Simply plug the
- unit into the expansion port, set the appropriate switches on the top of
- the unit, and powering on the unit.
-
- @(A) Technical Details
-
- The basic system utilizes a WDC W65C816S 16 bit microprocessor running at
- 20 MHz. This CPU can not only fully emulate a CMOS 6502, it can be
- switched into "native" mode which allows access to 16 bit registers and
- 16 megabytes of RAM without bank switching, DMA, or paging.
-
- Attached to the CPU is a bank of 64 kilobytes of Read Only Memory (ROM)
- and 128 bilobytes of high speed static RAM (SRAM). The extra RAM above
- 64 kB is used to "mirror" the contents of the slower ROM. See below for
- details.
-
- A number of features designed to maximize the performance of the
- SuperCPU are being developed into the unit. Since the late 1980's
- ROM speeds have not been able to keep pace with CPU clock frequencies.
- With the CMD accelerator moving into the frequency range of newer
- PC systems, this becomes a problem for the SuperCPU as well. The
- Commodore typically stores its KERNAL and BASIC code in ROMS, and the
- SuperCPU will need to read that code. The easiest solution is to read
- the stock ROMs in the computer, but those ICs can only be accessed
- at 1 MHz (they are part of that set of older ICs that cannot be utilized
- at 20 MHz). So, the next option is to copy that code into faster ROMs
- and instal those ROMs int the cartridge. Well, as stated earlier,
- ROMs of sufficient speed are very expensive and not widely available.
- So, the third option, which is the one CMD will use, is to copy the
- KERNAL and BASIC at startup to RAM and write protect the RAM area, making
- it look like ROM. Fast static RAM (SRAM) is available to meet the
- 20 MHz clock requirements, and is not terribly expensive, as most new
- PC systems use the same memory for similar uses. This technique is
- called ROM shadowing and has been utilized for a few years in the IBM
- PC community.
-
- The heart of the unit is the Altera Complex Programmable Logic Device
- (CPLD). Analogous to electonic "glue", this single chip can replace
- ten or hundreds of discrete ICs in circuits. This unit is responsible
- for decoding the complex series of signals presented in the expansion
- port, handling DMA requests to an REU unit, emulating the specialize
- I/O port found at locations $00 and $01 on the 6510 CPU, and handling
- the synchronization of the SuperCPU memory and C64 memory.
-
- One item that has plagued accelerator designers for years and minimized
- the widespread acceptance of accelerators invoves this RAM sync operation
- the Altera CPLD handles. In areas of the stock C64 memory map where
- only RAM is present, like $0002 - $40959, the synchronization of
- memory can be handled very easily. However, when dealing with areas
- like $d000, where RAM AND IO can be present, the situation becomes more
- complex. The SuperCPU overcomes this problem as well, which is important
- since many video applications use the RAM under IO at $d000 for graphics
- or text.
-
- As the VIC-II IC in the C64 and C128 requires that screen information be
- present in on-board memory, memory "mirriring" is necessary. However,
- CMD has introduced two new technologies, called WriteSmart(tm) and
- CacheWrite(tm) to reduce the slowdown associated with mirroring the
- SuperCPU SRAM and the slower on-board DRAM. According to documentation,
- WriteSmart allows the programmer to decide which portions of memory need
- mirroring. The four selections include "BASIC", where only text and
- color memory are mirrored, "GEOS", where GEOS foreground bitmap and color
- memory are mirrored, "ALL", where all 64 kB of RAM is mirrored, and
- "NONE", where the SuperCPU does not attempt to syncronize memory contents
- between the two RAM areas.
-
- The other technology, called CacheWrite(tm), minimizes the effect of
- this mirroring. When storing a value into SuperCPU RAM in a range of
- RAM that requires mirroring, the value is stored not only in SuperCPU
- RAM, but also into a special cache memory location. The SuperCPU is
- allowed to continue processing, while the system waits for the on board
- DRAM to acknowledge readiness to store a value. When successive stores
- to mirror ranges are done, the system must slow down, but can still
- operate at about 4 MHz. This speed is achieved because the SuperCPU need
- not wait for the value to be successfully stored before it attempts to
- fetch the next opcode and operand. Since opcodes that write value to
- memory avarage 4 cycles to complete, the SuperCPU can effectively do 4
- cycles worth of processing in 1 period of the 1 MHz clock. Note that
- this slowdown does not occur if the cache is not full when a store
- instruction is executed.
-
- @(A) Features
-
- Being a CMD product, the CMD SuperCPU comes with JiffyDOS, CMD's
- flagship speed enhancement routines, installed. However, JiffyDOS
- can be switched out for those applications that fail to run with this
- serial bus enhancement functionality.
-
- The unit also features compatibility with RAMLink, CMD's RAM drive unit.
- As the RAMLink fucntions by sharing the CPU with the computer system and
- runs a special set of instructions called RL-DOS, the SuperCPU contains its
- own version of RL-DOS optimized to take advantage of the speed and extra
- features available in the 65C816S. Preliminary information suggests that
- RAMLink data retrieval, typicially much slower the REU data retrieval,
- will now operate at speeds approaching that of the REU. In addition, the
- on-baord RL-DOS will handle usage of the special parallel CMD HD drive
- cable available with the RAMLink.
-
- For those with expansion in mind, CMD has incorporated a special
- expansion port internal to the unit. The port, called the "Rocket
- Socket", will allow access to the complete signal set from the W65C816S
- CPU and possibly other support ICs. This will allow developers to
- produce peripheral cards for the unit containing hardware that will run
- at 20 MHz (The cartridge port will still be limited to slow speed).
-
- @(A): Myths About the Unit
-
- In the early phases of development, CMD hinted that possibly extra RAM
- installed in the unit could be used as a fast RAM disk, a la RAMLink.
- However, the inability to battery back up that RAM area, coupled with the
- small increase in speed gained form doing so and the lengthy development
- time needed to realize this feature, has prompted CMD to abandon this
- idea for the time being. Later in the development cycle, such an idea
- might resurface, but the feature is most likely never to be implemented.
-
- Also, early information about the units noted that two speed options would
- be available, but low support for the slower 10 MHz model prompted CMD to
- discontinue development on that version. As of now, there is only one
- speed option available: 20 MHz.
-
- When CMD first announced the unit to the public, it was to include the
- Western Design Center W65C02S microprocessor. However, in late 1995/early
- 1996, CMD opted to switch from that CPU to its bigger brother, the W65C816
- 16 bit CPU, owing to small increase in per item cost, more flexibility, and
- more expansion options.
-
- Although the speed of the CPU in the SuperCPU unit is running at 20 MHz,
- that does not imply all operations will occur twenty times faster. Some
- operations, like reads from I/O ICs, derial bus operation, and mirroring
- of video memory, require the CPU to slow down temporarily. This will
- reduce the effective speed to about 17-18 MHz.
-
- @(A): Compatibility Issues
-
- All legal 6502/6510/8502 opcodes are supported in the accelerator.
- Undocumented or "illegal" opcodes are not supported and will fail.
-
- Although not a compatibility issue, some applications that rely on the
- CPU running at a certain speed to correctly time events will most likely
- fail or operate too quickly to be useful. Event or interrupt driven
- code should operate correctly.
-
- The SuperCPU 64 model will operate correctly with any C64 or C64C model
- of computer system, as well as with any C128 or C128D in 64 mode. However,
- CMD has recently announced a 128 native version of the cartridge.
-
- @(A): Super128CPU
-
- In early 1996, CMD announced that interest was compelling and that would
- begin development on a 128 version of the SuperCPU. As a result of this
- announcement, the ship date was moved from Februarty to April as CMD
- validated the SuperCPU design so that it could be used to manufacture
- both the SuperCPU 64 and SuperCPU 128. Both units will operate at a
- maximum of 20 MHz, and will most likely be packaged in the same enclosure.
- The SuperCPU 128 will operate in both 64 mode and native 128 mode. It
- will not enhance CP/M mode on the C128. CMD announced that the
- availability of this unit would be Auguest or September ot 1996. As far
- as cost is concerned, a current estimate falls at $300.00, and advance
- orders are being taken with a security deposit of US$50.00 needed to
- place an advance order.
-
- As this announcement was made, some confusion has resulted in the naming
- scheme. Previously called the SuperCPU or SuperCPU 64/20 (64 model at
- 20 MHz), the new models are referred to as alternately:
-
- 128 model 64 model
-
- Super128CPU Super64CPU
- SuperCPU 128/20 SuperCPU 64/20
-
- @(A) Prototype Testing and Benchmarks
-
- As no developer unit have shipped as of this date, CMD has the sole unit
- availabel for be testing and benchmarks. CMD's prototype unit consists
- of a handwired unit on perfboard. At first, CMD was hesitant that the
- prototype would actually run at 20 MHz, since such designs are not
- "clean" and can suffer from eignal degradation, signal skew, and
- crosstalk, which inhibits operation at higher frequencies. So, with
- that in mind, early tests were done at 4 MHz. CMD reported in late
- Fenbruary 1996 that the prototype had been ramped up to 20 MHz and was
- operating correctly. In fact, the unit appears to run faster than it
- can, illustrated by the following example:
-
- CMD tested the following program at 1 MHz on a Commodore 64
-
- 10 TI$="000000"
- 20 FORI=1TO10000:NEXT
- 30 PRINTTI
-
- The result from this test was 660. After enabling the unit, the test was
- rerun and the result printed out again: 31.
-
- Quick calculations by the CMD personnel verified that the unit was
- executing this program 21.29 times the normal speed. However, that
- is impossible, as the CPU is only clocked 20 times the nortmal speed.
-
- The supposed impossibility is explained if you delve deeper into the
- timing of the 64. As many know, the VIC-II "steals" cycles from the CPU
- in order to refresh the VIC-II video screen. Extra cycles are "stolen"
- for sprites. With the SuoperCPU disabled, the above code runs at 1 MHz
- minus the amount of time the VIC-II "steals" from the CPU. With the
- SuperCPU enabled, the VIC-II does not "steal" cycles from the unit, as
- the accelerator uses it own private memory area for operation. The VIC,
- meanwhile, uses the on-board C64 memory.
-
- CMD notes that games that use timers or are event driven function
- correctly, but hotse that count processor cycles or utilize spin-wait
- loops run so quickly as to be virtually unusable.
-
- Of partiular note to Commodore Hacking readers is the test done with the
- object code for the Polygonamy (Reference: polygon) article elsewhere in
- this issue. On a stock 64, the program renderes approximately 12-13
- frames per second. With the SuperCPU enabled, the frame rate jumped to 128
- fps. CMD notes that further gains might be realized if the code was
- modified to cooperate more fully with the CupserCPU memory scheme.
-
- As for Ram Expansion Unit compatibility, CMD responds that the issues
- have been tackled and that DMA operation is available on the SuperCPU
- unit. In adiition, CMD notes that the CPU need not be running at 1 MHz
- to initiate a DMA transfer.
-
- As stated from the beginning, the 64 model of the SuperCPU accelerator
- wil work on the Commodore 128 in 64 mode, and test have confirmed that
- the prototype 64 model does indeed frunction correctly any the C128 and
- C128D.
-
- @(A): Conclusion
-
- While it is too early to determine the success of the CMD SuperCPU
- product, the company has a reputation for delivering stable products
- packed with features. While no accelerator can guarantee 100%
- compatibility with all Commodore software, the CMD offering should provide
- the best compatibility options thus far, due to its solutions to
- RAM synchronization problems that have plagued accelerator designers for
- years. The fact that CMD also owns the marketing rights to the GEOS
- family of software products and manufacturers a wide variety of
- successful mass media storage devices bodes well for compatibility with
- those applications and peripherals.
-
- @(A): For More Information
-
- TO find out more about the CMD SuperCPU family of accelerators, contact
- CMD at the following address of via email:
-
- Creative Micro Designs, Inc.
- P.O. Box 646
- East Longmeadow, MA 01028-0646
- (413) 525-0023 (Information)
- (800) 638-3263 (Ordering only)
- cmd.sales@the-spa.com (Internet Contact for Sales)
-
- Advance orders are being taken for all units, and the cost to place an
- advance order is $50.00.
-
- For programmers, CMD is planning to make available a Developer's Package,
- which will help those wanting to exploit the potential of the new unit to
- achieve success. A W65C816S assembler supporting all the new opcodes and
- addressing modes will be provided, as will documentation pertaining to the
- unit, the CPU, and its capabilities.
-
- =========================================================================
-
- @(#)surf: Hack Surfing
-
- For those who can access that great expanse of area called the World Wide
- Web, here is some new places to visit that are of interest to the Commodore
- community. In early 1994, when the US Commodore WWW Site started, the number
- of sites online that catered to Commodore numbered in the 10's. Now, the
- number is in the 100's. What a change.
-
- If you know of a site that is not listed here, please feel free to send it
- to the magazine. The following links have been gleaned from those recently
- changed or added to the US Commodore WWW Site Links page
- (http://www.msen.com/~brain/cbmlinks/).
-
- To encourage these sites to strive to continually enhance their creations,
- and because we like to gripe :-), we'll point out an improvements that
- could be made at each site.
-
- @(A): Companies
-
- o http://www.armory.com/~spectre/cwi.html
- Computer Workshops Incorporated. CWI shows off their newest software
- offerings on this well-crafted WWW site. The darkbackground provides
- for visual effects, and the content is good as well. At the time we "hit"
- the page, CWI was working on a new game called Nether for the 64/128.
- From the information, it looks like a 3D action adventure. CWI offers
- both CBM and MS-DOS titles. Some are shareware, while others are
- commercial. C=Hacking gripe: We don't mind the MS-DOS information, but
- the diehard CBM user should be able to skip it. As of now, it's all on
- the same page.
-
- o http://www.msen.com/~brain/guest/Gaelyne_Moranec/qwkrr/
- QWKRR128, by Rod Gasson. Gaelyne Moranec, a supporter of QWKRR, presents
- this site for new and advanced users. The site is devoted to QWKRR128, a
- QWK-based offline mail reading program for BBS and Internet use, and
- Browser, a utility for reading large files on the 64/128. The site
- is clean and simple, with no fancy graphics, but lots of meaty information.
- Links include the QWKRR128 user's manual, the actual product's binaries,
- and helper applications needed to use QWKRR128. C=H gripe: It's hard to
- tell what all I need to read Internet email via QWKRR128.
-
- o http://www.msen.com/~brain/guest/rms/
- RMS Computer Systems. RMS offers up its line of services from this site,
- including software distribution, parts and accessories, and consulting/
- training. RMS can even design your WWW pages. The pages are colorful
- and clean, using either Microsoft Explorer or Netscape Navigator
- extension depending on the browser chosen off the home page. RMS offers
- the C-Net BBS software for sale and present information on the 64 and
- 128 versions of the program. C=H gripe: The home page offers a choice
- of using Netscape of Microsoft Explorer. What about the Lynx text mode
- browser? Which do they pick?
-
- @(A): Publications
-
- o http://www.the-spa.com/cmd/cwhome.html
- Commodore World. CMD's publications is presented at this site, with
- select articles, and information for potential writers and subscribers
- is detailed. The site is laid out well and provides for easy reading.
- Of course, we're not sure it does justice to the magazine, but that's
- true of LOADSTAR's home page as well. C=H gripe: the site needs updating,
- as the change dates are 9-95. When they do update it, we hope they'll
- remove that annoying "blink" tag!
-
- @(A): User's Groups
-
- o http://www.ccn.cs.dal.ca/Technology/CUGNS/CBM.html
- Cnada Commodore Users Group of Nova Scotia. The site makes use of
- color and grpahics to provide links to a number of Commodore content
- sites on the Internet. It links up with other user groups on the 'Net,
- and provides a public download area for software retrieval. C=H gripe:
- We still think this is a user's group, but no meetings, minutes,
- newsletters, or times and dates were mentioned. Whare are they?
-
- o http://www.fastlane.net/homepages/msessums/64.html
- Metro C-64/128 User's Group. Meeting dates, times, agendas, and some
- general information are provided on this page. You can also learn about
- this groups parent organization, the Metroplex Commodore Computer Club.
- C=H gripe: some newsletters from past meetings and a bit more about the
- group would be nice.
-
- o http://www.inna.net/mpcug/mpcug.html
- The Middle Peninsula Computer Users Group. Go here to find out just
- WHY the groups is named this way. Meeting times, dates, places, past
- newsletter articles, and background information is provided. The site
- has a sprinkle of color and graphcis to break up the text. C=H gripe:
- It looks like the group is multi-platform, but no mention is made of
- what Commodore 8-bit owners will find at meetings. Maybe we missed it.
-
- @(A): Demo Groups
-
- o http://rphc1.physik.uni-regensburg.de/~pem03049/eqx/
- The EQUINOXE WWW Site. This demo group puts on a good show, with
- content and color on their WWW site. Here is where you can find
- the announcement on the upcoming Shout! #2 magazine release. The list
- of links is implressive as well. C=H gripe: The front page use of large
- fonts sizes is a bit overdone.
-
- o http://flash.lakeheadu.ca/~jgvotour/index.html
- The OMNI/Revenge WWW Site. Color and content are mixed well on this
- site as well. A bit of history about Revenge is given, links to the
- demos to download is present, and information about upcoming releases
- is detailed. C=H gripe: We'd like to know more about the person behind
- the well-done page.
-
- @(A): Miscellaneous
-
- o http://vanbc.wimsey.com/~danf/cbm/languages.html
- Dan Fandrich's Commodore Languages List. Extensive doesn't really
- describe this page, which provides information on assemblers, compilers,
- cross-compilers, and interpreters for many different programming
- langauges supported by the Commodore 8-bit. Rare items like language
- support for the 264 series and the SuperPET are described as well.
- C=H gripe: the page is HUGE. Any chance of a breakdown into spearate
- files?
-
- o http://rrnet.com/~bfrandse/viccarts.html
- The Commodore VIC-20 Cartridge List. Cartridges from many different
- software companies are detailed, and both games and utilities are listed.
- As with the Programming Language Page, this list is extensive. It notes
- in the opening credits the trasnsitions the list has made to arrive at
- this current form. C=H gripe: same as for the langauge list. This thing
- is LARGE, and might benefit from a more heirachial listing treatment.
-
- o http://fox.nstn.ca/~ptiwana/john/webpage1.html
- John Elliot's WWW Site. This page explores the use of Commodore computers
- and other "orphan" machines to better education by improving the student/
- computer ratio. The information presented in this site is heartwarming,
- as it shows practical uses to dispel the myth that 8-bits are truly
- useless. C=H gripe: Not really a gripe, but we sure would like to see more
- of these reall world examples.
-
- o http://www.ksk.sala.se/~sp93rob/dungeon/
- The Alternate Reality WWW Site. For those wanting to relive the best of
- this game for the 64, visit this site. Everything from tips to tricks,
- stories to confidential material, and screenshots are available at this
- site. C=H gripe: The color scheme is a bit rough on the eyes, but it
- does look neat.
-
- o http://www.lysator.liu.se/tolkien-games/c64.html
- Fredrik Ekman's Tolkien Games WWW Site. The name says it all. If
- you've ever played a Tolkien game, here is where they are listed and
- examined. Fredrik give the history of each game, the solutions if there are
- any, and describes the game itself. C=H gripe: We left impressed with the
- information but wondering why someone would go to this effort. Tell us,
- Fredrik.
-
- o http://ubmail.ubalt.edu/~telliott/commodore.html
- Todd Elliott's Commodore 64/128 WWW Site. Todd provides some commentary
- and links to hardware hacks and ML tips. Of particular interst is his
- introduction to the Commodore C64 and C128 computers, which explains
- some of the history behind the machines. Our favorite passage in this
- page details his experisnces with Radio Shack.... C=H gripe: We'd like
- to know how Todd Elliott fits into the Commodore 8-bit arena.
-
- @(A): Change of Address
-
- o CMD recently moved to http://www.the-spa.com/cmd/
- CMD heard our issue #11 gripe, as the home page now has links directly
- to the SuperCPU information.
-
- o LOADSTAR has moved to http://www.softdisk.com/comp/loadstar/
-
- o Marc-Jano Knopp's CBM WWW Site is at:
- http://www.student.informatik.th-darmstadt.de/~supermjk/c64.html
-
- o The US Commodore WWW Links Site has moved to:
- http://www.msen.com/~brain/cbmlinks/
-
- ============================================================================
-
- @(#)trivia: Commodore Trivia
- by Jim Brain (brain@mail.msen.com)
-
- @(A): Introduction
-
- I had the good fortune of receiving some fine back issue of magazine and
- old books from a friend in Michigan (thanks Gaelyne), so I got busy reading
- and gleaning. The result is a new crop of trivia questions guaranteed to
- rack your brain and have you reachin' for those numerous Commodore
- publications. Go ahead, I won't mind.
-
- As some may know, these questions are part of a contest held each month on
- the Internet, in which the winner receives a donated prize. I encourage
- those who can received the newest editions of trivia to enter the contest.
-
- This article contains the questions and answers for trivia editions #23-26,
- with questions for the current contest, #27.
-
- If you wish, you can subscribe to the trivia mailing list and receive the
- newest editions of the trivia via Internet email. To add your name to the
- list, please mail a message:
-
- To: brain@mail.msen.com
- Subject: MAILSERV
- Body:
- subscribe trivia Firstname Lastname
- help
- quit
-
- @(A): Trivia Questions
-
- A publication describing BASIC on the Commodore makes the claim that
- BASIC variables are limited to 5 characters, with the first two being
- significant. The example to prove this point in the book is given as:
-
- ABCDE=5 works, while
- ABCDEF=6 does not.
-
- The following questions refer to this claim:
-
- Q $160) What is wrong with the above statement?
-
- A $160) Variables can indeed be longer than 5 characters.
-
- Q $161) What causes the variable ABCDEF to fail?
-
- A $161) The variable name fails becase the BASIC keyword "DEF" in it.
-
- Q $162) How long can variable names really be?
-
- Extra Credit: Who was the book publisher?
-
- A $162) As long as the maximum command line length. Theoretically, using
- automated code generation, you can get a variable name that is
- just shy of 255 characters in length.
-
- Oh, and Abacus wrote the offending book.
-
- The Commodore LCD Computer system, much like the Commodore 65,
- was a product that never reached the market. Do you remember this
- pint-size CBM machine?
-
- Q $163) How many keys were on the CLCD keyboard?
-
- A $163) 72 keys, including 8 function keys and 4 separate cursor keys.
-
- Q $164) What does LCD in the Commodore LCD stand for?
-
- A $164) Liquid Crystal Display.
-
- Q $165) Was an internal modem to be includes?
-
- A $165) Yep, A 300 bps auto dial/auto answer modem.
-
- Q $166) Like the Plus/4 the CLCD unit had integrated software. What programs
- were included?
-
- A $166) As referenced in $158, there are 8 integrated programs:
-
- Word Processor
- File Manager
- Spreadsheet
- Address Book
- Scheduler
- Calculator
- Memo Pad
- Telecommunications Package
-
- Q $167) How many batteries of what type did the CLCD use for power?
-
- A $167) 4 AA alkaline batteries.
-
- Q $168) Approximately how much did the CLCD unit weigh?
-
- A $168) 5 pounds.
-
- Q $169) What version of BASIC was to be included with the CLCD computer?
-
- A $169) 3.6. It contained all of Basic 3.5 plus a few extras.
-
- Q $16A) The CLCD unit contained a port that could be used with a
- Hewlett-Packard device. What did the device do?
-
- A $16A) An HP bar code reader.
-
- Q $16B) What microprocessor did the CLCD unit utilize?
-
- A $16B) The 65C102 CPU. This CPU was built using the 65C02 core from
- Western Design Center, who licenses the popular 65C816S CPU
- as well. CBM licensed this chip at little or no cost as a result
- of a lawsuit settlement between WDC and CBM over 6502 architecture
- patent infringements.
-
- Q $16C) In addition to the usual inclusion of standard Commodore ports,
- what two industry standard ports were included on the CLCD?
-
- A $16C) Centronics Parallel (printer) port, and an EIA-232 (RS-232C) port.
-
- Q $16D) How much RAM did the CLCD computer include?
-
- A $16D) 32kB of battery backed RAM.
-
- Q $16E) How many pixels are on the LCD screen on the CLCD machine?
-
- A $16E) 480 x 128 or 61440 pixels
-
- Q $16F) How much ROM did the CLCD computer contain?
-
- A $16F) 96kB of ROM, which held the OS and the integrated programs.
-
- Q $170) What text is displayed on the screen of a Commodore 128 upon
- bootup?
-
- A $170) The following text is centered on either the 40 or 80 column
- screen:
-
- COMMODORE BASIC V7.0 122365 BYTES FREE
- (C)1985 COMMODORE ELECTRONICS, LTD.
- (C)1977 MICROSOFT CORP.
- ALL RIGHTS RESERVED
-
- Q $171) How many bytes free does a Commodore 128 have on powerup?
-
- A $171) As shown above in Q $170, 122365 bytes.
-
- Q $172) On the Commodore B-128 series, the bell beeps at the right margin.
- What column is the default right margin on the B-128?
-
- A $172) Column 70.
-
- Q $173) When a Commodore C64 is hooked up to a 1541 and an MPS 801
- printer, everything is powered up and connected correctly, and
- the floppy won't load. What is wrong?
-
- A $173) The printer is offline. Put the printer on-line, and the floppy
- will operate correctly.
-
- Q $174) How do you access the "hidden message" in the C128DCR?
-
- A $174) One brute force way:
-
- While in the machine language monitor, type:
-
- m f63f5 f640b
-
- Q $175) Some of you may remember the Commodore Magic Voice cartridge.
- If so, how many words was in the base unit's vocabulary?
-
- A $175) 235
-
- Q $176) Who write the 3+1 software bundled with the Commodore
- Plus/4 in ROM.
-
- A $176) Tri Micro wrote the code, and created a version for the C64.
- It turns out that the 3+1 software included with the Commodore
- Plus/4 was originally designed to be but one of the many choices
- for bundled software with the 264. When the focus changed, 3+1
- became the only software bundled, and some assumed Commodore
- had written it. (Ref. RUN April 1985:43)
-
- Q $177) The BASIC extension "Simon's BASIC" was created by whom?
-
- A $177) David Simons (Ref: Commodore Power/Play April/May 1985:56-7)
-
- Q $178) Simons' BASIC was influenced a lot by what other computer
- manufacturer's BASIC?
-
- A $178) Hewlett Packard. (Commodore Power/Play April/May 1985:56)
-
- Q $179) How many commands does Simons' BASIC add to the Commodore 64?
-
- A $179) 114. (P/P Apr/May 1985:57)
-
- Q $17A) In the United Kingdom, there was an extension to Simons' BASIC
- developed by David. Among other things, what major complaint
- about the original BASIC extension does it address?
-
- A $17A) Renumbering GOTOs and GOSUBs when renumbering a program.
-
- Q $17B) In the Commodore Plus/4 File Manager, there exists two bugs,
- which show up if you have over a certain number of records. What
- is this magic number?
-
- A $17B) When merging over 255 records in the Word Processor, a printout might
- stop early int the file and continually reprint a single record, or
- entering one record might trash another record. (RUN April 1985:43)
-
- Q $17C) Commodore Semiconductor Group (CSG) manufactured an 8500 IC.
- What common IC number is this IC functionally equivalent to?
-
- A $17C) The 6502. The change in number owes more to a change in
- manufacturing process than anything else.
-
- Q $17D) How many BASIC commands were included in BASIC 3.5, not
- including the monitor commands?
-
- A $17D) 80. (RUN November 1984:37)
-
- Q $17E) On the Commodore VIC-20, 64, and C16 keyboards, what row and
- column pins on the keyboard connector does the letter D
- correspond to?
-
- A $17E) Row 2 Column 2. (RUN July 1984:109)
-
- Q $17F) What is special about the keys in Row 4 of the hardware keyboard
- matrix?
-
- A $17F) Column 2-4 spell out CBM. (RUN July 84:109)
-
- Q $180) Most people know what CPU is in a Commodore disk drive, but what
- CPU powers the venerable CBM 1525 printer?
-
- A $180) You had better sit down.... The 1525 is powered by an Intel 8039
- 8-bit microcontroller. Actually, this isn't so hard to believe,
- since Commodore didn't actually develop the printer, but used a
- Seikosha GP-100 printer mechanism for the unit, and most likely
- contracted Seikosha to develop the firmware.
-
- Q $181) What is the maximum number of characters per line on a CBM 1520?
-
- A $181) 80. 22 columns per inch times 3.63... inches of usable paper width.
-
- Q $182) Commodore rarely manufactured its own printer mechanisms. Who's
- mechanism did Commodore use in the DPS 1101?
-
- A $182) The Juki 6100 printer mechanism.
-
- Q $183) What is unique about the DPS 1101 printer?
-
- A $183) It is daisy-wheel, but Commodore made other daisy-wheel printers. what
- makes it unique is that it is the only such serial daisy-wheel made
- for the Commodore line.
-
- Q $184) Which was the first Commodore modem with DTMF dialling capabilities?
-
- A $184) The first to offer some kind of DTMF support was the Commodore 1660
- modem. The modem itself didn't provide any DTMF support, but included
- a cable to allow the SID to output to the phone line. Thus, with the
- SID's ability to reproduce DTMF tones, the modem could tone dial.
- Note that this was only possible on the C64, which has a SID. The
- first mode to INCORPORATE DTMF into the modem itself was the 1670.
-
- Q $185) Which was the last Commodore 8-bit peripheral drive developed?
-
- A $185) By develop, we are referring to actually produced models. With that
- definition, the 1581 holds this title. For models not actually
- produced, The prototype 1590-D-1 3.5" 1.44 MB model owned by Jack
- Vander White probably was the last under development.
-
- Q $186) What is the maximum size of RAM available for use for program
- storage on an expanded VIC-20
-
- A $186) 3583 bytes are available for BASIC programs and their variables.
-
- Q $187) One of the most poular magazines for computers in the 1980's was
- COMPUTE! What Commodore content magazine did it give birth to?
-
- A $187) COMPUTE!'s Gazette.
-
- Q $188) In a strange twist of irony, COMPUTE! was itself descended from a
- Commodore content magazine. Which one?
-
- A $188) The PET Gazette. The PET Gazette was started in April 1978 by Len
- Lindsey. For the first year, the magazine was sent out for free to
- at times 4000 people. In August of 1979, Small Systems Services,
- headed by Robert Lock, purchased the magazine from Len and changed
- the name to COMPUTE. The focus changed from PETs to all computer
- systems at that time. The first issue of COMPUTE. appeared in the
- Fall of 1979. It seems the relationship between Len Lindsay and
- Robert Lock was less than ideal, but I refer readers to INFO #15,
- page 8 for the scoop.
-
- Q $189) COMPUTE! underwent a name change very shortly after introduction.
- What subtle change was made to the name?
-
- A $189) COMPUTE. changed to COMPUTE! Notice the change?
-
- Q $18A) How were LOADSTAR and Commodore Microcomputing-Power/Play once
- connected?
-
- A $18A) In the mid 1980's, LOADSTAR distributed the type in programs for
- both magazines in the disk magazine.
-
- Q $18B) What is the fastest Commodore ever clocked a 6502 or derivative
- CPU in a machine?
-
- A $18B) The CSG65CE02 CPU, clocked at up to 3.54 MHz in the Commodore 65
- (64DX) prototype.
-
- Q $18C) Name one byte that yields the same character when printed and poked
- to a Commodore screen.
-
- A $18C) Any byte between 32 and 63 will produce identical results.
-
- Q $18D) Quick, which chr$ value flips to uppercase/lowercase mode?
-
- A $18D) chr$(14)
-
- Q $18E) Quicker, which chr$ value flips it back to uppercase/graphics?
-
- A $18E) chr$(142)
-
- Q $18F) How do you get INPUT to not display a question mark?
-
- A $18F) open 1,0:input#0,a$
-
- Q $190) In reference to Commodore, what does TOI stand for?
-
- A $190) The Other Intellect. Evidently, it was the computer the CBM
- engineers were working on before the VIC-20 project. The name
- sounds like it was dreamed up after the fact. In either case, this
- machine might have been the "Color PET" mention in _The Home
- Computer Wars_ that Chuck Peddle was designing before company
- shifted to the VIC architecture.
-
- Q $191) Name two values that, when poked to the screen, will yield the
- identical character appearance.
-
- A $191) 32 and 96 or 160 and 224. Space and reverse space.
- 103 and 106 or 101 and 116. Left and right lines.
-
- Q $192) What chr$ codes lock out and re enable the shift/commodore keyboard
- flip from uppercase to lowercase on the VIC-20?
-
- A $192) chr$(8) and chr$(9), respectively.
-
- Q $193) What chr$ codes lock out and re enable the shift/commodore keyboard
- flip from uppercase to lowercase on the C64?
-
- A $193) chr$(8) and chr$(9), respectively.
-
- Q $194) What chr$ codes lock out and re enable the shift/commodore keyboard
- flip from uppercase to lowercase on the C128?
-
- A $194) chr$(11) and chr$(12), respectively, while in 128 mode.
-
- Q $195) On CBM machines prior to the VIC-20, what chr$ code outputs the
- same character as chr$(44), the comma.
-
- A $195) 108.
-
- Q $196) Is the character described in $195 of any use?
-
- A $196) To put commas in strings read via INPUT. Remember, INPUT treats
- a comma (chr$(44)) as a delimiter between input fields, but chr$(108)
- does not produce the same effect, so you could replace 44 with 108 in
- data written to disk, and read it in with INPUT.
-
- Q $197) The speed of Commmodore BASIC increased dramatically after the first
- OS upgrade in 1979. Why?
-
- A $197) Jim Butterfield supplies us the answer:
-
- "The original PET 2001 suffered from the same kind of "screen
- sparkle" that was later seen in the early Commodore 64. So
- the original code would write to screen memory only during
- the "refresh" period; that really slowed down the speed of
- output to the screen. By the time the first revised PET came
- out, the screen sparkle was solved, and characters were
- delivered to the screen with no wait. (The new operating
- system also did a massive relocation of system variables,
- and used zero page very heavily, to the dismay of home
- programmers. When asked about this, Commodore pointed
- proudly at the "new, higher speed". But in fact it was
- the screen reorganization that caused 95% of the
- improvement)."
- --Jim
-
- Related to this question is $00C, which implies that the
- "sparkle" problem was fixed in the original PETs, so some people
- increased the performance of the original PET by setting the RETRACE
- line mentioned above to an output, which fooled the system into
- thinking the video was ALWAYS in RETRACE mode.
-
- Q $198) COMAL, a programming language available for Commodore computers, was
- created by whom?
-
- A $198) Borge Christensen and Benedict Lofstedt, although Borge is given
- the most credit.
-
- Q $199) At the 1980 COMDEX, Commodore PETs proved instrumental during a
- crisis. What happened?
-
- A $199) The following is excerpted from _The Whole PET Catalog_, page 21:
-
- "PET PROVEN USEFUL" During the 1980 MGM Grand fire in Las
- Vegas, Commodore moved its entire COMDEX '80 booth dowstairs
- to help track rooms, guests, etc. According to _InfoWorld_,
- 7 PETs with OZZ data-bases (predecessor to SILICON OFFICE)
- were used for two straight days. Local police agreed they
- could not have kept of the guests as well as the PETs did.
- Also, untrained operators quickly learned the system. In the
- crisis, PET was both powerful and useable.
-
- Q $19A) Who designed the PET/CBM 8032 computer?
-
- A $19A) Bill Seiler, the able assistant to Chuck Peddle, designed the unit.
-
- Q $19B) What was the "cursor gone out to lunch" bug in the first PETs?
-
- A $19B) No answer available yet (I can't find my notes!)
-
- Q $19C) On a PET/CBM (early models), what will "POKE 14,1" do?
-
- A $19C) If done immediately prior to an INPUT, the poke will suppress the
- question mark prompt.
-
- Q $19D) What version of BASIC would not utilize disk drives?
-
- A $19D) BASIC 1.0
-
- Q $19E) Who is Lyman Duggan and why is he important?
-
- A $19E) He is one of the founding fathers of the Toronto PET User's Group
- (TPUG), along with Jim Butterfield.
-
- Q $19F) Jim Butterfield notes to me that he received plenty of help in
- creating the first PET memory map (Q $0D8) from the Sphinx group,
- who published critical information in their early newsletters. How
- did Commodore influence the name of the group?
-
- A $19F) The name "Sphinx" was chosen because of the way early PETs resembled
- the Great Sphinx, the Lion with the head of a pharoah.
-
- Q $1A0) Commodore produced an assembler for the 128 called HCD65. What
- does HCD stand for?
-
- Q $1A1) Who wrote most of RAM DOS?
-
- Q $1A2) What is the name of the first C64 disk copy program? (hint: it
- sported a "gas gauge".)
-
- Q $1A3) What was the case color of the original Commodore 64s?
-
- Q $1A4) There are at least two ways to enter 64 mode from 128 mode on a C128:
- go 64 and sys 65357. They produce the same result (64 mode), but
- they differ in at least one noticable way. How?
-
- Q $1A5) What CPU powers the B-128 computer system?
-
- Q $1A6) What type of drive mechanisms are in the D series hard drives from
- Commodore?
-
- Q $1A7) Commodore produced a 16kB RAM expander for the Commodore VIC-20.
- What is its model number?
-
- Q $1A8) Commodore produced at least one disk drive with an optical track
- one sensor. Which drive?
-
- Q $1A9) The Commodore PET series used the IEEE bus to communicate with
- peripherals. Each peripheral had a unique ID. What range of IDs
- are supported by the PET?
-
- Q $1AA) Many people have developed Commodore software with the PAL assembler.
- What does PAL stand for?
-
- Q $1AB) Many people remember Compute's Gazette. This magazine is best known
- for the word processor program it shared with thousands of
- subscribers. Name the program?
-
- Q $1AC) In some 6502 assemblers, the opcode "bge" is available. It stands
- for "branch if greater than or equal to". What more common opcode
- is this opcode referring to?
-
- Q $1AD) If I wanted to do a "blt" (branch if result less than), what 6502
- opcode would i use?
-
- Q $1AE) Each Commodore peripheral has a device number, which is associated
- with a type of device. 8-15 implied disk drive, 4-5 implies
- printer. These have remained constant from the PET to the C128.
- However, one peripheral in the PET was phased out and its device
- number was reused. What device number was reused?
-
- Q $1AF) What is the maximum amount of general purpose RAM can one utilize
- in a stock C64? (I need an exact number here)
-
- =========================================================================
-
- @(#)gfx: Talking to TED: The MOS 7360/8360 Text Display ICs
- by Harsfalvi Levente (TLC@MSZI.PMMF.HU)
-
- @(A): Introduction
-
- This information file is based on my old books, descriptions, and especially
- my experiences while I was coding. That's no mistake. The Plus/4 series
- was not very famous in the world, but they were very poular in mideast
- Europe. In fact, there were even demo groups for the machine. I learned
- some of this information while writing demos for the machine in demo groups,
- while other things were gleaned from personal work on the machine. These
- computers did indeed play an important part in Commodore computer history.
-
- I started my first code development on a Plus/4 in late 1986. After I saw a
- HomeLab 3 (made in Hungary, U880 - GDR made Z80 compatible proc, B/W, 16K),
- I started writing demos and other software for the Plus/4 machine I owned.
- It actually wasn't that strange to see demo groups sprout up for all
- kinds of machines, including the Plus/4. All over, there were groups
- and individuals, writing software while trying to keep the flame lit for
- each machine. In fact, I know people currently working in groups writing
- for the Plus/4 in Hungary, Germany, and as far away as Alaska.
-
- @(A): Overview
-
- Let's discuss the TExt Editor (TED) IC and its environment. This DIL-48 IC
- was designed specifically for the 264 series of machines, which initially
- included the CV364 and the 264, evolving into the Plus/4, C16, and C116
- machines. Unlike the CIA or ACIA or other machines, this IC isn't well
- suited to any other system.
-
- The TED contains all functions done by several chips in former Commodore
- computers. The TED is a complete video-interface and composite video
- signal generator, sound generator, keyboard input latch, timer,
- clock generator, memory manager and DRAM refresher in a single IC. It can
- address the full memory map of the 264 series machines, and it generates
- the RAS', CAS', and MUX signals for the DRAM memory used in that series.
- For ROM, it generates the chip select (CS) lines, depending on the state
- of the internal registers. So, in addition to all the above duties, the
- TED IC is a simplistic MMU as well.
-
- @(A): Video Information
-
- We see the TED chip shine as it does its primary job, displaying graphics.
- Its abilities mostly parallel those of the uniquitous VIC-II video IC in the
- C64. It has the following modes:
-
- * 40x25 screen (characters)
- * enhanced color mode
- * multicolor mode
- * 320x200 Hi-Res Graphics
- * 160x200 Multicolor Graphics
-
- Of course, there are differences. TED does not contain sprite support.
-
- To offset this omission, the TED chip can select 8 intensities for each of
- the 16 supported colors, giving 121 colors (the 8 shades of black are all
- black). Other features include a hardware cursor, hardware text blinking,
- and hardware inverse character support. Character sets, screen and color
- memory, and graphics bitplanes can be addressed directly, without additional
- logic as found on the C64. In fact, even RAM/ROM selection requires change
- of a single bit.
-
- Character modes need $800 bytes of RAM for screen and color memory. The
- first $400 bytes act as color memory (the memory permanently located at
- $d800 on the C64), with the lower 4 bits containing color codes, exactly
- as found on the 64. Bits 4-6 denote the intensity level of the color, while
- the high bit select flashing/no-flashing attributes. The other $400 bytes
- contain the screen codes for the displayed characters. If hardware
- character inversion is selected, the lower 7 bits hold the screen code and
- the high bit selects inversion for the character. If character inversion
- is not selected, all 8 bits denote the screen code. Extended Color Mode (ECM)
- and Multi Color Mode (MCM) modes work exactly as described on the 64. While
- these two modes are in effect, inversion and blinking are disabled.
-
- Things get a bit more complex in graphics mode (pun unintentional). In
- graphcis mode, the bitplane occupies $2000 bytes and is handled just like a
- VIC-II biplane. The colors are handled differently. $800 bytes are needed
- for color memory, which is laid out in $400 bytes of intensity memory
- and $400 bytes of color memory. An "off" bit in the bitplane uses the
- lowest nybble of the appropriate color memory location as the color and
- retreieves the intensity from bits 4-6 of the appropriate intensity memory
- location. For an "on" bit, the color is taken from the high nybble of the
- appropriate color memory location, while the intensity is taken from bits
- 0-2 of the intensity memory location. Bits 3 and 7 in intensity memory are
- unused.
-
- In multicolor mode, differences abound. The 64's VIC-II enabled one to
- utilize 3 different colors in each 8x8 cell and a single background. The
- TED simply cannot accomplish this due to the lack of adequate color memory.
- So, TED allows only 2 varying colors per 8x8 cell. Those colors are chosen
- from the palette of 121. The remaining 2 colors are chosen for the
- entire screen, again from the 121 color palette. The mapping is as
- follows:
-
- 00 background color
- 01 same as "off" color in hires mode
- 10 same as "on" color in hires mode
- 11 another "background" color
-
- The TED IC is able to generate both PAL and NTSC compatible signals from
- a single IC. Only the crystal need be changed to go from one standard to
- the other. In PAL mode, there are 312 lines hown, while NTSC only has 262
- lines of display. The line synchronization is the same in either PAL or
- NTSC mode. It's always 57 clock cycles per rasterline. The TED divides
- the supplied crystal frequency by 20 for PAL display and by 16 for NTSC.
-
- For the serious video programmer, raster interrupts are implemented as on the
- VIC-II. However, the 0 line of the register corresponds to the first line
- of the character screen area, not the top of the border. In addition, the
- current raster line can be read from TED registers. you can modify the
- counter as well. Doing so will most likely affect the screen display. As
- a bonus, the horizontal location of the raster can be read and modified in
- the same way. Unfortunately, these registers provide the basis for most
- effects, as the TED can't handle sprites.
-
- @(A): Running The Show
-
- As earlier mentioned, the TED IC does more than produce graphics. One of
- its tasks involves generating the clock signal for the 7501/8501
- microprocessor. The clock is not constant, as it switches from from
- 885 kHz and twice that speed, 1.773 Mhz. The speed depends on TED's current
- task. It generates the slower clock signal when refreshing DRAM or fetching
- data for the video screen. Otherwise, the high clock signal is generated.
- The user can disable fast clock generation via a register. The end result
- is a machine that operates at approximately 1 MHz, as the CPU runs in slow
- mode while the screen is displayed, and operates in fast mode when the
- TED starts drawing the top and bottom borders.
-
- @(A): Sound Advice
-
- As far as a sound device is concerned, the TED doesn't stack up to the
- SID in the 64. Just 2 squarewave generators, of which the second can be
- switched to generate white-noise, are available for sound generation.
- Volume control is available in 8 levels.
-
- To play samples, the TED can switch the sound generators to constant level
- outputs. D/A is then done by changing the volume register setting. Each
- generator can generate frequencies from 100Hz to 23kHz.
-
- @(A): Other features
-
- The timers available in the TED appear to be nothing more than 16
- bit decrementing timers. They are always clocked with the slow clock.
- The first timer reloads its starting value when it reaches 0, the other 2
- are free-running.
-
- Since it already does almost everything else, it's not unusual to notice
- the TED handles the keyboard matrix. A simple 8-bit imput latch handles
- keyboard interfacing.
-
- As noted above, a single bit in the register space will page ROM or
- RAM into the upper 32kB of the address map. Since the TED knows what is
- paged in at all times, it knows what to output to access the memory
- locations in this area.
-
- @(A): Conclusion
-
- Well, that about wraps up the TED IC. All that is left is a map of the
- registers. Assume all registers are read/write unless noted otherwise.
- If you have questions, I cna be reached at the Internet address listed above
- or at:
-
- Harsfalvi Levente
- 7200 Dombovar
- Gorkij 33.
- Hungary
-
- By the way, catch FLI ED. V1.0; Its info file may contain some more about
- TED's screen-handling. It may be retrieved as
- ftp://ftp.funet.fi/pub/cbm/plus4/tlc/cns.lzh
-
- @(A): Register Map
-
- Register Description
- -------- -----------
- $ff00- $ff01: Counter #01. It always starts to decrement from the last
- written value into it.
- $ff02- $ff03: Counter #02. It runs freely from $ffff.
- $ff04- $ff05: Counter #03. Same as above.
- $ff06 : Mostly the same as VIC's $d011.
- Bit 0,1,2 : Vertical smooth-scrolling
- Bit 3 : 24/25 rows screen
- Bit 4 : Blank screen
- Bit 5 : Bitplane mode
- Bit 6 : Enhanced color mode
- Bit 7 : TED's internal test, it should be 0.
- $ff07 : Most similar VIC-reg is $d016.
- Bit 0,1,2 : Horizontal smooth-scrolling
- Bit 3 : 40/38 columns screen
- Bit 4 : Multicolor mode
- Bit 5 : TED stop. If set, the TED stops it's counters and
- screen-generating, only single clock and refresh
- cycles remain.
- Bit 6 : PAL/NTSC. 0:PAL, 1:NTSC
- Bit 7 : Disable reverse mode. If 0, we got 128 characters
- and higmost bit tells if the character should
- appear in inverse. If set, no inverse mode but
- 256 characters.
- $ff08 : Keyboard input latch. Giving a strobe - writing to the register,
- the latch stores the values of the input-lines. Then, we
- can read them from this register.
- $ff09 : Interrupt request register. When a counter sends want to send
- an IRQ, it's bit will appear as a 0; then, if the IRQ was
- caused then highmost bit is set.
- Bit 0 : Unused
- Bit 1 : Raster-counter
- Bit 2 : Lightpen. Not implemented.
- Bit 3 : Counter #1
- Bit 4 : Counter #2
- Bit 5 : Unused
- Bit 6 : Counter #3
- Bit 7 : Interrupt occured. This bit is set when an IRQ
- was enabled and therefore, the IRQ was sent to the
- processor. Physically, this is the negated level of
- the TED's IRQ output. The IRQ should be deleted
- with writing the register-value back after
- accepting an interrupt.
- $ff0a : Interrupt mask register. These bits could be used to disable and
- enable interrupt-sources. When a place is set to 1, that will
- be able to cause an interrupt to the processor. If not, the sign
- of the interrupt request will only be appear in the above
- register.
- Bit 0 : 9th bit of $ff0b (see there)
- Bit 1 : Raster-counter
- Bit 2 : Lightpen. Not implemented.
- Bit 3 : Counter #1
- Bit 4 : Counter #2
- Bit 5 : Unused
- Bit 6 : Counter #3
- Bit 7 : Unused
- $ff0b : Raster interrupt register. Same as $d012 when writing; it stores
- the position of occuring raster interrupt. Higmost bit is in
- $ff0a's 0. bit.
- $ff0c,$ff0d : Hardware-cursor position (10 bits). Lower bits: $ff0d, higher
- 2 bits in $ff0c's 0. and 1. places. Beyond 1000 the cursor is
- not seeable.
- $ff0e : This reg is the first sound-source's frq-value's lowmost 8 bit.
- More 2 bits are in $ff10's 0. and 1. places.
- $ff0f : 2nd. source, lowmost 8 bits. More 2 bits in $ff12, 0. and 1.
- places.
- The soundregister-value can be calculated as
- reg=1024-(111860.781/frq[Hz]) (NTSC)
- reg=1024-(111840.45 /frq[Hz]) (PAL)
- $ff10 : 1st. sound-source, higmost 2 bits. 2-7 bits are unused.
- $ff11 : Sound control register.
- Bit 0-3 : Volume. Maximum value is 8.
- Bit 4 : Sound #1 on/off.
- Bit 5 : Sound #2 squarewave on/off.
- Bit 6 : Sound #2 noise on/off. If You set both, the square
- will sound.
- Bit 7 : D/A mode. See above for more.
- $ff12 : Bit 0,1 : 2nd sound-source, highmost bits.
- Bit 2 : Character generator in ROM or RAM. When set, TED
- will enable ROM when trying to get data from the
- charactergenerator to build screen. Else, it will
- give out control-signals to the DRAM's.
- Bit 3,4,5 : These bits tell, where to find bitplane in the
- memory when using bitplane-mode. TED assumes them
- as A15,A14 and A13 bits. So, the bitplanes can be
- switched as 8K pages, anywhere in the 64K.
- Bit 6-7 : Unused.
- $ff13 Bit 0 : A sign to having control about memory paging. This
- bit always sets to 1 when ROM is active over $8000.
- Else, it will be 0. READ ONLY.
- Bit 1 : Force single clock mode. Then, TED will disable to
- generate twiee clock.
- Bit 2-7 : Charactergenerator. Bit 7 corresponds to A15, 6 to
- A14 and so on. This value shows and sets the start
- of the charactergenerator. It can be paged as $400
- bytes. Use with addition of $ff12-2.bit.
- $ff14 Bit 0-2 : Unused
- Bit 3-7 : Start of the video-ram. Bit 7 also corresponds to
- the A15 line as above. So, video-ram is mappable
- as $800 bytes - 2K. The above $ff12-2.bit doesn't
- affect this, but the actual RAM/ROM mapping (see at
- $ff3e/$ff3f and $ff13/0) does.
- $ff15 : Background. Lower bits contain color-code, higher 3 luminance
- and higmost is ignored.
- $ff16 : Color-reg 1
- $ff17 : Color-reg 2
- $ff18 : Color reg 3. This and the above are used in ECM and MCM modes.
- $ff19 : Border. All color registers use codes as described in $ff15.
- $ff1a : Bit 0-1 : Higmost bits of the next $ff1b
- Bit 2-7 : Unused
- $ff1b : Actual character-position. Higmost bits in the above register.
- TED counts the characters that it had fetched and put out to
- the screen. The number is increasing by 40 after every
- characterline (8 rasterline).
- $ff1c : Bit 0 : Higmost bit of $ff1d
- Bit 1-7 : Unused
- $ff1d : Actual position of vertical scanning. Higmost
- bit is in $ff1c. Read/Writeable!
- $ff1e : Actual position of horizontal scanning. R/W!. Lowmost bit is
- unused. It contains the TED's internal counter's highmost 8
- bits. So, it increases 4 with every character. When writing,
- it seems to put the value to a functionally different register
- (writing back a reading value in right time affects the screen).
- $ff1f : Bit 0,1,2 : Actual vertical scanning-line in a character-row.
- R/W!.
- Bit 3-6 : Flashing counter. It's value increases with every
- frame, and TED fits it's flashing feature to this
- register's reaching to 15.
- Bit 7 : Unused
- $ff3e : Switching to ROM. A writing statement to this address will
- cause to turn on the ROM between $8000-$ffff. It's an other
- matter, which one; this time, only sure thing that it'll give
- CS signals instead of RAS', CAS' and MUX.
- See $ff13/0 and $ff14
- $ff3f : Switching to RAM. The opposite of the above.
-
- ============================================================================
-
- @(#)error: ? DS, DS$: rem The Error Channel
-
- We are not aware of any errors with issue 11, save the changes to some WWW
- addresses as noted in Hack Surfing (Reference: surf).
-
- ============================================================================
-
- @(#)next: The Next Hack
-
- "... and that's not all you get." Well, it is for this issue, but here's
- what Commodore Hacking is cooking in its TV informercial cookware for
- issue #13:
-
- o CMD has announced that SuperCPU development units should be made
- available shortly, so C=Hacking will scrutinize it and detail the
- registers of interest as soon as it shows up.
-
- o Exploiting the 65C816S. We're holding this article over to next issue
- to allow testing of the examples with the CMD SuperCPU. This article
- will detail the new opcodes available to programmers, show how to
- detect CPU clock speed on any C64, accelerated or not, and discuss
- pitfalls in code migration.
-
- o Let's get HTMLized! It's about time the Commodore 8-bit learned to
- do HTML. There's nothing that says this popular WWW markup language
- can't do used to create nice disk magazines and newsletters on the
- CBM system, so C=Hacking begins a 4 part series on the language and
- how to render HTML pages on a Commodore machine.
-
- o And, of course, C=Hacking's regular goodies.
-
- So, go ahead, buy that box of disks, and label one now for Commodore
- Hacking Issue #13.
-
- ============================================================================
-
- @(#)editor: Hacking the Code
-
- For articles in Commodore Hacking that include binary files as part
- of their article, these binaries files are made available in this section
- as encoded text files. The format used for encoding is called UUCode,
- which is a standard widely used on the Internet to transmit binary files
- using only printable ASCII characters. To that end, each of these files
- must be decoded with a suitable decoding program before they can executed.
- Typical examples inlucde UUXFER for the 64, uudecode on the ACE OS for the
- 64 and 128, and uudecode on most UNIX OS machines. Some encoders can decode
- multiple files, while others will require the user to manually split this
- section into individual pieces prior to decoding.
-
- WARNING: The UUCode format trasnlates files from binary to ASCII, not
- PETSCII. Therefore, either decode this section before downloading this
- section to a PETSCII mode computer system, or download this section without
- translation to PETSCII. Some decoder programs can handle PETSCII converted
- UUCode files, but the practice is not recommended because conversion is
- typically done in a telecommunications program and cannot be guaranteed to
- be accurate.
-
- @(A)polycode: Binary for Polygonamy
-
- begin 600 polygonamy
- M`0@0",0'GC(P-C8@5C4N,````'BB_YJ]-PB=^`#*T/>.$=#N,-"&`:G-H&F%
- M+80NA:Z$KZ`Y3``!`*@%D3_,:;TL"9WH!^C0]^X"`>X%`8C0[J("()T!\"S)
- M!I`2*0&H()H!:0:0"*H@G0&%^1#CA8NE_#CEBX7\A8RE_>D`A?V%C2"&`:;Y
- M\`3&^1#%()T!\`D@F@&B`H:+D!OH()T!\`GH()T!()H!:0%I`X6+Z""=`<@@
- MF@%E_H6,I8UE_X6-.""&`?",I(NE_N6+A?ZP`L;_L8R1_HC0^6"^Z@&I`(6-
- MI/OP#`;Z*B:-QOO*$/*H8(6.L?R%^JD(A?NECJ3\T`+&_<;\P.?0W*3]P`?0
- MUJDWA0'.,-"I&XT1T%BI`(T`""!@IB".IDRNIP,'"PL("@">,C`V,>-_>*E_
- MS+&I-(4RC0R@(KFJ:9G=_XC`_]#USB#JE0CL'0@XC>8!HO.:R&"""B$!F+X+
- M*=@8@$I*4MK(T.KN/PL.0@CN2<B`.0C./`@0V:(.XP<"U)T#<"&=!.`&")T%
- MU*F`G0;4BCCI!ZH0XJ`/J0`*D!>B_XX.U(X/U(T3;GSPCA34HH&.$J!XCXP8
- MU*`"J?^@.-R9`=V(T/?`$+`,N3#@>0#<N4`;W;D`#9D`T,C`+]#E(%`-K3#`
- M>L.M,0.%R*D@H@:-8)F-_M_@#-ZFH`!,C@![69I,!,Y)FHV#"$@@+)!H(,J.
- M)("I"B\UR@(T`U0#=`.4I,5U*PC$'X88AB"Q"L8<A0"E$)$*B!#SQA[*E7?G
- M3`X"?P@(@0$(4[(M_Y5"_P1J8`1X)0`DR@J0&2(#,,84!$BMW:/F8:3.4V)@
- M%*J`F!#P+,KM\`6D!(6$H`O)__#C4`+T\!0&WY`$)M_&ET;_D.$@2(V1W,C0
- M^.;=T.AR[*T2T,F`T/DR#``$W`P`K0C=)N_JZL8!(8"I_XU@`*(*3!$`J7N-
- M$=#F`820A(0``H0"`!#%62@0,$.H`F#___S]""8!`P$`,S@Y,3%JW#`P,'X`
- MQ@8`+P,`BP%`"@!$````O;U*`.J9/_]]F0X"B!#ZC!G0ZH8!:S,`:$`("``P
- M`(!&X>FG>::<X\FZ)TX,YT(&L:@R`%,!T`H<.(8@)&P#&3J,#+!28*)"D!-J
- MO1!,!`(K/*@8>J1P%!=<`"$Q>`EA"Q#Q`HH0`$`,`$P`$(+Q[NY&`$``X>$H
- M`"4`"$%H$1$CBQX>C0"0X"`$!9LWUJ`5R``5</`L"`[^]BD`"!*3_)2%F(B3
- M*P=L/1*,QP`_!@`PGQ&L`'\0$(-Y$/NBF%^E,T0>D30P'N$%,`XAI357'I$V
- M,![=XQ%C0*4WC01,.(PH@HT%<@BQI3F-!MRE.HQB@HT'F@)"W*U`"2T@`]VE
- M,(T-W&`%GC,R-S;/`#@`+C%*+D^B.+W)!94"Y9V1`LH0\^8!J9`L$=`P^\T2
- MT-#VJ0@2X@Q`W7'=H#U(:*4`J0&B"(T.W(X/W*D`HG=,X`$%./'Y,`B!"`4"
- M;P44/A:`#KX$"B=+$`=(ZP"JL9&S(J$X`"`/B@1Q@!F!>@IVHP4&`$"CL[V2
- M-87@&0`!`S"2H`[%H#BHD)FD!2$FC__P!04`"J/F>M`"YGNM!@+).K`*!18C
- M3F/W@Z1DZAJGY*>&KMBL3$BR`#'J`[!'_DKSD?(.\E#R,_-7\<KQ[?8^\2_S
- M9OZE].WUR2#P[T6-!S`XZ=!@@$_'4EA`+/-D57\"!``*@`!O`!&!)H`""0!8
- MIG+V/`,D(PUO8&`(GX,0:*`!%A'$"`L(P=$)()3`!P``)Q@-P'`'A$41A0('
- MA@(&A\#;@>LLIVN`3#)7KR`0#PP9!P\.`0T9`D<3M`OL(%0%$`@%#B`,+B`*
- M%00$`04TG3(8(#(O-B\Y-@+`(3,#%!,@-CHX(#HI`A<T"P'H(`$8O0`,RU<%
- M!@<("0H+#`T.#U"91A.2&Q=)<B0;T9$@J%`06"C@D2&82(SAA8+@(P$+%55E
- MA8JP(U^)C@0L9I2H4!"4;@@I<Y2@4'=R0GM\?7YA"8&"@X2%AH>(B8J+C(V.
- MCY"1DI.4E9:7F)F:FYR=GI^@H:*CI*6FIZBIJJNLK:ZOL+&RL[2UMK>XN;J[
- MO+V^O\#!PL/$Q<;'R,G*R\S-SL_0T=+3U-76U]C9VMO<W=[?X.'BX^3EYN?H
- MZ>KK[.WN[_#Q\O/T]?;W^/GZ^_S]Y>X1!P;Y=Q!TEA44.DL5RIT-%87.DA4%
- M!P7((B`>'!D7%1,0#@P*"`8#`?_]^_GW]?,]XMH1Z.;DXN#>W!36CM&A;$?'
- MQ</!P+Z\NKBW$+D[KZZLJJBGI:.BH)Z=8NZ.E).1D(Z,BXF(AH6#@J`S=Q1W
- M=G1S<7!OA;UC9F5D8F%@7EU<6XB\'4M.34P+CT`ZOO`=1R"/8#P"\@B\+1"W
- M(2!H,+KC"?86B,<1P*,)YA&,QQ'*HP@?``80*((!"`<*B$@+`$@(`4!P`D@%
- M`T"B6T@2'DTHCR/L6C`>2S"/%A8CC<<?'Y/8(R)ACR5D/8(J*[0>04B/(WQ'
- M%]XC3$U.2X];7%U>8&%B9&5F);)[#(&B<W1V=T+W*(*#A8:(B8N,CI"1DY0Z
- MQT>=GJ"BHZ6GJ*JLKJ^0>3ZWN+J\OL#!P\7'0IZ/T:#(Q]S>X.+DYNA0F#Z"
- M\_7W^?O]_P$#!@@*#`X0$Q47&1P>("!>$`$"\)`"`O$``@^;`/[\^OCV]/+P
- M[NSJZ>?EX^'?W=O:V-;4TM#/S<O)R,;$PL&_O;NZN+:UL[&PKJRKJ:>FI*.A
- MGYZ<FYF8EI63DI"/C8R*B8>&A(.!@']]?'IY>'9U=')Q<&YM;&II:&=E9&-B
- M8%]>75M:65A75E134E%03TY-2TI)2$=&141#0D%`/SX]/#LZ.3@W-K[PP30S
- M,C$P+\&Q+2PK*EDH.O0E)!15(HX_!0$5$%1P4(%"!7'A4,%9C$5$!6&B@O`4
- M%A6$(*`G)FH))<`'<"$$BF@`#@L0@4P,`$P(`4P&`N.``PD$3`0%!@8&&%ZG
- MH)R";PH*BJ@I#`P-#0X.#P\0$!$1$A(3$Q04%146%Q<8&!D:&AL<'!T>'A\@
- M("$B(R,D)28F)R@I*2HK+"TN+B\P,3(S-#4U-C<X.3H[/#T^/T!!0D-$149'
- M2$E*2TU.3U!14E-45E=865I;75Y?8&)C9&3_F&EJZ&-P<7)T=79X>7I\?7^`
- M@8.$AH>)BHR-CY"2DY66F)F;G)Z?H:.DIJ>IJZRNL+&SM;:XNKN]O\'"Q,;(
- MR<O-S]#2U-;8VMO=W^'CY>?IZNSN\/+T]OCZ_/ZM@%,F^<V@=$@<\<6:;T09
- M[L2:<$8<\LF@=TXE_=6LA%TU#N:_F7)+)?_9LXUH0AWXU*^+9D(?^]>TD6Y+
- M*`;DPJ!^7#L:^=BWEW96-A;WU[B9>EL]'@#BQ*:);$\R%?C<OZ.';%`U&O_D
- MR:^4>F!&+1/ZX<BPEW]F3C<?!_#9PJN5?FA2/"81_.;1O:B4?VM70S`<"?;C
- MT;ZLFHAV9%-!,!\/_N[>SKZ2KIZ/@'%B5$4W*1L-`/+EV,N_LJ::CH)V:V!5
- M2C\T*B`6#`+Y\.;=U<S$N[.KI)R5CH>`>7-M9F!;55!*14$\-S,O*R<C(!T:
- M%Q01#PT+"0<&!`/_ID?_5298F>`]`0(#!`8'"0L-#Q%2QAH=(",G*R\S-SQ!
- M14I055M@9FUS>8"'CI6<I*NSN\3,U=WF\/D"#!8@*C0_2E5@:W:"CIJFLK_+
- MV.7R``T;*3=%5&)Q@(^>KK[.WN[^#Q\P05-D=HB:K+[1X_8)'#!#5VM_E*B]
- MT>;\$28\4FA^E:O"V?`''S=.9G^7L,CA^A,M1F!ZE*_)Y/\:-5!LAZ._W/@5
- M,D]LB:;$X@`>/5MZF;C7]Q8V5G:7M]CY&CM<?J#"Y`8H2VZ1M-?['T)FBZ_4
- M^!U":(VSV?\E2W*9O^8.-5V$K-7])4YWH,GR'$9PFL3N&41OFL7Q'$ATH,WY
- M)E.`GWZB!!;Z`^Z$,`>XA1D0P@"NJ`*<@)`$$`4/$&X`F5@!2H`/(`.8`!J`
- M`S5$%S8`%Q8!%Q("%PX#%PT$8#H%%PL&%PH'8)@(8`@)%PD*D@M@"`P7"`TR
- M#F`(#X80%P<1(`,2)A-@`A07!A72*P<2D?H)^YB`_`G]F(#^"?^8@``)`9B`
- M`@D#F(`$!Q0%!Q(&`@*#Y)TA-$%*4%9:76!C96=H:FML;6YO;W!Q<7)R<W-T
- M='1U=74;#W8"!'<"!G@""'D""WH"#WL"&'P"$WT(<9L(`%@-`U(&`!0#`!0`
- MB!```01P`D``_Q@\\"A()R8F)B4E)20D)"%9(R(B(B$A(2`@("%9'QX>'AT=
- M'1P<'"%9&QH:&AD9&1@8&"%9%Q86%A45%104%"&Y$Q(2$A$1$1`0$`\/#^%9
- M#@T-#0P,#`L+"R%9"@D)"0@("`<'!R%9!@4%!00$!`,#`R%9`F'^(P```/__
- M_V"%_OW]_?S\_/O[^V2%^OGY^?CX^/?W]V2%]O7U]?3T]//S\^2&\O'Q\?#P
- M\._O[^[N[F>%[>SL[.OKZ^KJZF2%Z>CHZ.?GY^;FYF2%Y>3DY./CX^+BXF2%
- MX>#@X-_?W][>WB@$W=S<W-O;V]K:VMG9V;C%T=[J]P00'2DV0D\@#W6!CIJG
- ML\`=#N;R_PL8)#$^2E=C<'R)C0ZON\C4X>WZ!Q,@+#E%4HT.>(21G:JVP]#<
- MZ?4"#AN-#D%-6F9S?XP=#K*^R]?D\/T*%B,O/$A586Y[AY2@K;G&T]_L^`41
- M'BHW1%!=:7:"CYRHM<'.VN?S``T9)C(_2UAD<7Z*EZ.PO,G6XN_["!0A+3I'
- M4V!L>862GZNXQ-'=ZO8#$!PI-4).6VAT@8V:IK._S-GE\OX+%R0P/4I68V]\
- MB)6BKKO'U.#M^083'RPX15%>:W>$D)VIML+/W.CU`0X:)S1`35EF<G^+F*6Q
- MOLK7X_#\"18B+XUZYJCM`@0`R)!@!0`H!$!,@,`$P`(('`3).]`.Z"@(\!#H
- MQ#+P"\``\`>F'$4Q1R2%!2C0!Z1/Q#+0`>CD'(8<\#S@";`XO(`?Q3+PP.*#
- M$2`P`2$3(C`!(Q,E,`$F$R<P`2@3*C`!*Q,L,`$M$R\P`3`3,3`!,A,T,`$U
- M$S8P`3<3.3`!.A,[,`$\`0@^N0`)D13(QB_0]HT$_ZD`8,E@D`(I7V"@!(0&
- MHC4^V4<@??^.('51++I$:2`-`*(%H"<@A$0@8@!:'<X;!Z\(")B`$`D8F(`@
- M"2B8@#`).)B`0`E(F(!0"5B8@&`):)B`<`EXF("`"8B8@)`)F)B`H`FHF("P
- M";B8@,`)R)B`T`G8F(#@">B8@/`)^"`HL0@(F(`0"1B8@"`)*)B`,$$X(2CU
- M*$)(P`103%C`!&!,:,`$<$QXP`2`3(C`!)!,F,`$H$RHP`2P3+C`!,!,R,`$
- MT$S8P`3@3.C`!/!,^"%`B44(P`003!C`!"!,*,`$,$PXP`1`3$C`!%!,6,`$
- M8$QHP`1P#'@B0JE'$0*()I!@`I@FH&`"J":P8`*X)L!@`L@FT&`"V";@8`+H
- M)O!@`O@B2BP"""808`(8)B!@`B@F,&`"."9`8`)()E!@`E@F8&`":"9P8`)X
- M)H!@`H@FD&`"F":@8`*H)K!@$+@C2CV*$,@P`=`3V#`!X!/H,`'P$_@C4&(1
- M"#`!$!,8,`$@$R@P`3`3.#`!0!-(,`%0$U@P`6`3:#`!<!-X,`&`$X@P`9`3
- MF#`!H!.H,`&P$[@P`<`3R#`!T!/8,`'@$^@P`?`D)20VZE&$@`@)$)B`&`D@
- MF(`H"3"8@#@)0)B`2`E0F(!8"6"8@&@)<)B`>`F`F("("9"8@)@)H)B`J`FP
- MF("X"<"8@,@)T)B`V`G@F(#H"?"8@/@E$HN`"`D0F(`8"2"8@"@),!B$."92
- MCR($2$Q0P`183`!&A,<,`$>$R`P`2(3)#`!)A,H,`$J$RPP`2X3,#`!,A,
- MT,`$V$S@P`3H3/#`!/@FE%@$"$P0P`083"#`!"A,,,`$.$Q`P`1(3%#`!%A,
- M8,`$:$QPP"!X)Y1Z%"&(8`*0)IA@`J`FJ&`"L":X8`+`)LA@`M`FV&`"X";H
- M8`+P)O@GH,0B"&`"$"888`(@)BA@`C`F.&`"0"9(8`)0)EA@`F`F:&`"<"9X
- M8`*`)HA@`I`FF&`"H":H8`*P!K@HH=2C"`'($]`P`=@3X#`!Z!/P,`'X*"46
- M`0@3$#`!&!,@,`$H$S`P`3@30#`!2!-0,`%8$V`P`6@3<#`!>!.`,`&($Y`P
- M`9@3H#`!J!.P,`&X$\`P`<@3T#`!V!/@,`'H$_`I4&(IHQY%"`B8@!`)&)B`
- M(`DHF(`P"3B8@$`)2)B`4`E8F(!@"6B8@'`)>)B`@`F(F("0"9B8@*`)J)B`
- ML`FXF(#`"<B8@-`)V)B`X`GHF(#P"?@J*+$(")B`$`D8F(`@"2B8@#!!."LH
- M]2A"2,`$4$Q8P`1@3&C`!'!,>,`$@$R(P`203)C`!*!,J,`$L$RXP`3`3,C`
- M!-!,V,`$X$SHP`3P3/@K0(E%",`$$$P8P`0@3"C`!#!,.,`$0$Q(P`103%C`
- M!&!,:,`$<`QX+$*I1Q$"B":08`*8)J!@`J@FL&`"N";`8`+()M!@`M@FX&`"
- MZ";P8`+X+$HL`@@F$&`"&"8@8`(H)C!@`C@F0&`"2"908`)8)F!@`F@F<&`"
- M>":`8`*()I!@`I@FH&`"J":P8!"X+4H]BA#(,`'0$]@P`>`3Z#`!\!/X+5!B
- M$0@P`1`3`!(!,H,`$P$S@P`4`32#`!4!-8,`%@$V@P`7`3>#`!@!.(,`&0
- M$Y@P`:`3J#`!L!.X,`'`$\@P`=`3V#`!X!/H,`'P+B4N-NI1A(`("1"8@!@)
- M()B`*`DPF(`X"4"8@$@)4)B`6`E@F(!H"7"8@'@)@)B`B`F0F("8":"8@*@)
- ML)B`N`G`F(#("="8@-@)X)B`Z`GPF(#X+Q*+@`@)$)B`&`D@F(`H"3`8A#@P
- M4H\B!$A,4,`$6$Q@P`1H3'#`!'A,@,`$B$R0P`283*#`!*A,L,`$N$S`P`3(
- M3-#`!-A,X,`$Z$SPP`3X,)18!`A,$,`$&$P@P`0H3##`!#A,0,`$2$Q0P`18
- M3`!&A,<,`@>#&4>A0AB&`"D":88`*@)JA@`K`FN&`"P";(8`+0)MA@`N`F
- MZ&`"\";X,:#$(@A@`A`F&&`"("8H8`(P)CA@`D`F2&`"4"988`)@)FA@`G`F
- M>&`"@":(8`*0)IA@`J`FJ&`"L`:X,J'4HP@!R!/0,`'8$^`P`>@3\#`!^#(E
- M%@$($Q`P`1@3(#`!*!,P,`$X$T`P`4@34#`!6!-@,`%H$W`P`7@3@#`!B!.0
- M,`&8$Z`P`:@3L#`!N!/`,`'($]`P`=@3X#`!Z!/P,U!B,Z,>10@(F(`0"1B8
- M@"`)*)B`,`DXF(!`"4B8@%`)6)B`8`EHF(!P"7B8@(`)B)B`D`F8F("@":B8
- M@+`)N)B`P`G(F(#0"=B8@.`)Z)B`\`GX-"BQ"`B8@!`)&)B`(`DHF(`P03@U
- M*/4H0DC`!%!,6,`$8$QHP`1P3'C`!(!,B,`$D$R8P`2@3*C`!+!,N,`$P$S(
- MP`303-C`!.!,Z,`$\$SX-4")10C`!!!,&,`$($PHP`0P3#C`!$!,2,`$4$Q8
- MP`1@3&C`!'`,>#9"J4<1`H@FD&`"F":@8`*H)K!@`K@FP&`"R";08`+8)N!@
- M`N@F\&`"^#9*+`(()A!@`A@F(&`"*"8P8`(X)D!@`D@F4&`"6"9@8`)H)G!@
- M`G@F@&`"B":08`*8)J!@`J@FL&`0N#=*/8H0R#`!T!/8,`'@$^@P`?`3^#=0
- M8A$(,`$0$Q@P`2`3*#`!,!,X,`%`$T@P`5`36#`!8!-H,`%P$W@P`8`3B#`!
- MD!.8,`&@$Z@P`;`3N#`!P!/(,`'0$]@P`>`3Z#`!\#@E.#;J482`"`D0F(`8
- M"2"8@"@),)B`.`E`F(!("5"8@%@)8)B`:`EPF(!X"8"8@(@)D)B`F`F@F("H
- M";"8@+@)P)B`R`G0F(#8">"8@.@)\)B`^#D2BX`("1"8@!@)()B`*`DP&(0X
- M.KH30$I(P`103%C`!&!,:,`$<$QXP`2`3(C`!)!,F,`$H$RHP`2P3+C`!,!,
- MR,`$T$S8P`3@3.C`!/!,^#I`B44(P`003!C`!"!,*,`$,$PXP`1`3$C`!%!,
- M6,`$8$QHP`1P#'@[0MT)@"6(8`*0)IA@`J`FJ&`"L":X8`+`)LA@`M`FV&`"
- MX";H8`+P)O@[H,0B"&`"$"888`(@)BA@`C`F.&`"0"9(8`)0)EA@`F`F:&`"
- M<"9X8`*`)HA@`I`FF&`"H":H8`*P!K@\H>Z$P!+(,`'0$]@P`>`3Z#`!\!/X
- M/%!B$0@P`1`3`!(!,H,`$P$S@P`4`32#`!4!-8,`%@$V@P`7`3>#`!@!.(
- M,`&0$Y@P`:`3J#`!L!.X,`'`$\@P`=`3V#`!X!/H,`'P/24]-GA`\(J`"`D0
- MF(`8"2"8@"@),)B`.`E`F(!("5"8@%@)8)B`:`EPF(!X"8"8@(@)D)B`F`F@
- MF("H";"8@+@)P)B`R`G0F(#8">"8@.@)\)B`^#Z9``P(F(`0"1B8@"`)*)B`
- M,#^9.#\!B.&S(/\>+R#`R@"`8@"`"`!20,!`"<#E"&"K`F$F8F`"8R9E8`)F
- M)F=@`F@F:F`":R9L8`)M)F]@`G`F<6`"<B9T8`)U)G9@`G<F>6`">B9[8`)\
- M)GY@`G\F@&`"@2:#8`*$)H4!"(8@`1`-`$"&`2T`(`$`"`!``0"]`:D/X+&-
- M(=#('B,5A?Q3C_U,38&3#AP1`0Z05T],64=S'DU9#04!$F`<#1\($F&9IT`E
- M-"(4R(W$`$1)3;J)4TE:#B:!A"H*8W-OQE!&CX)LLFH\!T!!!5U32E5$1$!.
- M5U4N1415SR.0`08@<T5%PX19`YYC/6A!0TLRK$Z0($99($16K4%)3%/F!Y4!
- M!R!UFAD).I%`$1&=+Y$[QS01`H!624=!)6*0#9P!!2`^/CX@<"3;Q5\@T$M%
- MD%@H3P$%14<YDB`\/#P-#9IAJ2XN+G-/4E+AE4%"3U5<`N(G0E5'4R$-=&$-
- M&@(!!=Y-DZQ3(%"<`T].04Q)5%D@14Y(04Y#15)3`+'\\"X@TO\F#O8W<#$%
- M!4]W%4$@4T5#4D4(#U1%6%0@34534T%'1303(%E/5R$@Y/_)`/#YI0$I_H4!
- MJ0AT$T<8C1C0K<<.Q`$"@A`%*?P)`[DPK<D)((T1T,#:_(7^80\>:&!,!@"-
- M05DP4*D$A?VI7('7@ZD6LB2,YOWFEBORB8'`2-#WJ1V1_)'^R-#YHL"&6NB&
- M6*(*AFBB#(9JH@Z&;*(0AFZB$H9PD,@=*W*AEB`P`F$2"%*[DNA)M(T$%`(!
- MR$R-`L`-@XTAW(*-(L`-1(U!W+R-0A9`=HT@%HTERP5G\3DV1'@@G_^ER\E`
- M\"_)+LT*0MY)("#)-]`+H@/*_@`6RA#Z,!')+6(W1Z.%3)N"R3+"UP:&$0'F
- M..8YI3H$%P.%.J6QK`+)P#"6$%^QI?@8:0C!Z\"%^*4YE"*L#%UL`#L%`4$H
- MO!0$A3PI"(T_^0!"/<$,`#J%/FTB"CN%0*4\=@!"I?]HA3@#0#C)-`5$ICND
- M//6112EY3$9AG<L*(,E'ID)@QD)(4,*?$-Z`22%X"`%L@E@D]!A(A0GH`L(0
- M%.!`Y@<+?D200$FF0Z1$:HD1$$J0'B/(3:9`OQ,\`%=`6&$"",L2`0Q%"SZD
- M/=)DRCCYL(202Z8_I$)!#:#0ID"D0;VS`8#*&!`!.&HXY?^F/:0^Q'-HRR07
- M`,NU*4RB`-EA!`_)AI`KV>@`)AAY0!:0(,(*A?^$^8I(\`ZT!KD`%L7_D`58
- M%T3RI/F4!VBJZ(@0R\HP)(:MM0?)`%?W`6B)9``!T`8@3(M,=83)`M`#(-"/
- MIJW*$-REO]`_-/$;&*3L`!B%QD`I+EH!X<>B&,%PC%FB(X036Z+(O7`P'-[_
- M6/`7AJ!XBDI*2AAIIX5<BBD'J.(9(7*FIO_*T-R"I22_J<:B>(X8T(T`W:D9
- MA;Q,8X(B5^Z)<(B.(`DL*$5612*>`!<`4S`$1$0IQAT)@0?$0`4P`:$(24Q(
- M&_$05$L@2;<0)%*#1S$F(4$R%1%2,2U,DT]25$%,LA=#$R!.3U0@2E535$E&
- M6=+L2$4@5T%94R!/1B!G3T0@5$\@34%.(B`M+2"0X@!%+D-534U)3D=3YLM6
- M4C`4PA<0"(U0&Q``E!=LA/`%!!KYHY``-$:(XL:LH`.(Z@5``@20,`!,_[F*
- M./VB3`+&_[<<B$`"!)@0%L(`-@@')@J`"87YN4@8,0D8\_D8OHTU?0`7D`+F
- M!`]0S/F90!9`AID`%H@0HV`.KP#(Q<8+,$#8B"ZTK+X`R25&",06>*+_BD@6
- MT3CE0C6W"*;_DD[</%NX8M9(4B-B29%!2K'(H$&E2]AJ1$PL,BA-EAD3PZ5%
- MI#M>&F#!`D:D/#/P0H5'I#V%:[%K2$0L0JAHI)9KP4F`@A04$*@^R0JP7/^J
- MO0`5JJ0>5@HJ%@,/H$*D0'90,$BIH+:"_Y`#YD,5"X9":&4S0TKP!LVP6(B&
- MJ&K)H)`(W#Y"J8D:0Z1!#B0D:29#:2D@9^,!9Q0/::"`1*0_BH5.2F^821QI
- M`44IL6](L6VD_SCQ;87_:/%OI?]<=T$0"UP!#:D`\`D8::C)R)`"J<>%09$:
- M/((893G6'4?NZ8XC6(`8M*,)(D@P0S%H1Q.T@H'&H!U-$$$"2%"0&)JF0"DY
- M>Y'D1,"2$P`)3@0@!2>"0()G7?B3X#&2#)\S8WCG(VQ'BR$S:@QW<P2P6#%X
- MQ(RA=HY@$T-XE1'#5M08!*A@I:Q(..4Z*`P7P7`$3>7!Q9`63;P9,8)-?*&-
- MKB""Q90)$T-:-$1%'C^1.T?&N>!&5<BM+[#)B.&V1@PU2G"-&B7DU8AA+6H,
- MW78$T`K"G'T068QB:(6L:%4``XWA7YI@%7A$D$`Q_$L33(!@%1`LAG]I@@D0
- MK$)3BV`!8OB7)H@@J&7"Q)`R31"(U2E8"HT!)#,2(909"4'*C`2OAREBIR<B
- M$$$H$8@FH!19C$$T:@RG5(0<(;S$B$&5QE!"PX27&HTB]8"(DF<C@IAE49
- MI?@3DZ88?&;$L%<U!H<Y@@X0$&K$<$,UACHK0HX0@&C$$$PUAL,IIBG28Z48
- M@++&$$%%8!D5@@.,X;ZJCS+F8KBOO*H\N!CVJPE00+;)<3'L5Z)3OFP,>K8$
- MF@I02N;!Q=!<540Y?4%L:\AQ<G2"V-:0(=B"P(-B33E.04Y/D!(AX,!06$Y1
- MD!-2Q-R6`!(4)%.6$U3D!%4!ISL$R3RIC#(0.AJQT%`;0D,<B4"]J3B:E)@D
- M`@4E%"@CH$`!(V5>7@PGT0F<1"=P$IU`F@S!D@DC<2`4[4@Q),F0-L4+-RA>
- M0#79,C.*%S10O(`RX@4R%*=H,>A$L"8NB9H$+$5-@K`80P"CJ4`E`414400B
- M52@"$5.4TXHQG,0.<!([P$GL`"<A#V+0`0+MC!A.8@<XB1W@)':`DY`',>@`
- M(44'(B@Z0"#1`2!*2/P8_HU3`HMB>(\DX#V2@/=(`DIC"'I8N+="OP0A*G:`
- MJ-@!HF('B`H=(+S'#O`>.\![[`!T,P0:2*;0,`%B1@RN-&.I**)A0E3L`%&Q
- M`T3%#A`5.D`VT0$WB@XU4'2`-0)#()4<IDTA)0&WD03<1A)P&TG`;2`!&P4)
- M'"A(0!I!`AI*_50PQ9-.*/<13Y3["$T*?@0I`-,^)88C*3&8QXB!.222Y0A$
- MRG($!`4YC@2E5(TE.E6-17`/4XT%1U,Q$D`%I5&-)AU2C4;&I5"-!L;D4%C^
- MC`:@V$8'HC5#&)F-_S`#3'6B*D@13(``B6(0D"H(A#B+04"J8`($2!2#@%1N
- M)<?%("!5T`.#RGH,&4R`@0(?.882DJ&,Q(LRY00S.31!RH6&<GJ.3)LU6,XV
- MD7,W)#6^*N(%*Q0O*:!X`2FE2R<H7D`H\0(FBA<F4+B().(%)10O(Z!X`2$T
- MAI"EI;$DT"@MBE4$+L4J@BPR%4<VL8HWH%A%-5"L(C4H53$S%*L(-(I5!#+%
- M*H(R4A5#P(LCY"Z"0W(700.YBR`$10,2%`1)8APA1`EF*""6$R'D!"(I$5]*
- MHXLCY00D.25!2H19DN-B)CDG04XHD"6`I4R8*5A.*I`3*Z1$IR@G?LB$B2SE
- M!"TY+JEBA3NIH84\J7R%/:T"07H^K2+@!C^M0A:%0"!IAJ5!A2^E0H4PI4.%
- M,:4A1AP)(BA(0"`I,B<*$BA0D(`F@@0FE",DH2`!)04)(RA(0"/YD4(@<5*E
- M*HV$A:4KC5ZE*8WI!46JI3"-(?X.,8U!G"^-`<--+[`"7*4MC2)W#BZ-0L:E
- M+(T"QN0L+.NJH`*$^ZD#A:.%_R!VF6"D^UU;!310A?ZH2DI*&*:_T`YI0/0\
- M&C`*0!MAT`QII\B!6H;!O@!;AL*%7(5FA6"I:;);F"D'A?I@".V:LL"Y+9R;
- M0&+2D!9#T!?LG6#:)74!WP@/\F<8D2^\FQ,.HV%6@C]`*Q*"#I@H=A`(Y:FJ
- MF.D`D/KPND.@8-`4C)>*\)2->D":HOJO+O2&1BRU6B"GJBKEJ)`6J(HGN)"0
- M`<@XY;<"YH@P!B"LG$SQI&`8IJ=[YHHE9$6FM98&(X5EJ&JV$03&J&`*M(UF
- M65*J"-W1;I4YH2+T6<)A*NX.1Y*%G\"0.^R<DXB,#UE2J@COD6QPCK2D-,<^
- MHI+*:-$@,$/H#8$9P@(1>+817F!>@F4R+T'8!;;*MD09IB+K<"19^`D,N4.?
- M,]'(C[G%#_V9DKF@!/T,GQ#^`SONYY]-#Y)H@)%HPWD,$L4\BK!`%!0'D`_H
- M.H8`%MF0`QCFJ)$^QXP!/VX-4S*$G\B0.YJAQJ70>Z3\$_<%I*.(X,E9Z84)
- MI83\_?*0<!9Y2+VAXA.G2A^H4"#"#Z2ADZ9*'*96]HBDT@>DQ:0T/ZK$#ZN&
- MJ<:ST'VD_9BJR,2CT`*@ZX/_$`H)_I@)!@#&\.>%LH6SA/V0)0"2<+1`'/D0
- MAK`#3)"=2KT@XH$X0,:%MD^(:JJDLLAUPCCY`,.P!J(`.'Z0%*HXX,2JA5=)
- M_VD`A5FEM'%9./%7ZX*0!^CELL6RL/F%N)A*Y]V&MZ6K?`N&<*2=!B"XQH$2
- M6JNEI^6IA:<1Y@2HBJCKI!K%7_`0A5^!<8U`J#^\7LBQN]`F;R8300&X`!"$
- M3[)?,(="`/$@4JA5(-BE94(]7[`;:0/0%*2GN<D<I+4Y)Q(+$4&P(*1!^K%Q
- M(%6FIJ<@<<S"(%V17::UO0#-,7$18Y'@S+DXY;BP$V6R5-P`&!0#D`Z%N:6U
- MY;>%M:JP)G.V&$Z1\`*4?0#%Q#4#Q67P'"V%PJP(@29,`HHI^!AEP24X"+9E
- MPA.I`:3^D;N8\`G&_@+&^C`&JO9,2*;!<(C&8,9FQERI8,0RH`>$^J5=P0E`
- M7:5>4UZE8\`2@&.E9*9DI<$XZ4"%P:7"Z0&%PDSQHZ1EJ9F16V!L6P"*!V4`
- M;%\``JB]%+='$`@P`1`3`!(!,H,`$P$S@P`4`32#`!4!-8,`%@$V@P`7`3
- M>#`!@!,00R$6`9@3H#`!J!.P,`&X$\`P`<@3T#`!V!/@,`'H$_`P`?A@)18!
- M"!,0,`$8$R`P`2@3,#`(.&&E'D4(2)B`4`E8F(!@"6B8@'`)>)B`@`F(F("0
- M"9B8@*`)J)B`L`FXF(#`"<B8@-`)V)B`X`GHF(#P"?AA*+$(")B`$`D8F(`@
- M"2B8@#`).)B`0`E(F(!0"5B8@&`):)B`<$%X8BCU*$*(P`203)C`!*!,J,`$
- ML$RXP`3`3,C`!-!,V,`$X$SHP`3P3/AB0(E%",`$$$P8P`0@3"C`!#!,.,`$
- M0$Q(P`103%C`!&!,:,`$<$QXP`2`3(C`!)!,F,`$H$RHP`2P#+AC0JE'$0+(
- M)M!@`M@FX&`"Z";P8`+X8THL`@@F$&`"&"8@8`(H)C!@`C@F0&`"2"908`)8
- M)F!@`F@F<&`">":`8`*()I!@`I@FH&`"J":P8`*X)L!@`L@FT&`"V";@8`+H
- M)O!DH,1D1CV*$`@P`1`3`!(!,H,`$P$S@P`4`32#`!4!-8,`%@$V@P`7`3
- M>#`!@!.(,`&0$Y@P`:`3J#`!L!.X,`'`$\@P`=`3V#`!X!/H,`'P$_AE4&(1
- M"#`!$!,8,`$@$R@P`3"#.&90ZE&$@$@)4)B`6`E@F(!H"7"8@'@)@)B`B`F0
- MF("8":"8@*@)L)B`N`G`F(#("="8@-@)X)B`Z`GPF(#X9A*+@`@)$)B`&`D@
- MF(`H"3"8@#@)0)B`2`E0F(!8"6"8@&@)<!B$>&=2CR($B$R0P`283*#`!*A,
- ML,`$N$S`P`3(3-#`!-A,X,`$Z$SPP`3X9Y18!`A,$,`$&$P@P`0H3##`!#A,
- M0,`$2$Q0P`183`!&A,<,`$>$R`P`2(3)#`!)A,H,`$J$RPP""X:)1Z%"'(
- M8`+0)MA@`N`FZ&`"\";X:*#$(@A@`A`F&&`"("8H8`(P)CA@`D`F2&`"4"98
- M8`)@)FA@`G`F>&`"@":(8`*0)IA@`J`FJ&`"L":X8`+`)LA@`M`FV&`"X";H
- M8`+P:4II;-2C"`$($Q`P`1@3(#`!*!,P,`$X$T`P`4@34#`!6!-@,`%H$W`P
- M`7@3@#`!B!.0,`&8$Z`P`:@3L#`!N!/`,`'($]`P`=@3X#`!Z!/P,`'X:B46
- M`0@3$#`!&!,@,`$H$S`P"#AKI1Y%"$B8@%`)6)B`8`EHF(!P"7B8@(`)B)B`
- MD`F8F("@":B8@+`)N)B`P`G(F(#0"=B8@.`)Z)B`\`GX:RBQ"`B8@!`)&)B`
- M(`DHF(`P"3B8@$`)2)B`4`E8F(!@"6B8@'!!>&PH]2A"B,`$D$R8P`2@3*C`
- M!+!,N,`$P$S(P`303-C`!.!,Z,`$\$SX;$")10C`!!!,&,`$($PHP`0P3#C`
- M!$!,2,`$4$Q8P`1@3&C`!'!,>,`$@$R(P`203)C`!*!,J,`$L`RX;4*I1Q$"
- MR";08`+8)N!@`N@F\&`"^&U*+`(()A!@`A@F(&`"*"8P8`(X)D!@`D@F4&`"
- M6"9@8`)H)G!@`G@F@&`"B":08`*8)J!@`J@FL&`"N";`8`+()M!@`M@FX&`"
- MZ";P;J#$;D8]BA`(,`$0$Q@P`2`3*#`!,!,X,`%`$T@P`5`36#`!8!-H,`%P
- M$W@P`8`3B#`!D!.8,`&@$Z@P`;`3N#`!P!/(,`'0$]@P`>`3Z#`!\!/X;U!B
- M$0@P`1`3`!(!,H,`$P@SAP4.I1A(!("5"8@%@)8)B`:`EPF(!X"8"8@(@)
- MD)B`F`F@F("H";"8@+@)P)B`R`G0F(#8">"8@.@)\)B`^'`2BX`("1"8@!@)
- M()B`*`DPF(`X"4"8@$@)4)B`6`E@F(!H"7`8A'AQ4H\B!(A,D,`$F$R@P`2H
- M3+#`!+A,P,`$R$S0P`383.#`!.A,\,`$^'&46`0(3!#`!!A,(,`$*$PPP`0X
- M3$#`!$A,4,`$6$Q@P`1H3'#`!'A,@,`$B$R0P`283*#`!*A,L,`@N'*4>A0A
- MR&`"T";88`+@)NA@`O`F^'*@Q"((8`(0)AA@`B`F*&`","8X8`)`)DA@`E`F
- M6&`"8"9H8`)P)GA@`H`FB&`"D":88`*@)JA@`K`FN&`"P";(8`+0)MA@`N`F
- MZ&`"\'-*<VS4HP@!"!,0,`$8$R`P`2@3,#`!.!-`,`%($U`P`5@38#`!:!-P
- M,`%X$X`P`8@3D#`!F!.@,`&H$[`P`;@3P#`!R!/0,`'8$^`P`>@3\#`!^'0E
- M%@$($Q`P`1@3(#`!*!,P,`@X=:4>10A(F(!0"5B8@&`):)B`<`EXF("`"8B8
- M@)`)F)B`H`FHF("P";B8@,`)R)B`T`G8F(#@">B8@/`)^'4HL0@(F(`0"1B8
- M@"`)*)B`,`DXF(!`"4B8@%`)6)B`8`EHF(!P07AV*/4H0HC`!)!,F,`$H$RH
- MP`2P3+C`!,!,R,`$T$S8P`3@3.C`!/!,^'9`B44(P`003!C`!"!,*,`$,$PX
- MP`1`3$C`!%!,6,`$8$QHP`1P3'C`!(!,B,`$D$R8P`2@3*C`!+`,N'="J4<1
- M`L@FT&`"V";@8`+H)O!@`OAW2BP"""808`(8)B!@`B@F,&`"."9`8`)()E!@
- M`E@F8&`":"9P8`)X)H!@`H@FD&`"F":@8`*H)K!@`K@FP&`"R";08`+8)N!@
- M`N@F\'B@Q'A&/8H0"#`!$!,8,`$@$R@P`3`3.#`!0!-(,`%0$U@P`6`3:#`!
- M<!-X,`&`$X@P`9`3F#`!H!.H,`&P$[@P`<`3R#`!T!/8,`'@$^@P`?`3^'E0
- M8A$(,`$0$Q@P`2`3*#`!,(,X>E!W0D`)2)B`4`E8F(!@"6B8@'`)>)B`@`F(
- MF("0"9B8@*`)J)B`L`FXF(#`"<B8@-`)V)B`X`GHF(#P"?AZ*+$(")B`$`D8
- MF(`@"2B8@#`).)B`0`E(F(!0"5B8@&`):)B`<$%X>Z@[@*$$B$R0P`283*#`
- M!*A,L,`$N$S`P`3(3-#`!-A,X,`$Z$SPP`3X>Y18!`A,$,`$&$P@P`0H3##`
- M!#A,0,`$2$Q0P`183`!&A,<,`$>$R`P`2(3)#`!)A,H,`$J$RPP""X?-2=
- MP%`"R";08`+8)N!@`N@F\&`"^'Q*+`(()A!@`A@F(&`"*"8P8`(X)D!@`D@F
- M4&`"6"9@8`)H)G!@`G@F@&`"B":08`*8)J!@`J@FL&`"N";`8`+()M!@`M@F
- MX&`"Z";P?:#$?28/`?&*@`@)$)B`&`D@F(`H"3"8@#@)0)B`2`E0F(!8"6"8
- M@&@)<)B`>`F`F("("9"8@)@)H)B`J`FPF("X"<"8@,@)T)B`V`G@F(#H"?"8
- M@/A^F0`,")B`$`D8F(`@"2B8@#!_F3A_`8AAGX`!@@2&"8P0E!F>)*HQN$#(
- M4=ID[GD$D!RI-L12X7``D"&R1-9I_)`DN4[D>A&H0-AQ"J0^V700K$GFA"+!
- M8`"@0>*$)LEL$+19_J1*\9A`Z)$ZY(XYY)`\Z99$\J%0`+!A$L1V*=R01/FN
- M9!K1B$#XL6HDWIE4$,R)1@3"@4``P(%"!,:)3!#4F5XDZK%X0`C1FF0N^<20
- M7"GVQ))A,`#0H7)$%NF\D&0Y#N2ZD6A`&/'*I'Y9-!#LR::$8D$@`.#!HH1F
- M22P0]-F^I(IQ6$`H$?KDSKFDD'QI5D0R(1``\.'2Q+:IG)"$>6YD6E%(0#@Q
- M*B0>&100#`D&!`+W_P`!`@0&"0P0%!D>)"HQ.$!(45ID;GF$D)RIML32X?``
- M$"$R1%9I?)"DN<[D^A$H0%AQBJ2^V?00+$EFA*+!X``@06*$ILGL$#19?J3*
- M\1A`:)&ZY`XY9)"\Z19$<J'0`#!ADL3V*5R0Q/DN9)K1"$!XL>HD7IG4$$R)
- MQ@1"@<``0('"!$:)S!!4F=XD:K'X0(C1&F2N^420W"EVQ!)AL`!0H?)$END\
- MD.0YCN0ZD>A`F/%*I/Y9M!!LR2:$XD&@`!(H3F2:P0=-D^I`IQV$"H$7KD
- M3KDDD/QIUD2R(9``<.%2Q#:I')`$>>YDVE'(0+@QJB2>&900C`F&!((!@$?^
- M`1/];R(W15!:86AN<WA\@(2(BXZN]@]9G9^AHZ6GJ:JLKJ^QLK2UMKC*>B*\
- MOK_`0HW$Q<;'R,G*2)@DS<XBE`C2BDL$,!$$F@AN(MS<XHG?W^#@4-.",!1!
- MIN;GY^CHZ>GJZNOK[.SM[>WN[N_O\/#P\?'R\O+S\_3T]/6%X[)Y?]G9VMK:
- MV]O;8H7<W=W=WM[>W]_?9(*PJB`$X@SCY.3D00;E3.;`".>,"!$,D"";0<#-
- M(``080`("`$`#P`"(7IF.CHC`3H5`CH.`SH,!#H)!3K0FC("!SH&"#()8`@*
- MY@LZ!0P-#0TZ!`X/#P\0$!`1$1$2$A(3$Q04%!45%A87%Q@8&1D:(,CW*0CX
- M5"`A(2(C(R0E)B8G*"DJ*RLL+2XO,#$R,S0U-C<X.3L\/3Y`U/%F"9AE3"C*
- M45)45EA96UU?86-E9VEK;6]R='9Y>WZ`@X6(BXTOKB29G)^95P,D`083"3`!
- M#!,/,`$2$Q4P`1@3&S`!'A,A,`$D$R<P`2H3+3`!,!,S,`$V$SDP`3P3/S`!
- M0A-%,`%($TLP`4X343`!5!-7,`%:$UT!"&"0'5P`@@)J_`!.`$Y4=#450\6L
- M='AA8"<^/CX@;75L=,5V<X-'3@5%A$!XH$A)1TB@0EE480Q&,RY9"")T99'H
- M0D4(/41T-UIP;(/8<&]S>7)P3U-)(Q&`H$]2MJ`_E!]LY"(V:88D2)`P5$A%
- M3I$G8605(S$V.),Y041$+*!!3D2@24:@<W1I;&R@3D5'051)5D4N+BXOCF-M
- M<'`1,@,1!V)C8R`Z;VL-(&QD82`C,#`@.W-%5*!43Z!:10$M'A!5"/\`[N[N
- M`+N[QP!`4%6[@0"`JA&J1"A@510`(`!5JA0`[MV[=Q`!@'>[W>X(`+M5[C2%
- M?D$!`O_;3IF]P]3!K1@$YY#%(``,`(D@``S_D`$@&.<@!`!&&-O,``!^O5,"
- M!O]^`0EKH@0$0``P]^OW[]?O"#8`,"("6/O5J]\`5RW?J]7]/`@`_]^OW_OU
- M^_\!I'$ORZ&/U@%B'P+L!I[`J;Z]O+NZN+>UL[&OK:NIIJ2AGIN8EI.0C(F&
- M@X!]>G=T<&UJ:&5B7UQ:5U5344]-2TE(1D5$0T(;\X$!!4!!04)#1$5&2$E+
- M34]14U576EQ?$/^H:FUP='=Z?8"#AHF,D).6F)N>H:2FJ:NMK[&SM;>XNKMH
- M?*B"H0H!`00:D.:!0,8@("`!"(!N``(#!08("0L,#@\0$A,4%1<8&1KNB!P=
- M2H@!0"`?'Q\>'AT<&QL:&1@7%103$A`/#@P+"0@&!0,"`/[]^_KX]_7T\O'P
- M[NWLZ^GHY^;GRB/DXRHA!@$'X.'AX>+BX^3EY>;GZ.GK[.WN\/'R]/7W^/K[
- M_?Z0<0!\`P">`0#'`(`%`/]_/Q\/!P,!)#$`O@$`SP"`8P#``@"`P.#P^/P2
- MV#8,F'^]U(`Z`X(&`""#0/0`O?7V]O;W]_?X^/GY^?KZ^OO[^_S\_/W]_?[^
- M_MC%1;2P`04-(W``"$30`"((YB$`B#``!(2`__#_`00`_P`"`!0!%2,N-S]&
- M3%%66EYB96AL;G%T=GA[?7^!@X6&B(J+C8Z0D9.4E9>8F9J;G)Z?H*&BHZ2E
- MIJ>GJ*FJJZRMK:ZOL+"QLK.SM+6UMK>WN+FYNKN[O+R]OKZ_O\#`P<'"P\/$
- MQ,7%QL;'Q\?(R,G)RLK+R\S,S,W-SL[/S\_0T-'1T=+2T]/3U-34U=75UM;7
- MU]?8V-C9V9#F`;``@(03))0PO3'JI$?^2O.1\@[R4/(S\U?QRO'M]C[Q+_-F
- M_J7T[?4!L$6,`P"]`0$`O1H:&AH:&AH:&AH:&AH:&AH:&AH:&AH:&AH:&AH:
- ,&AH:&AH:&AH:&AH:
- `
- end
-
- =========================================================================
- @(#): bottom