home *** CD-ROM | disk | FTP | other *** search
Text File | 2019-04-13 | 161.1 KB | 3,597 lines |
-
- ########
- ##################
- ###### ######
- #####
- ##### #### #### ## ##### #### #### #### #### #### #####
- ##### ## ## #### ## ## ## ### ## #### ## ## ##
- ##### ######## ## ## ## ##### ## ## ## ## ##
- ##### ## ## ######## ## ## ## ### ## ## #### ## ##
- ##### #### #### #### #### ##### #### #### #### #### #### ######
- ##### ##
- ###### ###### Issue #7
- ################## Feb. '94
- ########
-
- -----------------------------------------------------------------------------
- Editor's Notes:
- by Craig Taylor (duck@pembvax1.pembroke.edu)
-
- This net-magazine is still alive after over two years suprising even
- myself. There should be more to come also!! And it's been late everytime
- it's been released. :-) I dunno - I'm trying not to make that a
- tradition but next time I don't think I'm going to set any firm dates so
- it can't possibly be late.
-
- Lesee, first to address some questions and queries that have been going
- on over the network:
-
- - The C project that I mentioned a while back is now officially
- defunct, dead, resting in peace... whatever you want to call it.
- There may be other individuals working on their own version of an
- ANSI C compiler but the group that was setup is no longer.
- Basically, it was a problem of too many programmers, too few
- managers (and we know programmers *grins* - They all want to do it
- their way. Incidentilly - my way _was_ the best. ;-) )
-
- - The C65 exists but there are very few of them out there and
- GrapeVine no longer sells them (out of stock I believe). It was only
- made in small quantities for prototype work. There have been
- numerous individuals reading comp.sys.cbm that see mention of the
- C65 and assume that this creature Commodore released. Commodore sold
- a warehouse and its contents to Grapevine and Grapevine stumbled
- across them and sold 'em. They are functional but due to the low
- number of them available I doubt that there will be any C65 targated
- applications. (Someone prove me wrong, please?)
-
- - Geesh - That stupid article about the 1351 mouse that I kept
- promising from issue 2 on I've officially declared dead. It may come
- around later but for now it's dead. It's existed as a promise in one
- form or another since issue 2 so this message officially kills it.
-
- - Also there was some confusion last time about my wording about not
- writing any more articles and such (or rather, not as many as I had
- been). Basically, yes - I'm still going to do C=Hacking - it's just
- that because of time, frustration, school and jobs that I don't have
- as much time to devote to researching and writing articles. That's
- all that I meant to say - some people were concerned that C=Hacking
- was no longer going to be released...
-
- As always, here's the obligatory begging for authors on any type of
- software or hardware project that involves the Commodore computers.
- Please, Please if you or your user group has any information or material
- concerning the Commodore computers that you think may be appropriate for
- C=Hacking let me know via e-mail at duck@pembvax1.pembroke.edu. I'm
- looking for anything from hardware schematic, programming theory to
- actual programming techniques, programs.
-
- The articles in this issue of C=Hacking I'm especially pleased with.
- There are two articles concerning the VIC chip and its operations that
- detail how certain "magical" techniques are performed. Also, Marko
- Makela has written a very detailed, interesting article on various
- memory techniques for the C-64. We also have a summary of the ACE
- programming / operating system and a referance guide on how to write
- applications for it. I've also included an InterNet guide that I've
- started writing to show individuals how to use the InterNet to get
- Commodore-64/128/Vic-20 related material. Included within that is a list
- of FTP sites containing numerous programs.
-
- =============================================================================
-
- Please note that this issue and prior ones are available via anonymous
- FTP from ccosun.caltech.edu (among others) under pub/rknop/hacking.mag
- and via a mailserver which documentation can be obtained by sending
- mail to "duck@pembvax1.pembroke.edu" with a subject line of
- "mailserver" and the line "help" in the body of the mesage.
-
- =============================================================================
-
- NOTICE: Permission is granted to re-distribute this "net-magazine", in
- whole, freely for non-profit use. However, please contact individual
- authors for permission to publish or re-distribute articles
- seperately. A charge of no greater than 5 US dollars or equivlent may
- be charged for library service / diskette costs for this
- "net-magazine".
-
- =============================================================================
- In This Issue:
-
- Commodore Trivia Corner
-
- This section of C=Hacking will contain numerous questions that will test
- your knowledge of trivia for the Commodore computers. Each issue they'll
- be answers to the previous issues questions and new questions. How much
- do you know?
-
- InterNet Resources for the Commodore 64 / 128 V1.0
-
- This article goes into detail about the available resources on the InterNet
- and is meant to introduce people to the wonderful, wacky world of the
- InterNet. It covers what the InterNet is, what capabilities it has and
- how to access those capabilities. In addition, it also includes Howard
- Herman's latest list of File Transfer sites for the Commodore computers.
-
- Hiding kilobytes
-
- Most Commodore 64 programs do not utilize even nearly all of the 64 kB
- random access memory space. By default, there are only 44 kilobytes of
- accessible RAM. This article describes how you can take the hiding 20
- kilobytes to use.
-
- FLD - Scrolling the Screen
-
- This article, using a technique described by Pasi Ojala in the last
- issue of C=Hacking, gives an example of a program using Flexible Line
- Distance technique.
-
- Tech-tech - more resolution to vertical shift
-
- At one time half of the demos had pictures waving horizontally on the width
- of the whole screen. This effect is named tech-tech and it is done using
- character graphics. How exactly and is the same possible with sprites ?
-
- ACE-128/64 PROGRAMMER'S REFERENCE GUIDE (version 0.9, for Release #10)
-
- This article explains the complete system interface for the ACE-128/64
- computing environment. It is intended to be used by programmers for
- developing software to run on top of the ACE kernel. ACE is a program
- for the Commodore 128 and Commodore 64 that provides a command shell
- environment that is similar to that of Unix.
-
- ===============================================================================
- Commodore Trivia Corner
- by Jim Brain (brain@mail.msen.com)
-
- Everyone who reads this article has had, or presently owns a Commodore
- computer of some kind. I own more than one, which is not uncommon among
- Commodore enthusiasts. Well, I bought my first Commodore computer in
- 1982, a brand new Vic-20 with some game cartridges. I had wanted an
- Atari, but father knew best and he told the then 11 year old son that
- computers would shape my life more than any game machine. Well, it is
- 11 years later and a Computer Engineering Degree earned, and I have
- spent many a night during that time playing on many models of Commdore
- equipment. Now, I would like to share the knowledge I have with you in
- an interesting way.
-
- As you now know a little about me, let us see how much you know about
- the machines and company that binds us all together. The following is
- an installment of Commodore Trivia. These questions have been gleaned
- from books, magazines, persoanl knowledge, work on the machines in
- questions, and other fellow commodore users happy to share interesting
- bits of semi- useless knowledge concerning the CBM systems.
-
- This installment consists of two parts, the December 1993 edition
- complete with answers and the January 1994 edition without answers.
- Each new issue of Commodore Hacking Magazine will contain more
- questions, as well as answers to the previous issue's questions. Each
- new edition is also posted every month on the 12th of the month on the
- Usenet newsgroup comp.sys.cbm. Winners will be announced on the
- newsgroup, and prizes may be awarded. For anyone wishing to submit
- answers from this article, please email your responses with question
- numbers preceeding each answer to :
-
- brain@msen.com
-
- The answers to this edition will be posted on the 12th of February in
- comp.sys.cbm with the next edition of questions. Have fun trying to
- answer the questions and feel free to send me a note with new questions.
- I can always use them.
-
- [Ed's Note: In addition, the mailserver that I have setup for
- C=Hacking will make provisions to allow individuals to retrieve the
- newest set of questions and last month's answers. Currently not
- implemented, it should be available soon. Details in the next issue.
-
- Also due to C= Hacking being published fairly irregularly and not
- every month the column here will contain answers to the last issue of
- C=Hacking's questions and have new questions for the month that it's
- released in.]
-
- -----------------------------------------------------------------------------
- Here are the answers to the 10 questions in Commdore Triva Edition #1 for
- December 1993. [that were posted on comp.sys.cbm]
-
- Q $000) Commodore started out into computing with the PET series of
- computers. I am not sure if the first ones had PET emblem, but
- nonetheless, What does P E T stand for?
-
- A $000) Personal Electronic Transactor
- Since the acronym was made up before the expansion, the following
- are also valid:
-
- Personal Electronic Translator
- Peddle's Ego Trip
-
- Q $001) Commodore planned to manufacture a successor series to the
- successful Commodore 64 home computer. Both were intended to
- be Business machines. We all know this resulted in the Commodore
- Plus 4, but what were the machines originally called and what was
- the difference between the two?
-
- A $001) the 364, which had, among other things, a larger Plus 4 style case
- that housed the regular keyboard plus a numeric keypad. the 264
- turned into the Plus 4, with 64K of RAm. We will never know much
- more about the 364, since it got scrapped.
-
- Q $002) How much free memory does a Vic-20 have (unexpanded)?
-
- A $002) Oooh! There are many answers for this.
- The VIC has 3583 bytes of RAM for BASIC
- The VIC has 4096 bytes of RAM for ML
- The VIC has 5120 bytes of RAM. 4K of RAM + 1K for Video.
-
- Q $003) What early 80's Commodore software company had a Light Bulb
- as a company logo?
-
- A $003) Skyles Electric Works.
-
- The Vic-20 came out with a few peripherals I want the model
- numbers for the :
-
- Q $004) Disk Drive
-
- A $004) VIC-1540 - Same as 1541, only faster serial spped.
-
- Q $005) Cassette Player
-
- A $005) VIC-1530
-
- Q $006) Printer
-
- A $006) VIC 1515, which, by a miscommunication, could only use 7.5" paper.
- Evidently, someone thought 8.5" meant full width of paper w/ perfs!
- This printer was quickly supplanted and overtaken by the 1525, which
- should own this title in the first place!
-
- Q $007) 16 K Ram Expansion.
-
- A $007) VIC-1111
-
- Q $008) Commodore Introduced 3 printers that used the same printer mechanism.
- What are the model numbers.
-
- A $008) MPS 802 (Square Dots, Serial), CBM 1526 (Round Dots, Serial),
- PET 4023 (Round Dots, IEEE-488).
-
- Q $009) What is the diferences between the printers in #9
-
- A $009) MPS 802 (Square Dots, Serial), CBM 1526 (Round Dots, Serial),
- PET 4023 (Round Dots, IEEE-488).
-
- -----------------------------------------------------------------------------
- Here are the questions for Commodore Trivia Edition #2 for January 1994.
-
- Q $00A) What was the Code-Name of the Amiga while in Development?
-
- Q $00B) What is Lord British's Real Name (The creator of the Ultima
- Series)?
-
- Q $00C) What is the POKE location and value that will fry an early model
- PET?
-
- Q $00D) On the Plus 4 and C-16, the VIC chip was replaced with the TED
- chip. What does TED stand for?
-
- Q $00E) Commodore Produced a Letter Quality Printer in North America
- (maybe elsewhere) for the Commdore Serial Line. Name it.
-
- Q $00F) What is the version of DOS in the 1541?
-
- Q $010) What is the Version of BASIC in the Plus 4 and the C-16?
-
- Q $011) What are the nicknames of the original three custom Amiga chips?
-
- Q $012) Commodore produced a 64 in a PET case. What is its name and model
- number?
-
- Q $013) Commodore sold a 1 megabyte floppy disk drive in a 1541 case.
- Give the model number.
-
- Q $014) What does GCR stand for?
-
- Q $015) Commdore produced a drive to accompany the Plus 4 introduction.
- Give the model number.
-
- Q $016) What does SID stand for?
-
- Q $017) What does the acronym KERNAL stand for?
-
- Q $018) What version of DOS does the 1571 have?
-
- Q $019) What other two Commdore Disk Drives share the same DOS version
- number as the 1571?
-
- Q $01A) How many files will the 1571 hold?
-
- Q $10B) How many files will the 1541 hold?
-
- Q $01C) What did Commodore make right before entering the computer market?
-
- Q $01D) Commodore introduced an ill-fated 4 color plotter. Give the model
- number.
-
- Q $01E) Some formats of CP/M write disks using the MFM format. What does
- MFM stand for?
-
- Q $01F) On the Commodore 128, the user manual left two commands undocumented.
- One works, and the other gives a not-implemented error. Name both
- commands and what each one does or does not do.
-
- Some are easy, some are hard, try your hand at it.
-
- Jim Brain
- brain@msen.com
- =============================================================================
- InterNet Resources for the Commodore 64 / 128 V1.0
- by Craig Taylor (duck@pembvax1.pembroke.edu)
-
- [This article is placed into public domain by the author. Copying encouraged]
-
- The Internet
-
- Let me start this article with a quote by another author that everyone
- should heed when dealing with the InterNet:
-
- "One warning is perhaps in order---this territory we are entering can
- become a fantastic time-sink. Hours can slip by, people can come and
- go, and you'll be locked into Cyberspace. Remember to do your work!
-
- With that, I welcome you, the new user, to The Net."
-
- brendan@cs.widener.edu
- - Author, Zen and the Art of the Internet
-
- What is the InterNet?
-
- What exactly is the InterNet? Imagine if you will, when you were a kid
- stringing wires between houses in your neighborhood so that you could
- talk with the kids that lived beside you. You could talk to those beside
- you but not the ones that lived across town. Now, suppose that you
- wanted to relay a message to a buddy across town. The only feasible way
- would be to send a message to the guy next door; then have him send it
- to the correct person.
-
- This is the basic system of the Internet. Computers connected to other
- computers that are connected to others. In the above paragrph
- communication was limited because of geography - how close individuals
- were. The InterNet system; while geography does play a factor, relies
- more on how the sites grew up and were established as to how messages
- will get passed back and forth.
-
- There are also other networks hooked up to the InterNet that provide
- auxilary services to their local group of computers. One large one is
- BITNET and UUCP. Various bbs's also carry items from the InterNet such
- as the BitNet news. In addition, online services such as Genie,
- Compuserve, and others offer "gate-ways" or ways of getting access to
- the resources of the InterNet.
-
- Access To The InterNet
-
- Gaining Access to the InterNet There are several ways of gaining access
- to the InterNet. Your local college may be your best low-cost
- opportunity. Typically, if you are a student or faculty or staff, you
- may qualify to have an account that allows you to access all the
- InterNet facilities described above. If you don't fall into any of these
- categories your next best bet is an online service such as America
- Online, Genie, or Compuserve as these all support what is known as an
- InterNet gateway - allowing you t o access the InterNet through t hem.
- (At this time, I don't believe Prodigy has an InterNet gateway - if I'm
- wrong I'm sure I'll get tons of mail. Other online services also exist -
- I've only listed what I consider the "primary" ones.)
-
- Once you've gotten access to the InterNet you may be asking "Okay, I
- know what the InterNet _can_ give me - how do I do it?" Unfortunately,
- because the InterNet is run on differant computer systems this will vary
- from system to system. Your best bet would be to examine the
- documentation and help screens associated with the online service or
- college's facilities. Study them over until you can quote them backwards
- (well, not quite that much) - Study them over until you understand what
- they are saying. Also, having someone who is already experienced with
- the InterNet aid you in your explorations is a great help.
-
- What is E-MAIL?
-
- There are numerous individuals using the InterNet each day. Each is also
- able to write the other through the use of Electronic Mail or, as it's
- commonly called "e-mail".
-
- To send a message to me you'd use your mail program (the actual
- procedure varies depending on what type of machine you use) and tell it
- to send the message to my user name, "duck" at my site that I login at -
- (currently going to Pembroke State University) hence
- "pembvax1.pembroke.edu". So the full address with an "@" sign the
- computer needs to use to know how to seperate the computer name and the
- user name is "duck@pembvax1.pembroke.edu".
-
- It's easy to talk to somebody in Mexico, Germany, Australia with this
- method and it's quicker than the U.S. Postal system (which, on the
- InterNet you'll see referred to as Snail Mail (or s-mail) due to it's
- slow delivery time compared to e-mail). Projects, Questions, Answers,
- Ideas and general chit-chat on how the family is doing, etc can be
- relayed over the InterNet.
-
- There are also numerous abbreviations and notations that are used in
- E-Mail. Some of them are:
-
- ttyal8r - Talk to you later
- rtfm - Read the *uckin' manual
- imho - In My Humble Opinion
- rotfl - Rolls on the Floor Laughing
- lol - Laughs Out Loud.
- l8r - Later
- ;-) - (winks)
- :-) - (smile)
- :-( - (frowns)
-
- There are _many_ _many_ more - you can also find a huge list of the
- smiley faces (turn your head sideways and look at the ones in
- parenthesis above) on the InterNet.
-
- You may also hear the phrase "my e-mail bounced". What this means is
- that your message, much like a bounced check, did not work right and it
- was returned to your account. Typically this happens because of
- incorrect addresses, or an incorrect user name.
-
- Email Servers
-
- Another large way of getting information is from individuals running
- what are E-Mail servers from their accounts or from specific accounts.
- From Email servers you may request certain files; catalogs of programs
- that are availble for request; send messages to be distributed to other
- individuals and automatically subscribe yourself to the mailing list for
- new items.
-
- The only Email Server specifically designed for the Commodore computers
- is one ran by the author. It major intent is that of distributing the
- Commodore Hacking magazine as well as programs that are in the
- magazine. To get help on how to use it send a message to the author in
- the following format:
- To: duck@pembvax1.pembroke.edu
- Subj: MAILSERV
- Body of message: HELP
-
- This specific mailserver is ran twice a day so you should get your reply
- within approximately 12 hours. Please be sure to have a subject line of
- "MAILSERV".
-
- If anyone knows of any other Email Servers existing for the Commodore
- computers please let the author know.
-
- NewsGroups
-
- One of the primary purposes of the InterNet is for educational research
- and discussion. For this purpose, there are currently over 2000
- newsgroups established dealing with a wide range of social, politicial,
- science, computer and educational topics. Some of these range to inane,
- whimsical, to practical and useful.
-
- Two of these for the Commodore 64/128 line of computers are:
- comp.sys.cbm
- comp.binaries.cbm
-
- The names for the newsgroups start with a short abbreviation such as
- "comp" for computers, "sci" for science, "bio" for biology, etc... The
- second group of letters stand for the type of newsgroup "sys for system,
- binaries for binaries etc..." while the third describes it better -
- "cbm" in this case for Commodore Business Machines.
-
- The newsgroup, Comp.Sys.Cbm supports discussion about anything under the
- sun involving the Commodore 8 bit line of computers (and lately, even
- talking about the old old ancient calculators that Commodore mae that
- might not have even been 8 bit). Comp.Binaries.Cbm allows programs to be
- "posted" or made available to everyone who wishes them. There are
- programs available that will let you take the "encrypted" text-only
- version of the program that you see on the screen and convert them into
- the correct binary p rogram.
-
- Basically the rules for newsgroups are: 1) Enjoy yourself, 2) Don't
- harass others and 3) Try to stay on topic. Newsgroups are read by many
- many people - typically you'll get a response to an inquiry within only
- an hour or so - sometimes even sooner. But because they're read by so
- many people chatter or "babble" as it's known, is also discouraged.
- Don't hesitate to post any questions, concerns or comments but make sure
- in each message that you post that you have a reason to post.
-
- So What's Out There?
-
- So why should you be interested in the Internet? Imagine, if you will,
- being able to ask questions to numerous individuals, download the latest
- in shareware and public-domain software, know the "rumours" and topics
- before they exist all for free? (Or at least, only for what your
- "hookup" method charges - see Gaining Access to the InterNet latter).
- That's what's out on the Internet. Any question you have - there is sure
- to be an answer for - any software you're looking for you stand an
- extremely good chance of finding something along the lines of your
- needs.
-
- The major benefit of the Internet as I see it consists of the continued
- support for the Commodore computers. Because all these differant means
- of obtaining information are not sponsored by any one specific company
- or individual the Commodore 8-bit line of computers are guranteed
- continued support over the Internet. In addition, because the Internet
- strongly frowns upon Commercial advertising you won't find numerous ads
- or any other material urging you to "buy this, buy that" like you will
- on some other serv ices.
-
- FTP Sites
-
- FTP stands for File Transfer Protocols and is a method of obtaining
- programs that are stored on another system's computers. There are
- numerous FTP sites out there in InterNet land - one of the best
- currently available for the Commodore computers is that of R.Knop's site
- at ccosun.caltech.edu.
-
- [ The following is a list of FTP sites for the Commodore 64 and 128
- computes and is currenty maintained by Howard Herman
- (h.herman@GEnie.geis.com) and is used with his permission. He usually
- posts an updated list to comp.sys.cbm newsgroup every month or so.]
- -----------------------------------------------------------------------------
- This is the list of FTP sites containing software and programs
- specific to the Commodore 64 and 128 computers.
-
- I will try to keep this list as current and accurate as possible, so
- that it can be a useful resource for users of the newsgroup.
-
- PLEASE cooperate and send E-mail to me with any corrections and
- updates. If a site has closed or no longer carries CBM software, let
- me know and it will be deleted. If you uncover a site not listed,
- tell me so that it can be added.
- -----
-
- To use this list on a UNIX system, just type 'ftp <sitename>', where
- <sitename> is any of the sites listed below. Use 'anonymous' as
- your login, and your E-mail address for the password. You can change
- and list directories with 'cd' and 'dir', respectively, and download
- files to your system using 'get'. Be sure to specify either 'binary'
- if you are getting a program, or 'ascii' for a text file before you
- begin the download.
- -----
-
- In addition to the sites listed below there are hundreds of other
- FTP sites on INet with interesting files covering every topic
- imaginable. Take some time to seek out and explore these too.
-
- Enjoy!
- -----
-
- Host sol.cs.ruu.nl (131.211.80.17)
- Last updated 00:39 4 Sep 1993
- Location: /pub/MIDI/PROGRAMS
- DIRECTORY rwxr-xr-x 1024 Aug 26 09:58 C64
- Location: /pub/MIDI/DOC
- FILE rw-r--r-- 40183 Jan 19 1993 C64midi-interface.txt
-
- Host uceng.uc.edu (129.137.33.1)
- Last updated 04:38 6 Sep 1993
- Location: /pub/wuarchive/systems/cpm/c128
- FILE rw-r--r-- 24576 Nov 6 1986 c128-mex.com
- Location: /pub/wuarchive/systems/cpm/c64
- FILE rw-r--r-- 1615 Mar 14 1984 c64-cpm.msg
- FILE rw-r--r-- 1536 Feb 9 1985 c64modem.com
- FILE rw-r--r-- 4199 Feb 10 1984 c64modem.doc
- FILE rw-r--r-- 19200 Feb 9 1985 md730c64.com
- FILE rw-r--r-- 2192 Oct 1 1984 md730c64.doc
- Location: /pub/wuarchive/doc/misc/if-archive/infocom/tools
- FILE r--r--r-- 5798 Aug 5 14:42 c64todat.tar.Z
-
- Host aix370.rrz.uni-koeln.de (134.95.80.1)
- Location: /.disk2/usenet/comp.archives/auto/comp.sys.cbm
- DIRECTORY rwxrwxr-x 384 comp.sys.cbm
-
- Host ftp.csv.warwick.ac.uk (137.205.192.5)
- Last updated 00:00 18 Jan 1994
- Location: /pub/c64
- FILE rw-r--r-- 909 Jan 8 19:52 C64progs.doc
- FILE rw-r--r-- 19558 Jan 8 19:49 backgamm.sfx
- FILE rw-r--r-- 21384 Jan 8 19:49 chequebo.sfx
- FILE rw-r--r-- 11449 Jan 8 19:49 countdow.sfx
- FILE rw-r--r-- 18136 Jan 8 19:49 draughts.sfx
- FILE rw-r--r-- 5011 Jan 8 19:49 loader.sfx
- FILE rw-r--r-- 17423 Jan 8 19:49 whitewas.sfx
- Descriptions:
- ============
- backgamm - Backgammon board game
- chequebo - Cheque Book Organiser, written in basic with UK pound sign as
- currency, but could be changed to suit another.
- countdow - LOAD"count example",8,1 and watch the countdown during loading.
- draughts - Draughts board game.
- loader - Press RESTORE key and MENU on disk will be automatically re-loaded.
- whitewas - Colour squares board game.
- Location: /tmp/c64
- >Temporary files stored here. If /tmp directory not found, try
- >again at another time. /tmp directory not always available.
-
- Host clover.csv.warwick.ac.uk (137.205.192.6)
- Last updated 13:29 27 Sep 1993
- Location: /pub/c64
- FILE rw-r--r-- 812 c64progs.doc
- FILE rw-r--r-- 73696 c64progs.sfx
-
- Host nexus.yorku.ca (130.63.9.66)
- Last updated 00:00 21 Dec 1993
- Location: /pub/Internet-info
- FILE rw-r--r-- 6308 commodore.ftp
- >An older version of this listing.
-
- Host rigel.acs.oakland.edu (141.210.10.117)
- Last updated 01:42 3 Sep 1993
- Location: /pub2/cpm
- DIRECTORY rwxr-xr-x 1536 Jun 4 1992 c128
- DIRECTORY rwxr-xr-x 512 c64
- Location: /pub2/cpm/c64
- FILE rw-r--r-- 1615 Mar 14 1984 c64-cpm.msg
- FILE rw-r--r-- 1536 Feb 9 1985 c64modem.com
- FILE rw-r--r-- 4199 Feb 10 1984 c64modem.doc
- FILE rw-r--r-- 19200 Feb 9 1985 md730c64.com
- FILE rw-r--r-- 2192 Oct 2 1984 md730c64.doc
-
- Host oak.oakland.edu
- Last updated 00:00 18 Dec 1993
- Location: /pub2/cpm
- >For CP/M software, most all of which will run on the C128.
-
- Host src.doc.ic.ac.uk (146.169.2.1)
- Location: /usenet/comp.archives/auto
- DIRECTORY rwxr-xr-x 512 comp.sys.cbm
- Location: /usenet/comp.archives
- DIRECTORY rwxr-xr-x 512 commodore-64-128
- DIRECTORY rwxr-xr-x 512 May 3 1991 c64
- Location: /media/visual/collections/funet-pics/jpeg/games
- DIRECTORY rwxr-xr-x 512 Mar 20 05:48 c64
- Location: /media/visual/collections/funet-pics/jpeg/comp/games
- DIRECTORY rwxr-xr-x 512 May 6 03:55 c64
-
- Host tupac-amaru.informatik.rwth-aachen.de (137.226.112.31)
- Last updated 04:59 7 Oct 1992
- Location: /pub/rz.archiv/simtel/cpm
- DIRECTORY rwxr-xr-x 512 c64
- DIRECTORY rwxr-xr-x 512 Sep 21 20:56 c128
-
- Host wuarchive.wustl.edu (128.252.135.4)
- Last updated 02:40 23 May 1993
- Location: /systems/amiga/incoming/misc
- FILE rw-rw-r-- 21815 Jan 23 14:26 C64View.lha
- FILE rw-rw-r-- 120 Jan 23 14:26 C64View.readme
- Location: /mirrors/cpm
- DIRECTORY rwxr-xr-x 512 c64
- DIRECTORY rwxr-xr-x 1536 Nov 22 1992 c128
-
- Host watsun.cc.columbia.edu (128.59.39.2)
- Last updated 02:07 8 Sep 1993
- Location: /kermit2/old
- DIRECTORY rwxrwxr-x 1024 Jul 12 18:30 c64
- Location: /kermit/bin
-
- Host cs.columbia.edu (128.59.1.2)
- Last updated 01:29 12 Sep 1993
- Location: /archives/mirror1/kermit
- FILE rw-rw-r-- 15016 Aug 24 1988 c644th.prg.gz
- FILE rw-rw-r-- 733 Sep 29 1992 c64help.txt.gz
- FILE rw-rw-r-- 6095 Sep 29 1992 c64ker1660.sda.gz
- FILE rw-rw-r-- 5904 Sep 29 1992 c64kerfast.sda.gz
- FILE rw-rw-r-- 26484 Sep 29 1992 c64kerv22a.sda.gz
- FILE rw-rw-r-- 42552 Sep 29 1992 c64kerv22b.sda.gz
- FILE rw-rw-r-- 31982 Sep 29 1992 c64slkv22s.sda.gz
-
- Host plaza.aarnet.edu.au (139.130.4.6)
- Last updated 00:00 28 Dec 1993
- Location: /pub/kermit/c
- FILE r--r--r-- 3073 Aug 16 1988 c64boot.bas
- FILE r--r--r-- 1547 Aug 16 1988 c64boot.c
- FILE r--r--r-- 1151 Aug 16 1988 c64boot.clu
- FILE r--r--r-- 3002 Aug 16 1988 c64boot.for
- FILE r--r--r-- 3315 Aug 16 1988 c64boot.sim
- >There are more Kermit files which are not listed. Be sure to
- >get the complete set of C64/128 Kermit files.
-
- Host flubber.cs.umd.edu (128.8.128.99)
- Last updated 00:00 03 Jan 1994
- Location: /rec/newballistic
- FILE rw-r--r-- 8576 Mar 23 21:21 balistic.c64
- --------------------------------
-
- Host f.ms.uky.edu (128.163.128.6)
- Last updated 00:00 28 Dec 1993
- Location: /archive/c64.zip
-
- Host ftp.funet.fi (128.214.6.100)
- Last updated 06:11 22 Mar 1993
- Location: /pub/pics/jpeg/games
- DIRECTORY rwxrwxr-x 512 Mar 20 02:07 c64
- Location: /pub/misc
- DIRECTORY rwxrwxr-x 512 Mar 13 23:30 c64
- Location: /pub/kermit
- DIRECTORY rwxrwxr-x 1024 Jan 13 1992 c64
- Location: /pub/amiga/audio/misc/sid-tunes
- FILE rw-rw-r-- 671490 Jun 18 1992 C64MusicShow-1.lha
- FILE rw-rw-r-- 316521 Jun 18 1992 C64MusicShow-2.lha
- /pub/cbm
-
- Host nic.switch.ch (130.59.1.40)
- Last updated 00:39 31 Aug 1993
- Location: /mirror/kermit/bin
-
- Host gmdzi.gmd.de (129.26.8.90)
- Last updated 01:08 1 Aug 1993
- Location: /if-archive/infocom/tools
- FILE rw-rw-r-- 5668 Apr 27 15:00 c64.to.dat
-
- Host micros.hensa.ac.uk (148.88.8.84)
- Location /kermit
- DIRECTORY rwxr-x--- 1024 Nov 11 09:20 c64
-
- Host wilbur.stanford.edu (36.14.0.36)
- Location /pub/emulators
- DIRECTORY rwxr-xr-x 512 Jun 30 00:57 c64
-
- Host syrinx.umd.edu (128.8.2.114)
- Last updated 00:00 28 Dec 1993
- Location: /rush/c64-sounds
-
- Host tolsun.oulu.fi (130.231.96.16)
- Last updated 01:53 6 Sep 1993
- Location: /pub
- DIRECTORY rwxr-xr-x 1024 Jul 15 1990 c64
- Location: /incoming
- DIRECTORY --------- 1024 Jun 20 1992 c64
- /pub/amiga/4/c64trans.zoo
- /pub/c64
- >Uploading to /pub/c64 is disabled because of lack of disk space.
- >However, for downloading it is still fully accessible.
- >Currently there is no administration for /pub/c64.
- >/pub/amiga is active, though.
-
- Host ccosun.caltech.edu (131.215.139.2)
- Last updated 00:00 31 JAN 1994
- Location: /pub/rknop
- Location: /pub/rknop/misc
- > 64/128 programs can be found within directories according to
- > function. When searching, be sure to check related directories.
-
- Host ucsd.edu (128.54.16.1)
- Last updated 04:46 6 Sep 1993
- Location: /midi/software
- DIRECTORY rwxr-xr-x 512 Jan 27 1992 c64
-
- Host cs.dal.ca (129.173.4.5)
- Last updated 01:36 12 Sep 1993
- Location: /comp.archives
- DIRECTORY rwxrwxr-x 3584 Apr 7 04:05 c64
- pub/comp.archives/comp.sys.cbm
-
- Host ccnga.uwaterloo.ca
- Last updated 00:00 01 Jan 1994
- Location: /pub/cbm/vbm110.uua
- > For VBM Bitmap Viewer version 1.10
-
- Host bert.psyc.upei.ca
- Last updated 00:00 31 Jan 1994
- Location: /pub
- > All the releases of the major demo parties of '93
-
- --------------------------------
- Send all info regarding changes/additions/corrections [to the FTP list] to:
-
- 72560.3467@CompuServe.COM or: h.herman1@GEnie.geis.COM
- =============================================================================
- Hiding kilobytes
- by Marko M"akel"a <Marko.Makela@Helsinki.FI>
-
- Most Commodore 64 programs do not utilize even nearly all of the 64 kB
- random access memory space. By default, there are only 44 kilobytes of
- accessible RAM. This article describes how you can take the hiding 20
- kilobytes to use.
-
-
- _Memory management_
-
- The Commodore 64 has access to more memory than its processor can
- directly handle. This is possible by banking the memory. There are
- five user configurable inputs that affect the banking. Three of them
- can be controlled by program, and the rest two serve as control lines
- on the memory expansion port.
-
- The 6510 MPU has an integrated I/O port with six I/O lines. This
- port is accessed through the memory locations 0 and 1. The location 0
- is the Data Direction Register for the Peripheral data Register, which
- is mapped to the other location. When a bit in the DDR is set, the
- corresponding PR bit controls the state of a corresponding Peripheral
- line as an output. When it is clear, the state of the Peripheral line
- is reflected by the Peripheral register. The Peripheral lines are
- numbered from 0 to 5, and they are mapped to the DDR and PR bits 0 - 5,
- respectively. The 8502 processor, which is used in the Commodore 128,
- has seven Peripheral lines in its I/O port. The seventh line is connected
- to the Caps lock or ASC/CC key.
-
- The I/O lines have the following functions:
-
- Direction Line Function
- --------- ---- --------
- out P5 Cassette motor control. (0 = motor spins)
- in P4 Cassette sense. (0 = PLAY button depressed)
- out P3 Cassette write data.
- out P2 CHAREN
- out P1 HIRAM
- out P0 LORAM
-
- The default value of the DDR register is $2F, so all lines except
- Cassette sense are outputs. The default PR value is $37 (Datassette
- motor stopped, and all three memory management lines high).
-
- Like most chips in the Commodore 64, the 6510 MPU uses the NMOS
- (N-channel metal oxide semiconductor) technology. The NMOS switches
- produce strong logical '0' levels, but weak '1' levels. The opposite
- is the PMOS (P-channel metal oxide semiconductor) technology, which
- cannot pull strong signals low, but is able to drive them high. The CMOS
- technology (complementary metal oxide semiconductor), which combines
- these two technologies, is able to drive both logical levels.
-
- Because most integrated circuits in the C64 use the NMOS technology,
- all hardware lines that are not outputs are driven to +5 volts with a
- weak current. This is usually accomplished by pull-up resistors, large
- resistances between the hardware lines and the +5 volt power supply
- line. The resistors can be inside a chip or on the printed circuit
- board. This allows any NMOS or CMOS chip to drive the line to the
- desired state (low or high voltage level).
-
- The difference between an input and an output is that an output uses
- more current to drive the signal to the desired level. An input and an
- output outputting logical '1' are equivalent for any other inputting
- chip. But if a chip is trying to drive a signal to ground level, it
- needs more current to sink an output than an input. You can even use
- outputs as inputs, i.e. read them in your program.
-
- You can use this feature to distinquish between the left
- shift and the shift lock keys, although they are connected
- to same hardware lines. The shift lock key has smaller
- resistance than the left shift. If you make both CIA 1
- ports to outputs (write $FF to $DC03 and $DC01) prior
- reading the left shift key, only shift lock can change the
- values you read from CIA 1 port B ($DC01).)
-
- So, if you turn any memory management line to input, the external
- pull-up resistors will make it look like it is outputting logical
- '1'. This is actually why the computer always switches the ROMs in
- upon startup: Pulling the -RESET line low resets all Peripheral lines
- to inputs, thus driving all three processor-driven memory management
- lines high.
-
- The two remaining memory management lines are -EXROM and -GAME on
- the cartridge port. Each line has a pull-up resistor, so the lines are
- '1' by default. (In the Commodore 128, you can set the state of these
- two lines prior to selecting the C64 mode, provided that you write the
- mode switch routine yourself.)
-
- Even though the memory banking has been implemented with a 82S100
- Programmable _Logic_ Array, there is only one control line that seems
- to behave logically at first sight, the -CHAREN line. It is mostly
- used to choose between I/O address space and the character generator
- ROM. The following memory map introduces the oddities of -CHAREN and
- the other memory management lines. It is based on the memory maps in
- the Commodore 64 Programmer's Reference Guide, pp. 263 - 267, and some
- errors and inaccuracies have been corrected.
-
- The leftmost column of the table contains addresses in hexadecimal
- notation. The columns aside it introduce all possible memory
- configurations. The default mode is on the left, and the absolutely
- most rarely used Ultimax game console configuration is on the right.
- (There have been at least two Ultimax cartridges on the market.) Each
- memory configuration column has one or more four-digit binary numbers
- as a title. The bits, from left to right, represent the state of the
- -LORAM, -HIRAM, -GAME and -EXROM lines, respectively. The bits whose
- state does not matter are marked with "x". For instance, when the
- Ultimax video game configuration is active (the -GAME line is shorted
- to ground, -EXROM kept high), the -LORAM and -HIRAM lines have no effect.
-
-
- default Ultimax
- 1111 101x 1000 011x 001x 1110 0100 1100 xx01
- 00x0
- 10000
- -----------------------------------------------------------------------------
- F000
- Kernal RAM RAM Kernal RAM Kernal Kernal Kernal ROMH(*
- E000
- -----------------------------------------------------------------------------
- D000 IO/C IO/C IO/RAM IO/C RAM IO/C IO/C IO/C I/O
- -----------------------------------------------------------------------------
- C000 RAM RAM RAM RAM RAM RAM RAM RAM -
- -----------------------------------------------------------------------------
- B000
- BASIC RAM RAM RAM RAM BASIC ROMH ROMH -
- A000
- -----------------------------------------------------------------------------
- 9000
- RAM RAM RAM RAM RAM ROML RAM ROML ROML(*
- 8000
- -----------------------------------------------------------------------------
- 7000
-
- 6000
- RAM RAM RAM RAM RAM RAM RAM RAM -
- 5000
-
- 4000
- -----------------------------------------------------------------------------
- 3000
-
- 2000 RAM RAM RAM RAM RAM RAM RAM RAM -
-
- 1000
- -----------------------------------------------------------------------------
- 0000 RAM RAM RAM RAM RAM RAM RAM RAM RAM
- -----------------------------------------------------------------------------
-
- *) Internal memory does not respond to write accesses to these areas.
-
-
- Legend: Kernal E000-FFFF Kernal ROM.
-
- IO/C D000-DFFF I/O address space or Character
- generator ROM, selected by -CHAREN.
- If the CHAREN bit is clear,
- the character generator ROM is
- chosen. If it is set, the
- I/O chips are accessible.
-
- IO/RAM D000-DFFF I/O address space or RAM,
- selected by -CHAREN.
- If the CHAREN bit is clear,
- the character generator ROM is
- chosen. If it is set, the
- internal RAM is accessible.
-
- I/O D000-DFFF I/O address space.
- The -CHAREN line has no effect.
-
- BASIC A000-BFFF BASIC ROM.
-
- ROMH A000-BFFF or External ROM with the -ROMH line
- E000-FFFF connected to its -CS line.
-
- ROML 8000-9FFF External ROM with the -ROML line
- connected to its -CS line.
-
- RAM various ranges Commodore 64's internal RAM.
-
- - 1000-7FFF and Open address space.
- A000-CFFF The Commodore 64's memory chips
- do not detect any memory accesses
- to this area except the VIC-II's
- DMA and memory refreshes.
-
- NOTE: Whenever the processor tries to write to any ROM area
- (Kernal, BASIC, CHAROM, ROML, ROMH), the data will get
- "through the ROM" to the C64's internal RAM.
-
- For this reason, you can easily copy data from ROM to RAM,
- without any bank switching. But implementing external
- memory expansions without DMA is very hard, as you have to
- use the Ultimax memory configuration, or the data will be
- written both to internal and external RAM.
-
- However, this is not true for the Ultimax game
- configuration. In that mode, the internal RAM ignores all
- memory accesses outside the area $0000-$0FFF, unless they are
- performed by the VIC, and you can write to external memory
- at $1000-$CFFF and $E000-$FFFF, if any, without changing
- the contents of the internal RAM.
-
-
- _A note concerning the I/O area_
-
- The I/O area is divided as follows:
-
- Address range Owner
- ------------- -----
- D000-D3FF MOS 6567/6569 VIC-II Video Interface Controller
- D400-D7FF MOS 6581 SID Sound Interface Device
- D800-DBFF Color RAM (only lower nybbles are connected)
- DC00-DCFF MOS 6526 CIA Complex Interface Adapter #1
- DD00-DDFF MOS 6526 CIA Complex Interface Adapter #2
- DE00-DEFF User expansion #1 (-I/O1 on Expansion Port)
- DF00-DFFF User expansion #2 (-I/O2 on Expansion Port)
-
- As you can see, the address ranges for the chips are much larger
- than required. Because of this, you can access the chips through
- multiple memory areas. The VIC-II appears in its window every $40
- addresses. For instance, the addresses $D040 and $D080 are both mapped
- to the Sprite 0 X co-ordinate register. The SID has one register
- selection line less, thus it appears at every $20 bytes. The CIA
- chips have only 16 registers, so there are 16 copies of each in their
- memory area.
-
- However, you should not use other addresses than those specified by
- Commodore. For instance, the Commodore 128 mapped its additional I/O
- chips to this same memory area, and the SID responds only to the
- addresses D400-D4FF, also when in C64 mode. And the Commodore 65,
- which unfortunately did not make its way to the market, could narrow
- the memory window reserved for the MOS 6569/6567 VIC-II (or CSG 4567
- VIC-III in that machine).
-
-
- _The video chip_
-
- The MOS 6567/6569 VIC-II Video Interface Controller has access to
- only 16 kilobytes at a time. To enable the VIC-II to access the whole
- 64 kB memory space, the main memory is divided to four banks of 16 kB
- each. The lines PA0 and PA1 of the second CIA are the inverse of the
- virtual VIC-II address lines VA14 and VA15, respectively. To select a
- VIC-II bank other than the default, you must program the CIA lines to
- output the desired bit pair. For instance, the following code selects
- the memory area $4000-$7FFF (bank 1) for the video controller:
-
- LDA $DD02 ; Data Direction Register A
- ORA #$03 ; Set pins PA0 and PA1 to outputs
- STA $DD02
- LDA $DD00
- AND #$FC ; Mask the lowmost bit pair off
- ORA #$02 ; Select VIC-II bank 1 (the inverse of binary 01 is 10)
- STA $DD00
-
- Why should you set the pins to outputs? Hardware RESET resets all
- I/O lines to inputs, and thanks to the CIA's internal pull-up
- resistors, the inputs actually output logical high voltage level. So,
- upon -RESET, the video bank 0 is selected automatically, and older
- Kernals could leave it uninitialized.
-
- Note that the VIC-II always fetches its information from the
- internal RAM, totally ignoring the memory configuration lines. There
- is only one exception to this rule: The character generator ROM.
- Unless the Ultimax mode is selected, VIC-II "sees" character generator
- ROM in the memory areas 1000-1FFF and 9000-9FFF. If the Ultimax
- configuration is active, the VIC-II will fetch all data from the
- internal RAM.
-
-
- _An application: Making an operating system extension_
-
- If you are making a memory resident program and want to make it as
- invisible to the system as possible, probably the best method is
- keeping most of your code under the I/O area (in the RAM at
- $D000-$DFFF). This area is very safe, since programs utilizing it are
- rare, since they are very difficult to implement and to debug. You
- need only a short routine in the normally visible RAM that pushes the
- current value of the processor's I/O register $01 on stack, switches
- RAM on to $D000-$DFFF and jumps to this area. Returning from the
- $D000-$DFFF area is possible even without any routine in the normally
- visible RAM area. Just write an RTS or an RTI to an I/O register and
- return through it.
-
- But what if your program needs to use I/O? And how can you write the
- return instruction to an I/O register while the I/O area is switched
- off? You need a swap area for your program in normally visible memory.
- The first thing your routine at $D000-$DFFF does is copying the I/O
- routines (or the whole program) to normally visible memory, swapping
- the bytes. For instance, if your I/O routines are initially being
- stored at $D200-$D3FF, exchange the bytes in $D200-$D3FF with the
- contents of $C000-$C1FF. Now you can call the I/O routines from your
- routine at $D000-$DFFF, and the I/O routines can switch the I/O area
- temporarily on to access the I/O chips. And right before exiting your
- program at $D000-$DFFF swaps the old contents of that I/O routine area
- in, e.g. exchanges the memory areas $D200-$D3FF and $C000-$C1FF
- again.
-
- What I/O registers can you use for the return instruction? There are
- basically two alternatives: 8-bit VIC sprite registers or either CIA's
- serial port register. The VIC registers are easiest to use, as they
- act precisely like memory places: you can easily write the desired
- value to a register. But the CIA register is usually better, as
- changing the VIC registers might change the screen layout.
-
- However, also the SP register has some drawbacks: If the machine's
- CNT1 and CNT2 lines are connected to a frequency source, you must stop
- either CIA's Timer A to use the SP register method. Normally the 1st
- CIA's Timer A is the main hardware interrupt source. And if you use
- the Kernal's RS232, you cannot stop the 2nd CIA's Timer A either. Also,
- if you don't want to lose any CIA interrupts, you might want to know
- that executing the RTS or RTI at SP register has the side effect of
- reading the Interrupt Control Register, thus acknowledging an interrupt
- that might have been waiting.
-
- If you can't use either method, you can use either CIA's ToD seconds
- or minutes or ToD alarm time for storing an RTI. Or, if you don't want
- to alter any registers, use the VIC-II's light pen register. Before
- exiting, wait for appropriate raster line and trig the light pen latch
- with CIA1's PB4 bit. However, this method assumes that the control
- port 1's button/light pen line remains up for that frame. After
- trigging the light pen, causing the light pen Y co-ordinate register
- ($D014) to be $40 or $60, you have more than half a frame time to
- restore the state of the I/O chips and return through the register.
-
- You can also use the SID to store an RTI or RTS command. How is this
- possible, you might ask. After all, the chip consists of read only or
- write only registers. However, there are two registers that can be
- controlled by program, the envelope generator and oscillator outputs
- of the third voice. This method requires you to change the frequency
- of voice 3 and to select a waveform for it. This will affect on the
- voice output by turning the voice 3 off, but who would keep the voice
- 3 producing a tone while calling an operating system routine?
-
- Also keep in mind that the user could press RESTORE while the Kernal
- ROM and I/O areas are disabled. You could write your own non-maskable
- interrupt (NMI) handler (using the NMI vector at $FFFA), but a fast
- loader that uses very tight timing would still stop working if the
- user pressed RESTORE in the middle of a data block transfer. So, to
- make a robust program, you have to disable NMI interrupts. But how is
- this possible? They are Non-Maskable after all. The NMI interrupt is
- edge-sensitive, the processor jumps to NMI handler only when the -NMI
- line drops from +5V to ground. To disable the interrupt, simply cause
- an NMI with CIA2's timer, but don't read the Interrupt Control
- register. If you need to read $DD0D in your program, you must add a
- NMI handler just in case the user presses RESTORE. And don't forget to
- raise the -NMI line upon exiting the program. Otherwise the RESTORE
- key does not work until the user issues a -RESET or reads the ICR
- register explicitly. (The Kernal does not read $DD0D, unless it is
- handling an interrupt.) This can be done automatically by the two
- following SP register examples due to one of the 6510's undocumented
- features (refer to the descriptions of RTS and RTI below).
-
- ; Returning via VIC sprite 7 X co-ordinate register
-
- Initialization: ; This is executed when I/O is switched on
- LDA #$60
- STA $D015 ; Write RTS to VIC register $15.
-
- Exiting: ; NOTE: This procedure must start at VIC register
- ; $12. You have multiple alternatives, as the VIC
- ; appears in memory at $D000+$40*n, where $0<=n<=$F.
-
- PLA ; Pull the saved 6510 I/O register state from stack
- STA $01 ; Restore original memory bank configuration
- ; Now the processor fetches the RTS command from the
- ; VIC register $15.
-
-
- ; Returning via CIA 2's ToD or ToD alarm seconds register
-
- Initialization: ; This is executed when I/O is switched on
- LDA #$40
- STA $DD08 ; Set ToD tenths of seconds
- ; (clear it so that the seconds register
- ; would not overflow)
- ; If ToD alarm register is selected, this
- ; instruction will be unnecessary.
- STA $DD09 ; Set ToD seconds
- LDA $DD0B ; Read ToD hours (freeze ToD display)
-
- Exiting: ; NOTE: This procedure must start at CIA 2 register
- ; $6. As the CIA 2 appears in memory at $DD00+$10*n,
- ; where 0<=n<=$F, you have sixteen alternatives.
- PLA
- STA $01 ; Restore original memory bank configuration
- ; Now the processor fetches the RTS command from
- ; the CIA 2 register $9.
-
-
- ; Returning via CIA 2's SP register (assuming that CNT2 is stable)
-
- Initialization: ; This is executed when I/O is switched on
- LDA $DD0E ; CIA 2's Control Register A
- AND #$BF ; Set Serial Port to input
- STA $DD0E ; (make the SP register to act as a memory place)
- LDA #$60
- STA $DD0C ; Write RTS to CIA 2 register $C.
-
- Exiting: ; NOTE: This procedure must start at CIA 2 register
- ; $9. As the CIA 2 appears in memory at $DD00+$10*n,
- ; where 0<=n<=$F, you have sixteen alternatives.
- PLA
- STA $01 ; Restore original memory bank configuration
- ; Now the processor fetches the RTS command from
- ; the CIA 2 register $C.
-
-
- ; Returning via CIA 2's SP register, stopping the Timer A
- ; and forcing SP2 and CNT2 to output
-
- Initialization: ; This is executed when I/O is switched on
- LDA $DD0E ; CIA 2's Control Register A
- AND #$FE ; Stop Timer A
- ORA #$40 ; Set Serial Port to output
- STA $DD0E ; (make the SP register to act as a memory place)
- LDA #$60
- STA $DD0C ; Write RTS to CIA register $C.
-
- Exiting: ; NOTE: This procedure must start at CIA 2 register
- ; $9. As the CIA 2 appears in memory at $DD00+$10*n,
- ; where 0<=n<=$F, you have sixteen alternatives.
- PLA
- STA $01 ; Restore original memory bank configuration
- ; Now the processor fetches the RTS command from
- ; the CIA 2 register $C.
-
- ; Returning via SID oscillator 3 output register
-
- Initialization: ; This is executed when I/O is switched on
- LDA #$20 ; Select sawtooth waveform
- STA $D412 ; but do not enable the sound
- LDY #$00 ; Select frequency
- STY $D40E ; (system clock)/$FF00,
- LDA #$FF ; causing the OSC3 output to increment by one
- STY $D40F ; every $10000/$FF00 cycles.
-
- LDA #$0E
- LDX #$60
-
- BIT $D41B ; Wait for the oscillator 3 output
- BMI *-3 ; to be in the range
- BVS *-5 ; $00-$3F.
- BIT $D41B ; Wait for the oscillator 3 output
- BVC *-3 ; to be at least $40.
-
- STA $D40F ; Slow down the frequency to (system clock)/$0E00.
- CPX $D41B ; Wait for the oscillator 3
- BNE *-3 ; output to reach $60 (RTS)
-
- STY $D40F ; Reset the frequency of voice 3
- ; (stop the OSC3 register from increasing)
-
- Exiting: ; NOTE: This procedure must start at SID register
- ; $18. As the SID appears in memory at $D400+$20*n,
- ; where 0<=n<=$20, you have thirty-two alternatives.
- ; However, in C128 there are only eight alternatives,
- ; as the SID is only at $D400-$D4FF.
-
- PLA
- STA $01 ; Restore original memory bank configuration
- ; Now the processor fetches the RTS command from
- ; the SID register $1B.
-
-
- For instance, if you want to make a highly compatible fast loader,
- make the ILOAD vector ($0330) point to the beginning of the stack
- area. Remember that the BASIC interpreter uses the first bytes of
- stack while converting numbers to text. A good address is $0120.
- Robust programs practically never use so much stack that it could
- corrupt this routine. Usually only crunched programs (demos and alike)
- use all stack in the decompression phase. They also make use of the
- $D000-$DFFF area.
-
- This stack routine will jump to your routine at $D000-$DFFF, as
- described above. For performance's sake, copy the whole byte transfer
- loop to the swap area, e.g. $C000-$C1FF, and call that subroutine
- after doing the preliminary work. But what about files that load over
- $C000-$C1FF? Wouldn't that destroy the transfer loop and jam the
- machine? Not necessarily. If you copy those bytes to your swap area at
- $D000-$DFFF, they will be loaded properly, as your program restores
- the original $C000-$C1FF area.
-
- If you want to make your program user-friendly, put a vector
- initialization routine to the stack area as well, so that the user can
- restore the fast loader by issuing a SYS command, rather than loading
- it each time he has pressed RESET.
-
-
- _An example: A "hello world" program_
-
- To help you in getting started, I have written a small example
- program that echoes the famous message "hello, world!" to standard
- output (normally screen) using the Kernal's CHROUT subroutine. After
- the initialization routine has been run, the program can be started by
- commanding SYS 300. I used the Commodore 128's machine language
- monitor to put it up, but it was still pretty difficult to debug the
- program. Here it is in uuencoded format:
-
- begin 644 hello
- M`0@+",D'GC(P-C$```!XI0%(*?B%`:(,O3`(G2P!RA#WHHN]/`B=8]W*T/=H
- MA0%88*4!JBGX"01XA0%,I-WF`:*!C@W=H@".!=WHC@3=HMV.#MVB0(X,W<8!
- M8*4!2`D#A0&@#+DSP"#2_X@0]VB%`6`A1$Q23U<@+$],3$5(BDBM^O](K?O_
- M2*D6C?K_J<"-^_\@W-T@`,!HC?O_:(WZ_R`=P"#<W6BHJ0!(NOX"`=`#_@,!
- 5A`&@/[X`P+EDW9D`P(J99-V($/!@
- `
- end
-
- In order to fully understand the operation of this program, you need
- to know how the instructions RTI, RTS and PHA work. There is some work
- going on to reverse engineer the NMOS 6502 microprocessor to large
- extent, and it is now known for most instructions what memory places
- they access during their execution and for what purpose. The internal
- procedures haven't been described in detail yet, but these
- descriptions should be easier to read anyway.
-
- For curiosity, I quote here the description of all instructions that
- use the stack. The descriptions of internal operations are yet
- inaccurate, but the memory accesses have been verified with an
- oscilloscope. I will mail copies the whole document upon request. When
- finished, the document will be put on an FTP site.
-
-
- JSR
-
- # address R/W description
- --- ------- --- -------------------------------------------------
- 1 PC R fetch opcode, increment PC
- 2 PC R fetch address's low byte to latch, increment PC
- 3 $0100,S R
- 4 $0100,S W push PCH on stack, decrement S
- 5 $0100,S W push PCL on stack, decrement S
- 6 PC R copy latch to PCL, fetch address's high byte to
- latch, copy latch to PCH
-
-
- RTS
-
- # address R/W description
- --- ------- --- -----------------------------------------------
- 1 PC R fetch opcode, increment PC
- 2 PC R read next instruction byte (and throw it away),
- increment PC
- 3 $0100,S R increment S
- 4 $0100,S R pull PCL from stack, increment S
- 5 $0100,S R pull PCH from stack
- 6 PC R increment PC
-
-
- BRK
-
- # address R/W description
- --- ------- --- -----------------------------------------------
- 1 PC R fetch opcode, increment PC
- 2 PC R read next instruction byte (and throw it away),
- increment PC
- 3 $0100,S W push PCH on stack, decrement S
- 4 $0100,S W push PCL on stack, decrement S
- 5 $0100,S W push P on stack (with B flag set), decrement S,
- set I flag
- 6 $FFFE R fetch PCL
- 7 $FFFF R fetch PCH
-
-
- RTI
-
- # address R/W description
- --- ------- --- -----------------------------------------------
- 1 PC R fetch opcode, increment PC
- 2 PC R read next instruction byte (and throw it away),
- increment PC
- 3 $0100,S R increment S
- 4 $0100,S R pull P from stack, increment S
- 5 $0100,S R pull PCL from stack, increment S
- 6 $0100,S R pull PCH from stack
-
-
- PHA, PHP
-
- # address R/W description
- --- ------- --- -----------------------------------------------
- 1 PC R fetch opcode, increment PC
- 2 PC R read next instruction byte (and throw it away),
- increment PC
- 3 $0100,S W push register on stack, decrement S
-
-
- PLA, PLP
-
- # address R/W description
- --- ------- --- -----------------------------------------------
- 1 PC R fetch opcode, increment PC
- 2 PC R read next instruction byte (and throw it away),
- increment PC
- 3 $0100,S R increment S
- 4 $0100,S R pull register from stack
-
-
- The example program consists of three parts. The first part
- transfers the other parts to appropriate memory areas. The second part
- is located in stack area (300-312), and it invokes the third part, the
- main module.
-
- The loader part ($0801-$08C7) is as follows:
-
- 1993 SYS2061
-
- 080D SEI Disable interrupts.
- 080E LDA $01
- 0810 PHA Store the state of the processor's I/O lines.
- 0811 AND #$F8
- 0813 STA $01 Select 64 kB RAM memory configuration.
-
- 0815 LDX #$0C Copy the invoking part to 300-312.
- 0817 LDA $0830,X
- 081A STA $012C,X
- 081D DEX
- 081E BPL $0817
-
- 0820 LDX #$8B Copy the main part to $DD64-$DDEE.
- 0822 LDA $083C,X
- 0825 STA $DD63,X
- 0828 DEX
- 0829 BNE $0822
-
- 082B PLA Restore original memory configuration.
- 082C STA $01
- 082E CLI Enable interrupts.
- 082F RTS Return.
-
- The user invokes the following part by issuing SYS 300. This part
- changes the memory configuration and jumps to the main part.
-
- 012C LDA $01
- 012E TAX Store original memory configuration to X register.
- 012F AND #$F8
- 0131 ORA #$04
- 0133 SEI Disable interrupts.
- 0134 STA $01 Select 64 kB RAM memory configuration.
- 0136 JMP $DDA4 Jump to the main part.
-
- The main part actually consists of two parts. It may be a bit
- complicated, and it might teach new tricks to you.
-
- DDA4 TXA
- DDA5 PHA Push original memory configuration on stack.
- DDA6 LDA $FFFA
- DDA9 PHA
- DDAA LDA $FFFB
- DDAD PHA Store the original values of $FFFA and $FFFB.
- DDAE LDA #$16
- DDB0 STA $FFFA Set ($FFFA) to point to RTI.
- DDB3 LDA #$C0
- DDB5 STA $FFFB
- DDB8 JSR $DDDC Swap the auxiliary routines in.
- DDBB JSR $C000 Disable NMI's and initialize CIA2.
- DDBE PLA
- DDBF STA $FFFB Restore original values to $FFFA and $FFFB.
- DDC2 PLA
- DDC3 STA $FFFA
- DDC6 JSR $C01D Print the message.
- DDC9 JSR $DDDC Swap the auxiliary routines out.
- DDCC PLA
- DDCD TAY Load original memory configuration to Y register.
- DDCE LDA #$00 Push desired stack register value on stack
- DDD0 PHA (clear all flags, especially the I flag).
- DDD1 TSX
- DDD2 INC $0102,X Increment the return address.
- DDD5 BNE $DDDA (RTS preincrements it, but RTI does not.)
- DDD7 INC $0103,X
- DDDA STY $01 Restore original memory configuration.
-
- (The 6510 fetches the next instruction from $DDDC, which is now
- connected to the CIA2's register $C, the Serial Port register.
- The initialization routine wrote an RTI to it. The processor also
- reads from $DDDD as a side effect of the instruction fetch,
- thus re-enabling NMI's.)
-
- DDDC LDY #$3F Subroutine: Swap the memory areas $C000-$C03F
- DDDE LDX $C000,Y and $DD64-$DDA3 with each other.
- DDE1 LDA $DD64,Y
- DDE4 STA $C000,Y
- DDE7 TXA
- DDE8 STA $DD64,Y
- DDEB DEY
- DDEC BPL $DDDE
- DDEE RTS
-
- C000 INC $01 Enable the I/O area.
- C002 LDX #$81
- C004 STX $DD0D Enable Timer A interrupts of CIA2.
- C007 LDX #$00
- C009 STX $DD05
- C00C INX
- C00D STX $DD04 Prepare Timer A to count from 1 to 0.
- C010 LDX #$DD
- C012 STX $DD0E Cause an interrupt.
-
- (The instruction sets SP to output, makes Timer A to count
- system clock pulses, forces the CIA to load the initial value
- to the counter, selects one-shot counting and starts the timer.)
-
- C015 LDX #$40
-
- (The processor now jumps to the NMI handler ($C016), and
- the SP register starts to act as a memory place.)
-
- C017 STX $DD0C Write an RTI to Serial Port register.
- C01A DEC $01 Disable the I/O area.
- C01C RTS Return.
-
- C01D LDA $01
- C01F PHA
- C020 ORA #$03 Enable I/O and ROMs.
- C022 STA $01
- C024 LDY #$0C Print the message.
- C026 LDA $C033,Y
- C029 JSR $FFD2
- C02C DEY
- C02D BPL $C026
- C02F PLA
- C030 STA $01 Restore the 64 kB memory configuration.
- C032 RTS
-
- C033 "!DLROW ,OLLEH"
-
- (The string is backwards in memory, since I don't want to
- waste cycles in explicit comparisons. This method results in
- more readable code than doing a forward loop with an index
- value $100-(number of characters).)
-
- This program is not excellent. It has the following bugs:
-
- o The 6510's memory management lines P0 and P1 (LORAM and HIRAM,
- respectively) are assumed to be outputs. If you issued the
- command POKE0,PEEK(0)AND252, this program would not work.
- This could be easily corrected by setting the P0 and P1 lines
- to output in the beginning of the interfacing routine (300 - 312):
-
- LDA $00
- ORA #$02
- STA $00
-
- o The program does not restore the original state of the CIA2
- Control Register A or Interrupt Control Register. It might be
- impossible to start using the Kernal's RS-232 routines after
- running this.
-
- o If the user redirected output to cassette or RS-232, interrupts
- would be required. However, they are completely disabled.
-
- o If a non-maskable interrupt occurs while the loader part is being
- executed, the program will screw up. This will happen also in the
- main part, if an NMI is issued after disabling ROMs and I/O in
- $0134 but before exchanging the contents of the memory places
- $C016 and $DD7A.
-
-
- _Freezer cartridges_
-
- There are many cartridges that let you to stop almost any program for
- "back-up" purposes. One of the most popular of these freezer
- cartridges is the Action Replay VI made by Datel Electronics back in
- 1989. The cartridge has 8 kilobytes RAM and 32 kilobytes ROM on board,
- and it has a custom chip for fiddling with the C64 cartridge port
- lines -EXROM, -GAME, -IRQ, -NMI and BA.
-
- If the -NMI line is not asserted (the NMI interrupts are enabled), all
- freezer cartridges should be able to halt any program. When the user
- presses the "freeze" button, the cartridges halt the processor by
- dropping the BA line low. Then they switch some of their own ROM to
- the $E000 - $FFFF block by selecting the UltiMax configuration with
- the -EXROM and -GAME lines. After this, they assert the -NMI line and
- release the BA line. After completing the current instruction, the
- processor will take the NMI interrupt and load the program counter
- from the vector at $FFFA, provided that the NMI line was not asserted
- already.
-
- This approach is prone to many flaws. Firstly, if the processor is
- executing a write instruction when the program is being halted, and if
- the write occurred outside the area $0000 - $0FFF, the data would get
- lost, if the UltiMax configuration was asserted too early. This can be
- corrected to some extent by waiting at least two cycles after
- asserting the BA line, as the processor will not stop during write
- cycles. However, this is of no help if the processor has not gotten to
- the write stage yet.
-
- Secondly, if the instruction being executed is outside the area
- $0000 - $0FFF, or if it accesses any data outside that area, the
- processor will fetch either wrong parameters or incorrect data, or
- both. If the instruction does not write anything, will only corrupt
- one processor register.
-
- Thirdly, if the NMI interrupts are disabled, pressing the "freeze"
- button does not have any other immediate effect than leaving the
- UltiMax mode asserted, which makes any system RAM outside the area
- $0000 - $0FFF unavailable. It also forces the I/O area ($D000 - $DFFF)
- on. If the program has any instructions or data outside the lowmost
- four kilobytes, it will eventually jam, as that data will be something
- else than the program expects.
-
- One might except that reading from open address space should return
- random bytes. But, in at least two C64's, the bytes read are mostly
- $BD, which is the opcode for LDA absolute,X. So, if the processor has
- a "good luck", it will happily execute only LDA $BDBD,X commands, and
- it might survive to the cartridge ROM area without jamming. Or it
- could eventually fetch a BRK and jump to the cartridge ROM via the
- IRQ/BRK vector at $FFFE. The Action Replay VI has the familiar
- autostart data in the beginning of both the ROML and ROMH blocks by
- default, and that data could be interpreted as sensible commands. The
- Action Replay VI was indeed able to freeze my test program, even
- though I had covered its -RESET, -IRQ and -NMI lines with a piece of
- tape, until I relocated the program to the first 4 kilobyte block.
-
-
- _Building an unbeatable freezer circuit_
-
- As you can see, it is totally impossible to design a freezer cartridge
- that freezes any program. If the program to be freezed has disabled
- the NMI interrupts, and if its code runs mostly at $0000 - $0FFF or
- $D000 - $DFFF, the computer will more probably hang than succeed in
- freezing the program.
-
- However, it is possible to make some internal modifications to a C64,
- so that it can freeze literally any program. You need to expand your
- machine to 256 kilobytes following the documents on ftp.funet.fi in
- the /pub/cbm/hardware/256kB directory. It will let you to reset the
- computer so that all of the 64 kilobytes the previous program used,
- will remain intact. If you add a switch to one of the memory expansion
- controller's chip selection lines, the program being examined will
- have no way to screw the machine up, as the additional memory management
- registers will not be available.
-
- A few enhancements to this circuit are required so that you can freeze
- the programs without losing the state of the I/O chips. You will also
- need to replace the Kernal ROM chip with your own code, if you do not
- want to lose the state of the A, X, P and S registers. Unfortunately
- this circuit will not preserve the state of the processor's Peripheral
- lines (its built-in I/O port mapped to the memory addresses 0 and 1),
- nor does it record the program counter (PC). I have a partial solution
- to the PC problem, though.
-
- If you are interested in this project, contact me. I will design the
- additional hardware, and I will program the startup routines, but I
- certainly do not have the time to program all of the freezer software.
- Most of the freezer software could be in RAM, so it would be very easy
- to develop it, and you could even use existing tools by patching them
- slightly.
-
- =============================================================================
- FLD - Scrolling the screen
- by Marek Klampar (klampar@elf.stuba.sk)
-
-
- Scrolling the screen
- --------------------
- [inspirated by Pasi Ojala article 'Opening the borders' from issue#6]
-
- From Pasi 'Albert' Ojala's (po87553@cs.tut.fi or albert@cc.tut.fi) article:
-
- _Scrolling the screen_
-
- VIC begins to draw the screen from the first bad line. VIC will know
- what line is a bad line by comparing its scan line counter to the
- vertical scroll register : when they match, the next line is a bad
- line. If we change the vertical scroll register ($d011), the first bad
- line will move also. If we do this on every line, the line counter in
- VIC will never match with it and the drawing never starts (until it is
- allowed to do so).
-
- When we don't have to worry about bad lines, we have enough time to
- open the borders and do some other effects too. It is not necassary to
- change the vertical scroll on every line to get rid of the bad lines,
- just make sure that it never matches the line counter (or actually the
- least significant 3 bits).
-
- You can even scroll the bad lines independently and you have FLD -
- Flexible Line Distance. You just allow a bad line when it is time to
- display the next character row. With this you can bounce the lines or
- scroll a hires picture very fast down the screen.
-
- (*** end of Albert's paragraph ***)
-
- Well, everything important was written. I'm just adding this:
-
- For moving hires picture replace ORA #$10 by ORA #$30.
-
- For another FX try to replace part of irq routine begining with ORA #$10 by:
- ORA #$C0
- STA $D016,
- remove JSR CHOFS,
- replace LDX OFSET
- by LDX #$ff
- and enjoy =)
-
-
- The demonstartion program for FLD application
- ;---------------------------------------
- ; Commodore Cracker 1993
- ;---------------------------------------
- FROM = $32
- TO = $FA
- ;---------------------------------------
- *= $C000
- ;---------------------------------------
- INIT LDA #0
- STA DIR ; Direction
- LDA #$FF ; Set garbage
- STA $3FFF
- LDA #FROM
- STA OFSET ; Set ofset
- SEI ; Disable interrupt
- LDA #$7F ; Disable timer interrupt
- STA $DC0D
- LDA #1 ; Enable raster interrupt
- STA $D01A
- LDA #<IRQ ; Set irq vector
- STA $0314
- LDA #>IRQ
- STA $0315
- LDA #0 ; To evoke our irq routine on 0th line
- STA $D012
- CLI ; Enable interrupt
- RTS
- ;---------------------------------------
- IRQ LDX OFSET
- L2 LDY $D012 ; Moving 1st bad line
- L1 CPY $D012
- BEQ L1 ; Wait for begin of next line
- DEY ; IY - bad line
- TYA
- AND #$07 ; Clear higher 5 bits
- ORA #$10 ; Set text mode
- STA $D011
- DEX
- BNE L2
- INC $D019 ; Acknowledge the raster interrupt
- JSR CHOFS
- JMP $EA31 ; Do standard irq routine
- ;---------------------------------------
- OFSET .BYTE FROM
- DIR .BYTE 0
- ;---------------------------------------
- CHOFS LDA DIR ; Change OFSET of screen
- BNE UP
- INC OFSET ; Down
- LDA OFSET
- CMP #TO
- BNE SKIP
- STA DIR
- SKIP RTS
- ;---------------------------------------
- UP DEC OFSET ; Up
- LDA OFSET
- CMP #FROM
- BNE SKIP
- LDA #0
- STA DIR
- RTS
-
- =============================================================================
- Tech-tech - more resolution to vertical shift.
- by Pasi 'Albert' Ojala (po87553@cs.tut.fi _or_ albert@cc.tut.fi)
- Written on 16-May-91 Translation 02-Jun-92
-
- (All timings are in PAL, principles will apply to NTSC too)
-
- One time half of the demos had pictures waving horizontally on the
- width of the whole screen. This effect is named tech-tech, and the
- audience was puzzled. You can move the screen only eight pixels using
- the horizontal scroll register. This effect was done using character
- graphics. How exactly and is the same possible with sprites ?
-
-
- Horizontal scroll register can move the screen by eight pixels. This
- isn't even nearly enough to produce a really stunning effect. You have
- to move the graphics itself, fortunately with a resolution of one
- character position (one byte) only, the rest can be done with the scroll
- register. During one scan line there is no time to move the actual data,
- you can only move a pointer. Changing the video matrix pointer won't
- help, because VIC (video interface controller) will fetch the character
- codes only at certain times, called bad lines. You can change the
- character set pointer instead, because VIC reads the data it displays
- directly from the character set memory.
-
-
- Character set-implementation has its restrictions
-
- Because horizontal movement is done by changing the character sets, the
- picture or text must be pure graphic and the character codes in the
- video matrix must be in a numerical order. The normal picture is in the
- first character memory and in the next one it is shifted one character
- position to the right. One video bank can hold only seven full character
- memories besides the video matrix. This limits the movement of the
- picture to 56 pixels. It is possible to get more movement if you use
- smaller picture or another video bank.
-
- The shift is done so that on each scan line we update the horizontal
- scroll register ($D016) with the three lowest bits of the shift value.
- We use the other bits to select the right character set ($D018). In a
- tech-tech the shift value changes during the display of the whole
- picture, and the values are stored in a table. In addition to that, the
- shift values should be put into two tables, one for the horizontal
- scroll register and another for the character set select. This is
- necessary, because there is no time for extra calculations on a bad
- line.
-
- Because we have to change the character set and x-scroll dynamically, we
- also need a raster routine to show a tech-tech. A raster routine is a
- routine which is synchronized to the electron beam. This eats up the
- processor time: the bigger the picture, the less time is left over for
- other activities. On other than bad lines you can do other funny things,
- like change the color of the background or border.
-
-
- An example program
-
- The demo program uses video bank 2, memory addesses $4000-7fff. The
- video matrix is in the beginning of the bank. Only inverted chars are
- used for the graphics, this way we have all eight character memories
- available and the maximum shift is 64 pixels. The area for the tech-tech
- in the video matrix is eight character rows high, but it has identical
- graphics on every line. This is why we use only 320 bytes from each
- character set.
-
- You can use a joystick to control the movement of the tech-tech. The
- stick decreases or increases the shift add value in a resolution of a
- half pixel. When the shift reaches its highest/lowest value, the
- direction of the add is reversed. Just experiment with it.
-
-
- You can do it on the screen, how about borders ?
-
- Because you cannot get characters to the border, you might think that it
- is impossible to make a tech-tech effect in the borders. It takes so
- much time to change sprite x-coordinates, that you can change only some
- of them. There is time for five sprite moves, if you do not need to
- change the most significant (9th) bit of the x-coordinate. On the other
- hand, you could design the movements directly to the sprites and then
- just change the images, but then the movements would be constant.
-
- However, there is one trick you can use to get all of the sprites on the
- screen, with variable movements and color bars etc. You do not change
- the x-coordinates, but the data itself on each scan line. In fact you
- change the sprite image pointers. There is multiple sprite pictures,
- where the graphics is shifted horizontally, just like the normal
- tech-tech charsets. Because of this, the sprites have to be placed side
- by side. No gaps are allowed. By changing the image pointers you can get
- the graphics to move horizontally on each line as you wish. With
- multicolor sprites you have to remember that one pixel corresponds to
- two bits - the movement is not so smooth.
-
- Wait ! How come there is enough time to change the sprite pointers, when
- there is not time to change the coordinates ? This is another pointer
- trick. VIC reads the sprite image pointers from the end of the current
- video matrix, normally $07f8. You just have to change the video matrix
- pointer ($D018) to change all of the image pointers. This takes only
- eight cycles and there is plenty of time left for other effects on each
- scan line. If you use only one video bank, you can get the sprite
- picture to 16 different places. This allows also another kind of
- effects, just use your imagination.
-
- --------------------------------------------------------------------------
- Tech-tech demo program (PAL)
-
- BANK= $96 ; The value of the video bank register (CIA2) in the tech-area
- ZP= $FB ; Zero page for indirect addressing
- START= $4400 ; Start of the charsets (we use inverted chars)
- SCREEN= $4000 ; Position of the video matrix
- SHIFTL= $CF00 ; x-shift, lowest 3 bits
- SHIFTH= $CE00 ; x-shift, highest 3 bittid (multiplied with two)
- POINTER= $033C ; Pointer to shift-table
- VALUE= $033D ; Shift now
- SPEED= $033E ; Shift change
-
- *= $C000 ; Start address..
-
- INIT SEI ; Disable interrupts
- LDA #$7F
- STA $DC0D ; Disable timer interrupt
- LDA #$81
- STA $D01A ; Enable raster interrupt
- LDA #<IRQ
- STA $0314 ; Our own interrupt handler
- LDA #>IRQ
- STA $0315
- LDA #49 ; The interrupt to the line before the first bad line
- STA $D012
- LDA #$1B
- STA $D011 ; 9th bit of the raster compare
-
- LDY #0
- LDX #$40
- STX ZP+1
- STY ZP
- TYA
- LOOP0 STA (ZP),Y ; Clear the whole video bank ($4000-7FFF)
- INY
- BNE LOOP0
- INC ZP+1
- BPL LOOP0
-
- LDA #>START
- STA ZP+1
- LDA #$32 ; Character ROM to address space ($D000-)
- STA $01
- LOOP1 TYA ; (Y-register is zero initially)
- LSR
- LSR
- LSR
- TAX
- LDA TEXT,X ; Which char to plot ?
- ASL ; Source
- ASL
- ASL
- TAX ; low byte to X
- LDA #$D0
- ADC #0 ; high byte (one bit) taken into account
- STA LOOP2+2 ; Self-modifying again..
- LOOP2 LDA $D000,X
- STA (ZP),Y
- INX
- INY
- TXA
- AND #7
- BNE LOOP2 ; Copy one char
- CPY #0
- BNE LOOP1 ; Copy 32 chars (256 bytes)
- LDA #$37 ; Memory configuration back to normal
- STA $01
-
- LOOP3 LDA START,Y ; Copy the data to each charset, shifted by one
- STA START+2056,Y ; position to the right
- STA START+4112,Y
- STA START+6168,Y
- STA START+8224,Y
- STA START+10280,Y
- STA START+12336,Y
- STA START+14392,Y
- INY
- BNE LOOP3
- LDA #0 ; Clear the pointer, value and speed
- STA POINTER
- STA VALUE
- STA SPEED
-
- LOOP4 TYA ; (Y was zero)
- ORA #$80 ; Use the inverted chars
- STA SCREEN,Y ; Set the character codes to video matrix
- STA SCREEN+40,Y
- STA SCREEN+80,Y
- STA SCREEN+120,Y
- STA SCREEN+160,Y
- STA SCREEN+200,Y
- STA SCREEN+240,Y
- STA SCREEN+280,Y
- LDA #239 ; leave the last line empty
- STA SCREEN+320,Y
- INY
- CPY #40
- BNE LOOP4 ; Loop until the whole area is filled
- CLI ; Enable interrupts
- RTS
-
- IRQ LDA #BANK ; Change the video bank, some timing
- STA $DD00
- NOP
- NOP
-
- LDY POINTER ; Y-register will point to x-shift
- JMP BAD ; next line is a bad line
- LOOP5 NOP
- LOOP6 LDA SHIFTL,Y ; Do the shift
- STA $D016 ; 3 lowest bits
- LDA SHIFTH,Y
- STA $D018 ; another 3 bits
- NOP : NOP : NOP : NOP : NOP : NOP ; waste some time
- NOP : NOP : NOP : NOP : NOP : NOP
- NOP : NOP : NOP
- LDA $D012 ; check if it is time to stop
- CMP #$78
- BPL OVER
- INY ; next position in table
- DEX
- BNE LOOP5 ; No bad line, loop
- BAD LDA SHIFTL,Y ; This is a bad line, a bit more hurry
- STA $D016
- LDA SHIFTH,Y
- STA $D018
- INY
- LDX #7 ; New bad line coming up
- JMP LOOP6
-
- OVER LDA #$97 ; Video bank to 'normal'
- STA $DD00
- LDA #22 ; Same with the charset
- STA $D018
- LDA #8 ; and the horizontal scroll register
- STA $D016
-
- LDA $DC00 ; Let's check the joysticks
- AND $DC01
- TAX
- LDY SPEED
- AND #8 ; Turned right, add speed
- BNE EIP
- INY
- CPY #4 ; Don't store, too much speed
- BPL EIP
- STY SPEED
- EIP TXA
- AND #4 ; Turned left
- BNE ULOS
- DEY
- CPY #$FC ; Too much ?
- BMI ULOS
- STY SPEED
- ULOS LDA VALUE ; Add speed to value (signed)
- CLC
- ADC SPEED
- BPL OK
- LDA SPEED ; Banged to the side ?
- EOR #$FF
- CLC
- ADC #1
- STA SPEED
- LDA VALUE
- OK STA VALUE
- LSR ; Value is twice the shift
- TAX ; Remember the shift
- AND #7 ; lowest 3 bits
- ORA #8 ; (screen 40 chars wide)
- LDY POINTER
- STA SHIFTL,Y
- TXA
- LSR
- LSR
- LSR ; highest 3 bits too
- ASL ; multiplicated by two
- STA SHIFTH,Y
- DEC POINTER
-
- LDA #1 ; Ack the interrupt
- STA $D019
- JMP $EA31 ; The normal interrupt routine
-
- TEXT SCR "THIS IS TECH-TECH FOR C=64 BY ME" ; Test text
- ; SCR converts to screen codes
-
- --------------------------------------------------------------------------
- Basic loader for the Tech-tech demo program (PAL)
-
- 1 S=49152
- 2 DEFFNH(C)=C-48+7*(C>64)
- 3 CH=0:READA$,A:PRINTA$:IFA$="END"THENPRINT"<clr>":SYS49152:END
- 4 FORF=0TO31:Q=FNH(ASC(MID$(A$,F*2+1)))*16+FNH(ASC(MID$(A$,F*2+2)))
- 5 CH=CH+Q:POKES,Q:S=S+1:NEXT:IFCH=ATHEN3
- 6 PRINT"CHECKSUM ERROR":END
- 100 DATA 78A97F8D0DDCA9818D1AD0A9AD8D1403A9C08D1503A9318D12D0A91B8D11D0A0, 3802
- 101 DATA 00A24086FC84FB9891FBC8D0FBE6FC10F7A94485FCA9328501984A4A4AAABD5E, 4749
- 102 DATA C10A0A0AAAA9D069008D4EC0BD00D091FBE8C88A2907D0F4C000D0DDA9378501, 4128
- 103 DATA B9004499084C99105499185C99206499286C99307499387CC8D0E5A9008D3C03, 3258
- 104 DATA 8D3D038D3E0398098099004099284099504099784099A04099C84099F0409918, 3236
- 105 DATA 41A9EF994041C8C028D0DB5860A9968D00DDEAEAAC3C034CE1C0EAB900CF8D16, 4464
- 106 DATA D0B900CE8D18D0EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAAD12D0C9781016C8CAD0, 5850
- 107 DATA D9B900CF8D16D0B900CE8D18D0C8A2074CBBC0A9978D00DDA9168D18D0A9088D, 4132
- 108 DATA 16D0AD00DC2D01DCAAAC3E032908D008C8C00410038C3E038A2904D00888C0FC, 3160
- 109 DATA 30038C3E03AD3D03186D3E03100EAD3E0349FF1869018D3E03AD3D038D3D034A, 2139
- 110 DATA AA29070908AC3C039900CF8A4A4A4A0A9900CECE3C03A9018D19D04C31EA1408, 2759
- 111 DATA 091320091320140503082D1405030820060F1220033D3634200219200D050F12, 652
- 200 DATA END,0
-
- --------------------------------------------------------------------------
- Uuencoded C64 executable version of the demo program (PAL)
-
- begin 644 tech.64
- M`0@-"`$`4[(T.3$U,@`F"`(`EJ5(*$,ILD.K-#BJ-ZPH0[$V-"D`7`@#`$-(J
- MLC`ZAT$D+$$ZF4$D.HM!)+(B14Y$(J>9(CS7R,G4Q3X\P\S2/B(ZGC0Y,34R;
- M.H``DP@$`(%&LC"D,S$Z4;*E2"C&*,HH020L1JPRJC$I*2FL,3:JI4@HQBC*1
- M*$$D+$:L,JHR*2DI`+0(!0!#2+)#2*I1.I=3+%$Z4[)3JC$Z@CJ+0TBR0:<S?
- M`,P(!@"9(D-(14-+4U5-($524D]2(CJ``!D)9`"#(#<X03DW1CA$,$1$0T$YN
- M.#$X1#%!1#!!.4%$.$0Q-#`S03E#,#A$,34P,T$Y,S$X1#$R1#!!.3%".$0Q+
- M,40P03`L(#,X,#(`9@EE`(,@,#!!,C0P.#9&0S@T1D(Y.#DQ1D)#.$0P1D)%G
- M-D9#,3!&-T$Y-#0X-49#03DS,C@U,#$Y.#1!-$$T04%!0D0U12P@-#<T.0"S+
- M"68`@R!#,3!!,$$P04%!03E$,#8Y,#`X1#1%0S!"1#`P1#`Y,49"13A#.#A!]
- M,CDP-T0P1C1#,#`P1#!$1$$Y,S<X-3`Q+"`T,3(X```*9P"#($(Y,#`T-#DYE
- M,#@T0SDY,3`U-#DY,3@U0SDY,C`V-#DY,C@V0SDY,S`W-#DY,S@W0T,X1#!%,
- M-4$Y,#`X1#-#,#,L(#,R-3@`30IH`(,@.$0S1#`S.$0S13`S.3@P.3@P.3DPU
- M,#0P.3DR.#0P.3DU,#0P.3DW.#0P.3E!,#0P.3E#.#0P.3E&,#0P.3DQ."P@?
- M,S(S-@":"FD`@R`T,4$Y148Y.30P-#%#.$,P,CA$,$1"-3@V,$$Y.38X1#`P-
- M1$1%045!04,S0S`S-$-%,4,P14%".3`P0T8X1#$V+"`T-#8T`.<*:@"#($0PN
- M0CDP,$-%.$0Q.$0P14%%045!14%%045!14%%045!14%%045!14%%045!040Q,
- M,D0P0SDW.#$P,39#.$-!1#`L(#4X-3``-`MK`(,@1#E".3`P0T8X1#$V1#!"Q
- M.3`P0T4X1#$X1#!#.$$R,#<T0T)"0S!!.3DW.$0P,$1$03DQ-CA$,3A$,$$Y_
- M,#@X1"P@-#$S,@"!"VP`@R`Q-D0P040P,$1#,D0P,41#04%!0S-%,#,R.3`XN
- M1#`P.$,X0S`P-#$P,#,X0S-%,#,X03(Y,#1$,#`X.#A#,$9#+"`S,38P`,X+'
- M;0"#(#,P,#,X0S-%,#-!1#-$,#,Q.#9$,T4P,S$P,$5!1#-%,#,T.49&,3@V7
- M.3`Q.$0S13`S040S1#`S.$0S1#`S-$$L(#(Q,SD`&PQN`(,@04$R.3`W,#DP;
- M.$%#,T,P,SDY,#!#1CA!-$$T031!,$$Y.3`P0T5#13-#,#-!.3`Q.$0Q.40PI
- M-$,S,45!,30P."P@,C<U.0!G#&\`@R`P.3$S,C`P.3$S,C`Q-#`U,#,P.#)$_
- M,30P-3`S,#@R,#`V,$8Q,C(P,#,S1#,V,S0R,#`R,3DR,#!$,#4P1C$R+"`V&
- 4-3(`<PS(`(,@14Y$+#````````HS!
- ``
- end
-
- =============================================================================
- ACE-128/64 PROGRAMMER'S REFERENCE GUIDE (version 0.9, for Release #10)
- by Craig Bruce <csbruce@ccnga.uwaterloo.ca>
-
- 1. INTRODUCTION
-
- ACE is a program for the Commodore 128 and Commodore 64 that provides a
- command shell environment that is similar to that of Unix. It is still
- in the development stage, but enough of it is complete to be useful.
- BTW, "ACE" means "Advanced Computing Environment" (well, advanced for
- the 128/64).
-
- So what is ACE all about? Well, originally I tried a very ambitious
- project of writing a multitasking operating system for the 128. It got
- it partially working, but it was much too fragile and incomplete to be
- released. It was a white-elephant project. So, then then it came to me
- that I was aiming much too high. What I needed was a much simpler
- system, one that would give the type of programming interface and
- built-in features that I wanted, but one that was close enough to the
- Commodore Kernal that it would not require much of a programming effort
- to hack together a minimal implementation. And thus, there was ACE-128
- Release #1. And I saw it was good.
-
- What I wanted was a system that would be easier to program than the
- Commodore Kernal with all its weird and wonderful device types,
- non-existent memory management, and single-application design. The
- first important feature of this environment was to be able to pass
- arguments from a command line to an application program by typing them
- on the command line of the shell. It is so annoying to load up a
- program in BASIC, run it, and have it ask you for filenames in some
- highly inconvenient way.
-
- Another important system feature is to make near and far memory
- management part of the system, and to make far memory convenient to use
- for storing massively bulky data. And so it was. Also, we want to use
- custom device drivers. Commodore didn't really come through with the
- device drivers it provided. They are all REALLY SLOW. And so that was,
- also, although more custom device drivers are needed. We want to have
- the capability of making programs work together, rather than having
- programs that are totally incompatible. This functionality is still
- under construction. Programs will work together in this uni-tasking
- environment by allowing a program to execute another program as a
- sub-task, and then having control return to the calling program upon
- exit. Finally, we want some good quality applications and a powerful
- command shell. This is still being worked on and progress is coming
- slowly. Oh, almost forgot; we also want all programs to work on both
- the C64 and C128, and they do.
-
- This documentation refers to ACE release #10, which has not been
- released yet (or even programmed). In fact, the current release is #9.
- Release #10 will be spruced up from the inside out to support the system
- interface described in this document. The current release is not being
- described, because some of its features are not the best they could
- possibly be. Note, however, that the basic features, like "open",
- "read", "dirread", and argv are not going to change. Note also that the
- version number of this "P.R.G." is 0.9. This is because this is the
- first incarnation of this document and, considering its nature, is bound
- to hold a large number of small errors.
-
- 2. SYSTEM INTERFACE
-
- This section describes the interface between user programs and the ACE
- kernel. I am very careful throughout this interface specification about
- revealing any internal details that you do not strictly need to know.
- The interface with ACE is not specified in terms of absolute addresses;
- to aid in portability and extensibility, all interfaces are specified in
- terms of symbolic assembler labels. All of the ACE code is currently
- written for the Buddy-128 assembler. Also, because these interface
- absolute addresses are subject to change from version to version of the
- kernel, executables compiled for use with an old version of ACE may not
- work with a new version.
-
- 2.1. ZERO-PAGE VARIABLES
-
- There are four zero-page variables used for passing arguments in most
- system calls. They are as follows:
-
- SYMBOL BYTES DESCRIPTION
- ------- ----- -----------
- zp 2 zeropage pointer
- zw 2 zeropage word
- mp 4 memory pointer
- syswork 16 system work area / arguments
-
- The first two, "zp" and "zw" are used in most calls. They store simple
- 16-bit values; "zp" usually stores pointers to strings in RAM0 memory.
- The "mp" variable is 32-bits in length and is used exclusively for
- passing far memory pointers for use with the far memory routines. All
- three of these variables will remain unchanged inside of system call
- unless they will contain a return value. "syswork" is a 16-byte array
- used mainly when there are too many arguments for other variables to
- hold, and all non-input and non-output bytes of "syswork" are subject to
- change by the kernel. All input arguments placed in the "syswork"
- locations will be preserved unless otherwise indicated. [Note: In
- Release #9, "zp" took on the rolls of both "zp" and "mp"].
-
- 2.2. SYSTEM VARIABLES
-
- There are several non-zeropage variables for storing system status and
- return values:
-
- SYMBOL BYTES DESCRIPTION
- ---------- ----- -----------
- errno 1 error number code returned by failed system calls
- aceID 2 proof that user program is running on top of ACE
- aceArgc 2 argument count for current process
- aceArgv 2 argument vector address for current process
- aceMemTop 2 highest address, plus one, that user prog can use
- aceShellPath 2 ptr to storage for search path for executable programs
- aceShellAlias 2 ptr to storage for shell command aliases
- aceCurDirName 2 ptr to storage for the current directory name
- aceExitData 2 ptr to storage for exit status from the last called prg
- aceDirentBuffer <next> storage for directory entries read from disk
- aceDirentLength - really a constant: length in bytes of "aceDirentBuffer"
- aceDirentBytes 4 bytes in file (usually inexact)
- aceDirentDate 8 date of file in "YY:YY:MM:DD:HH:MM:SS:TW" format
- aceDirentType 4 type of file in null-terminated string
- aceDirentFlags 1 flags of file, "drwx*-et" format
- aceDirentNameLen 1 length of name of file
- aceDirentName 17 null-terminated name of file
-
- ERRNO: "errno" is used to return error codes from system calls. When a
- system call ends in error, it sets the carry flag to "1", puts the error
- code in "errno", and returns to the user program, after undoing any
- system work completed at the time the error is encountered and aborting
- the operation. An error code number is stored in binary in the
- single-byte "errno" location. The symbolic names for the possible error
- codes are given in the next section. If no error occurs in a system
- call, the carry flag will be cleared on return from the call. Note that
- not all system calls can run into errors, so not all set the carry flag
- accordingly.
-
- ID: "aceID" is a two-byte variable. Its purpose is to allow user
- programs to be sure that they are executing on top of ACE. The low byte
- (i.e., the first byte) must be equal to the symbolic constant "aceID1",
- and the high, "aceID2". This will allow ACE applications to inform idiot
- users that they cannot simply BOOT the program from BASIC, but rather
- they must run ACE first.
-
- ARGC: "aceArgc" is a two-byte unsigned number. It gives the number of
- arguments passed to the application by the program (usually the command
- shell) that called the application. The first argument is always the
- name of the application program, so the count will always be at least
- one. Other arguments are optional.
-
- ARGV: "aceArgv" is a two-byte RAM0 pointer. Pay attention. This
- pointer points to the first entry of an array of two-byte pointers which
- point to the null-terminated strings that are the arguments passed to
- the application program by the caller. (A null-terminated string is one
- that ends with a zero byte). To find the address of the N-th argument
- to an application, multiply N by two, add the "aceArgv" contents to
- that, and fetch the pointer from that address. In this scheme, the
- ever-present application name is the 0-th argument. The argv[argc]
- element of the argument vector will always contain a value of $0000, a
- null pointer.
-
- MEM-TOP: "aceMemTop" is a two-byte RAM0 pointer. This points to one
- byte past the highest byte that the application program is allowed to
- use. All application programs are loaded into memory at address
- "aceAppAddress" (next section), and all memory between the end of the
- progam code and "aceMemTop" can be used for temporary variables, file
- buffers, etc. The main problem with this approach is that there are no
- guarantees about how much memory your application will get to play with.
- Many applications, such as simple file utilities, can simply use all
- available memory for a file buffer, but other programs, such as a file
- compressor, may have much greater demand for "near" memory. [Note: this
- variable has a different name in Release #9].
-
- SHELL-PATH: "aceShellPath" is a two-byte RAM0 pointer. This points to
- the page of memory that stores the pathnames of directories to search
- through in order to find executable files. Each pathname is stored as a
- null-terminated string, and the list is terminated by an empty string
- (containing only the zero character). This is intended to be used by
- the shell program, or any other program that is so inclined, to examine
- or alter the search path. The search paths specified in the path page
- are global variables and are used by all programs that make the "exec"
- system call. This mechanism for reading/altering the executable search
- path may be changed in the future.
-
- SHELL-ALIAS: "aceShellAlias" is a two-byte RAM0 pointer. This points to
- the page of memory that stores the aliases to be used with the command
- shell. An alias is a string that is substituted in the place of a
- command name on a shell command line whenever a certain command name
- comes up. For example, you might specify if the user enters the command
- "list a:" that the command name "list" be string-replaced with "cls;xls
- -l". Each alias is stored with the command name first, followed by an
- equals character ("="), followed by the string to substitute, followed
- by a zero. The alias list is terminated by an empty string. This
- mechanism may be extended in the future to allow multiple pages of
- aliases, or may be changed completely.
-
- CUR-DIR-NAME: "aceCurDirName" is a two-byte RAM0 pointer. It points to
- the null-terminated string indicating the current directory. The user
- is not supposed to modify this value, and the value will not always give
- a full pathname. The implementation of this feature may need to change
- in future versions of ACE.
-
- ACE-EXIT-DATA: "aceExitData" is a two-byte RAM0 pointer. It points to
- the 256-byte buffer allocated for user programs to give detailed return
- information upon exiting back to their parent program. See the "exit"
- system call. User programs are allowed to read and write this storage.
- An example use of this feature would be a compiler program returning the
- line number and character position, and description of a compilation
- error to a text editor, so the editor can position the cursor and
- display the error message for user convenience. The implementation of
- this feature may need to change in future versions of ACE.
-
- DIRENT-BUFFER: "aceDirentBuffer" is a buffer used for storing directory
- information read with the "dirread" system call, and is
- "aceDirentLength" bytes long. Only a single directory entry is
- (logically) read from disk at a time. The individual fields of a read
- directory entry are accessed by the fields described next. This field
- is also used for returning disk name information and the number of bytes
- free on a disk drive (see the "dirread" system call).
-
- DIRENT-BYTES: "aceDirentBytes" is a four-byte (32-bit) unsigned field.
- As always, the bytes are addressed from least significant to most
- significant. This field gives the number of bytes in the file. Note
- that this value may not be exact, since Commodore decided to store sizes
- in disk blocks rather than bytes. For devices that report only block
- counts (i.e., every disk device currently supported), the number of
- bytes returned is the number of blocks multiplied by 254. This field,
- as well and the other dirent fields are absolute addresses, not offsets
- from aceDirentBuffer.
-
- DIRENT-DATE: "aceDirentDate" is an eight-byte array of binary coded
- decimal values, stored from most significant digits to least
- significant. The first byte contains the BCD century, the second the
- year, and so on, and the last byte contains the number of tenths of
- seconds in its most significant nybble and a code for the day-of-week in
- its least significant nybble. Sunday has code 1, Monday 2, etc.,
- Saturday 7, and a code of 0 means "unknown". This is the standard
- format for all dates used in ACE. This format is abstracted as
- "YY:YY:MM:DD:HH:MM:SS:TW". For disk devices that don't support dates,
- this field will be set to all zeroes, which can be conveniently
- interpreted as the NULL date, negative infinity, or as the time that
- J.C. was a seven-year-old boy.
-
- DIRENT-TYPE: "aceDirentType" is a three-character (four-byte)
- null-terminated string. It indicates what type the file is, in
- lowercase PETSCII. Standard types such as "SEQ" and "PRG" will be
- returned, as well and other possibilities for custom device drivers.
-
- DIRENT-FLAGS: "aceDirentFlags" is a one-byte field that is interpreted
- as consisting of eight independent one-bit fields. The abstract view of
- the fields is "drwx*-et". "d" means that the item is a subdirectory
- (otherwise it is a regular file), "r" means the item is readable, "w"
- means the item is writable, and "x" means the item is executable. The
- "x" option is really not supported currently. "*" means the item is
- improperly closed (a "splat" file in Commodore-DOS terminology). The
- "-" field is currently undefined. "e" means that the value given in the
- "aceDirentBytes" field is actually exact, and "t" means the file should
- be interpreted as being a "text" file (otherwise, its type is either
- binary or unknown). The bit fields are all booleans; a value of "1"
- means true, "0", false. The "d" bit occupies the 128-bit position, etc.
-
- DIRENT-NAME-LEN: "aceDirentNameLen" is a one-byte number. It gives the
- number of characters in the filename. It is present for convenience.
-
- DIRENT-NAME: "aceDirentName" is a 16-character (17-byte) null-terminated
- character string field. It gives the name of the file or directory or
- disk. Filenames used with ACE are limited to 16 characters.
-
- 2.3. SYSTEM CONSTANTS
-
- There are several symbolic constants that are used with the ACE system
- interface:
-
- SYMBOL DESCRIPTION
- ------------------- -------------------------
- aceAppAddress the start address of applications
- aceID1 the id characters used to identify ACE applications
- aceID2 ...
- aceID3 ...
- aceMemNull the far memory type code used to indicate null ptrs
- aceMemREU far mem type code for Ram Expansion Unit memory
- aceMemInternal far mem type code for internal memory
- aceMemRLREU far mem type code for REU memory accessed thru RAMLink
- aceMemRL far mem type code for direct-access RAMLink memory
- aceErrStopped error code for syscall aborted by STOP key
- aceErrTooManyFiles err: too many files already opened to open another
- aceErrFileOpen err: don't know what this means
- aceErrFileNotOpen err: the given file descriptor is not actually open
- aceErrFileNotFound err: named file to open for reading does not exist
- aceErrDeviceNotPresent err: the specified physical device is not online
- aceErrFileNotInput err: file cannot be opened for reading
- aceErrFileNotOutput err: file cannot be opened for writing
- aceErrMissingFilename err: pathname component is the null string
- aceErrIllegalDevice err: the specified device cannot do what you want
- aceErrWriteProtect err: trying to write to a disk that is write-protected
- aceErrFileExists err: trying to open for writing file that exists
- aceErrFileTypeMismatch err: you specified the file type incorrectly
- aceErrNoChannel err: too many open files on disk drive to open another
- aceErrInsufficientMemory err: ACE could not allocate the memory you requested
- aceErrOpenDirectory err: you are trying to open a dir as if it were a file
- aceErrDiskOnlyOperation err: trying to perform disk-only op on char device
- aceErrNullPointer err: trying to dereference a null far pointer
- aceErrInvalidFreeParms err: bad call to "pagefree": misaligned/wrong size
- aceErrFreeNotOwned err: trying to free far memory you don't own
- stdin file descriptor reserved for stdin input stream
- stdout file descriptor reserved for stdout output stream
- stderr file descriptor reserved for stderr output stream
-
- "aceAppAddress", as discussed before, is the address that application
- programs are loaded into memory at. They must, of course, be compiled
- to execute starting at this address.
-
- The "aceMem" group of constants are for use with the "pagealloc" system
- call, except for "aceMemNull", which may be used by application programs
- for indicating null far pointers. The "pagealloc" call allows you to
- specify what types of memory you are willing to accept. This is
- important because the difference types of memory have different
- performance characteristics. ACE will try to give you the fastest
- memory that is available. Ram Expansion Unit memory has startup and
- byte-transfer times of about 60 us (microseconds) and 1 us,
- respectively. This is the fastest type of far memory. Internal memory
- has a startup time of 24 us and a byte-transfer time of between 7 and 14
- us (depending on whether accessing RAM0 or RAM1+). REU memory accessed
- through a RAMLink has a terrible startup time of 1000 us and a
- byte-transfer time of 2 us. Direct-access RAMLink memory has a startup
- time of 1000 us and a byte-transfer time of 16 us. All these times are
- for the C128 in 2 MHz mode.
-
- The "aceErr" group gives the error codes returned by system calls. The
- error codes are returned in the "errno" variable. Not all possible
- error codes from Commodore disk drives are covered, but the important
- ones are. Finally, the "std" files group give the symbolic file
- descriptor identifiers of the default input, output, and error output
- file streams.
-
- 2.4. SYSTEM CALLS
-
- All system calls are called by setting up arguments in specified
- processor registers and memory locations, executing a JSR to the system
- call address, and pulling the return values out of processor registers
- and memory locations.
-
- 2.1. FILE CALLS
-
- NAME : open
- PURPOSE: open a file
- ARGS : (zp) = pathname
- .A = file mode ("r", "w", or "a")
- RETURNS: .A = file descriptor number
- .CS = error occurred flag
- ALTERS : .X, .Y, errno
-
- Opens a file. The name of the file is given by a pointer to a
- null-terminated string, and may contain device names and pathnames as
- specified in the ACE user documentation. The file mode is a PETSCII
- character. "r" means to open the file for reading, "w" means to open
- the file for writing, and "a" means to open the file for appending
- (writing, starting at the end of the file). An error will be returned
- if you attempt to open for reading or appending a file that does not
- exist, or if you attempt to open for writing a file that does already
- exist. If you wish to overwrite an existing file, you will have to call
- "remove" to delete the old version before opening the new version for
- writing.
-
- The function returns a file descriptor number, which is a small unsigned
- integer that is used with other file calls to specify the file that has
- been opened. File descriptors numbered 0, 1, and 2 are used for stdin,
- stdout, and stderr, respectively. The file descriptor returned will be
- the minimum number that is not currently in use. These numbers are
- system-wide (rather than local to a process as in Unix), and this has
- some implications for I/O redirection (see the "fdswap" call below).
-
- Restrictions: only so many Kernal files allowed to be open on a disk
- device, and there is a system maximum of open files. You will get a
- "too many files" error if you ever exceed this limit. Also, because of
- the nature of Commodore-DOS, there may be even tighter restrictions on
- the number of files that can be simultaneously open on a single disk
- device, resulting in a "no channel" error. Note that this call checks
- the status channel of Commodore disk drives on each open, so you don't
- have to (and should not anyway).
-
- If the current program exits either by calling "exit" or simply by doing
- the last RTS, all files that were opened by the program and are still
- open will be automatically closed by the system before returning to the
- parent program.
-
- NAME : close
- PURPOSE: close an open file
- ARGS : .A = File descriptor number
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Closes an open file. Not much to say about this one.
-
- NAME : read
- PURPOSE: read data from an open file
- ARGS : .X = File descriptor number
- (zp) = pointer to buffer to store data into
- .AY = maximum number of bytes to read
- RETURNS: (zw) = .AY=number of bytes actually read in
- .CS = error occurred flag
- .ZS = EOF reached flag
- ALTERS : .X, errno
-
- Reads data from the current position of an open file. Up to the
- specified maximum number of bytes will be read. You should not give a
- maximum of zero bytes, or you may misinterpret an EOF (end of file).
- The buffer must be at least the size of the maximum number of bytes to
- read. The data are not interpreted in any way, so it is the
- programmer's responsibility to search for carriage return characters to
- locate lines of input, if he so desires. However, for the console the
- input is naturally divided up into lines, so each call will return an
- entire line of bytes if the buffer is large enough. There are no
- guarantees about the number of bytes that will be returned, except that
- it will be between 1 and the buffer size. So, if you wish to read a
- certain number of bytes, you may have to make multiple read calls.
-
- The call returns the number of bytes read in both the .AY register pair
- and in (zw), for added convenience. [Note: in ACE Release #9, the
- number of bytes read are returned only in the .AY registers, not in
- (zw).] A return of zero bytes read means that the end of the file has
- been reached. An attempt to read beyond the end of file will simply
- give another EOF return. End of file is also returned in the .Z flag of
- the processor.
-
- NAME : write
- PURPOSE: write data to an open file
- ARGS : .X = file descriptor number
- (zp) = pointer to data to be written
- .AY = length of data to be written in bytes
- RETURNS: .CS = error occurred
- ALTERS : .A, .X, .Y, errno
-
- Writes data at the current position of an open file. [Note: ACE Release
- #9 also alters locations (zw) when writing to the console. This problem
- will be corrected.]
-
- NAME : fastopen
- PURPOSE: open a file for fast reading
- ARGS : (zp) = Name
- .A = file mode (must be "r")
- RETURNS: .A = file descriptor number
- .CS = error occurred flag
- ALTERS : .X, .Y, errno
-
- This performs the same function as the regular "open" call, except this
- style of file accessing will allow files to be read much faster than the
- other. On devices that are so equipped, the "fastload" burst command is
- used (similar shortcuts may be possible with other devices too). The
- drawback of this increased speed is that no other device I/O can take
- place while a file is opened for "fast" access, not even to other
- devices, except for output to the console. Other files can be open,
- just not accessed. You also cannot open more than one "fast" file at a
- time. Interrupts will be disabled while a file is open for fast
- accessing, so the user cannot re-enable them, for technical reasons.
- The arguments to this call are exactly the same as the regular "open" to
- make it easy to switch from using one to the other. [Note: these "fast"
- calls do not exist in Release #9].
-
- NAME : fastclose
- PURPOSE: close the file that was opened for fast reading
- ARGS : .A = File descriptor number
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Closes the file that was opened for fast reading.
-
- NAME : fastread
- PURPOSE: read data from the file opened for fast reading
- ARGS : .X = File descriptor number
- (zp) = pointer to buffer to store data into
- .AY = maximum number of bytes to read
- RETURNS: (zw) = .AY=number of bytes actually read in
- .CS = error occurred flag
- .ZS = EOF reached flag
- ALTERS : .X, errno
-
- Read data from the (one) file that is currently opened for "fast"
- reading. The arguments and semantics are equivalent to the regular
- "read" call.
-
- NAME : bload
- PURPOSE: binary load
- ARGS : (zp) = pathname
- .AY = address to load file
- (zw) = highest address that file may occupy, plus one
- RETURNS: .AY = end address of load, plus one
- .CS = error occurred flag
- ALTERS : .X, errno
-
- Binary-load a file directly into memory. If the file will not fit into
- the specified space, an error will be returned and the load truncated if
- the device supports truncation; otherwise, important data may be
- overwritten.
-
- NAME : remove
- PURPOSE: delete a file
- ARGS : (zp) = pathname
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Delete the named file.
-
- NAME : rename
- PURPOSE: rename a file or directory
- ARGS : (zp) = old filename
- (zw) = new filename
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Renames a file or directory. If a file with the new name already
- exists, then the operation will be aborted and a "file exists" error
- will be returned. On most devices, the file to be renamed must be in
- the current directory and the new name may not include any path, just a
- filename.
-
- NAME : devinfo
- PURPOSE: give information about device
- ARGS : .X = file descriptor number
- RETURNS: .A = device type code
- .X = number of columns on device
- .Y = number of rows per "page" of device
- .CS = error occurred flag
- ALTERS : errno
-
- This call returns information about the device of an open file. There
- are four possible values for the device type code: 0==console,
- 1==character-oriented device, and 2==disk device. The number of rows
- and columns per "page" of the device are also returned. For the
- console, this will be the current window size. For a character-oriented
- device, it will be the natural size (typically 80 columns by 66 rows),
- and for a disk, it will be 40 columns in 64 mode or 80 columns in 128
- mode, both by 66 rows.
-
- NAME : fdswap
- PURPOSE: swap two file descriptor numbers
- ARGS : .X = first file descriptor number
- .Y = second file descriptor number
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- This call swaps meanings of two file descriptor numbers. The file
- descriptors may be either in use or not use when the call is made. This
- call is intended to be used to redirect the stdin, stdout, and stderr
- file streams. To do this, simply open the new file intended to be, for
- example, stdout, and swap the file descriptor number returned from the
- open with file descriptor number 1 (stdout). Poof. Then call your
- subroutine or external program, and on return, swap the two file
- descriptors back, and close the redirection file.
-
- 2.2. DIRECTORY CALLS
-
- NAME : diropen
- PURPOSE: open a directory for scanning its directory entries
- ARGS : (zp) = directory pathname
- RETURNS: .A = file descriptor number
- .CS = error occurred flag
- ALTERS : .X, .Y, errno
-
- This call opens a directory for reading its entries. It returns a
- "file" descriptor number to you to use for reading successive directory
- entires with the "dirread" call. The pathname that you give to this
- call must be a proper directory name like "a:" or "c:2//c64/games/:",
- ending with a colon character. You can have directories from multiple
- devices open for reading at one time, but you cannot have the directory
- of one device open multiple times. Also note that you cannot pass
- wildcards to this call; you will receive the entire directory listing.
-
- NAME : dirclose
- PURPOSE: close a directory opened for scanning
- ARGS : .A = file descriptor number
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Closes a directory that is open for reading. You can make this call at
- any point while scanning a directory; you do not have to finish scanning
- an entire directory first.
-
- NAME : dirread
- PURPOSE: read the next directory entry from an open directory
- ARGS : .X = file descriptor number
- RETURNS: .Z = end of directory flag
- .CS = error occurred flag
- aceDirentBuffer = new directory entry data
- ALTERS : .A, .X, .Y, errno
-
- Reads the next directory entry from the specified open directory into
- the system interface global variable "aceDirentBuffer" described
- earlier. After opening a directory for reading, the first time you call
- this routine, you will receive the name of the disk (or directory). The
- "aceDirentNameLen" and "aceDirentName" fields are the only ones that
- will contain information; the rest of the fields should be ignored.
-
- Each subsequent call to this routine will return the next directory
- entry in the directory. All of the "dirent" fields will be valid for
- these.
-
- Then, after all directory entries have been read through, the last call
- will return a directory entry with a null (zero-length) name. This
- corresponds to the "blocks free" line in a Commodore disk directory
- listing. The "aceDirentBytes" field for this last entry will be set to
- the number of bytes available for storage on the disk. On a Commodore
- disk drive, this will be the number of blocks free multiplied by 254.
- After reading this last entry, you should close the directory.
-
- At any time, if something bizarre happens to the listing from the disk
- that is not considered an error (I don't actually know if this is
- possible or not), then the .Z flag will be set, indicating the abrupt
- ending of the directory listing.
-
- NAME : isdir
- PURPOSE: determine whether the given pathname is for a file or a directory
- ARGS : (zp) = pathname
- RETURNS: .A = device identifier
- .X = is a disk device flag
- .Y = is a directory flag
- .CS = error occurred flag
- ALTERS : errno
-
- Given a properly formatted directoryname or filename, this routine will
- return whether the name is for a file or a directory, whether the device
- of the file or directory is a disk or character device, and the system
- identifier for the device. The two flags return $FF for true and $00
- for false. The device identifier is superfluous for now, but a
- "devinfo" call may be added later. Note that this file does not indicate
- whether the file/directory actually exists or not.
-
- NAME : chdir
- PURPOSE: change the current working directory
- ARGS : (zp) = new directory pathname
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Changes the current working directory to the named directory. Too bad
- the Commodore Kernal doesn't have a similar call. Unlike the "cd" shell
- command, the argument has to be a properly formatted directory name.
- Note that only directories in native partitions on CMD devices are
- supported by this command; the 1581's crummy idea of partitions is not
- supported.
-
- NAME : cdhome
- PURPOSE: change the current working directory back to the "home" directory
- ARGS : <none>
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Changes the current working directory back to the "home" directory that
- is defined in the "config.sys" file as the initial directory.
-
- NAME : mkdir
- PURPOSE: create a new directory
- ARGS : (zp) = pathname of new directory
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Creates a new directory. I'm not sure, but I think that the current
- directory has to be the parent directory of the directory you want to
- create. This may be required by CMD devices, which will be the lowest
- common denominator for directory support. [Note: this call is not
- implemented in Release #9].
-
- NAME : rmdir
- PURPOSE: delete an empty existing directory
- ARGS : (zp) = pathname of empty directory to remove
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Deletes an existing directory. The directory must be empty (have no
- directory entries) in order for this command to succeed. Again, I am
- pretty sure that you have to be "in" the parent directory of the one to
- be deleted, since this is probably required by CMD devices. [Note: this
- call is not implemented in Release #9].
-
- 2.3. MEMORY CALLS
-
- The calls given in this section are to be used for accessing "far"
- memory in ACE, which includes all REU, RAMLink, RAM1 and above, and
- sections of RAM0 that are not in the application program area.
- Applications are not allowed to access "far" memory directly, because
- the practice of bypassing the operating system would undoubtedly lead to
- problems (can you say "MS-DOS"?).
-
- All of these calls use a 32-bit pointer that is stored in the zero-page
- argument field "mp" (memory pointer). This field is to be interpreted
- as consisting of low and high words. The low word, which of course come
- first, is the offset into the memory "bank" that is contained in the
- high word. Users may assume that offsets within a bank are continuous,
- so operations like addition may be performed without fear on offsets, to
- access subfields of a structure, for example. You may not, however,
- make any interpretation of the bank word. An application should only
- access far memory that it has allocated for itself via the "pagealloc"
- call.
-
- NAME : zpload
- ARGS : [mp] = source far memory pointer
- .X = destination zero-page address
- .Y = transfer length
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Load zero-page locations with the contents of far memory. "mp", of
- course, gives the address of the first byte of far memory to be
- retrieved. The X register is loaded with the first address of the
- storage space for the data on zero page. It must be in the application
- zero-page space. The Y register holds the number of bytes to be
- transferred, which, considering that transfers must be to the
- application zero-page storage, must be 126 bytes or less. This routine
- will return a "reference through null pointer" if [mp] contains a null
- pointer.
-
- NAME : zpstore
- ARGS : .X = source zero-page address
- [mp] = destination far memory pointer
- .Y = transfer length
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- This routine is the complement of "zpload"; this transfers data from
- zero page to far memory. The arguments and restrictions are the same as
- "zpload".
-
- NAME : fetch
- ARGS : [mp] = source far memory pointer
- (zp) = destination RAM0 pointer
- .AY = transfer length
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- This routine will fetch up to 64K of data from far memory into RAM0
- memory where it can be accessed directly by the processor. The
- arguments should mostly speak for themselves. You should not fetch into
- RAM0 memory that is not specifically allocated to the application. You
- will get an error if you try to use a null far pointer.
-
- NAME : stash
- ARGS : (zp) = source RAM0 pointer
- [mp] = destination far memory pointer
- .AY = transfer length
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- This is the complement of "fetch" and operates analogously, except that
- it transfers data from RAM0 to far memory.
-
- NAME : pagealloc
- ARGS : .A = requested number of pages to be allocated
- .X = starting "type" of memory to search
- .Y = ending "type" of memory to search, inclusive
- RETURNS: [mp] = far memory pointer to start of allocated memory
- .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- This routine allocates a given number of contiguous far-memory pages for
- use by the application, and returns a pointer to the first byte of the
- first page. On calling, the accumulator contains the number of pages to
- allocate (a page is 256 contiguous bytes aligned on a 256-byte address
- (i.e., the low byte of a page address is all zeros)).
-
- The X and Y registers contain the start and end "types" of far memory to
- search for the required allocation. The possible types are mentioned in
- the System Constants section. The numeric values for the "aceMem"
- constants are arranged in order of accessing speed. So, if your
- application has speed requirements that dictate, for example, that
- RAMLink memory should not be used, then you would call "pagealloc" with
- a search range of .X=0 to .Y=aceMemInternal. If you wanted to say you
- are willing to accept any memory the system can give to you, you would
- specify .X=0 to .Y=255. The values of 0 and 255 will be converted to
- the fastest and slowest memory available. ACE will give you the fastest
- type of memory, from what you specify as acceptable, that it can. If
- you had an application that you didn't want to waste the high-speed
- memory on, you could first call "pagealloc" asking for slow memory, such
- as .X=aceMemRLREU to .Y=255, and if there is none of that type of memory
- left, make another call with .X=0 to .Y=aceMemRLREU-1.
-
- This routine will then search its available free memory for a chunk
- fitting your specifications. If it cannot find one, the routine will
- return a "insufficient memory" error and a null pointer. Note that this
- error may occur if there is actually the correct amount of memory free
- but just not in a big enough contiguous chunk. If successful, this
- routine will return in "mp" a pointer to the first byte of the first
- page of the allocated memory.
-
- If you call a subprogram with the "exec" call while the current program
- is holding far memory, that far memory will be kept allocated to your
- program and will be safe while the child program is executing. If you
- don't deallocate the memory with "pagefree" before exiting back to your
- parent program, then the system will automatically deallocate all memory
- allocated to you. So, have no fear about calling "exit" if you are in
- the middle of complicated far memory manipulation when a fatal error
- condition is discovered and you don't feel like figuring out what memory
- your program owns and deallocating it.
-
- Some applications will want to have the most amount of memory to work
- with, and if there is free space in the application program area that
- the program is not using directly, then you may want to use that as
- "far" memory. To do this, you will need to write your own stub routines
- that manage page allocation and deallocation requests to the near
- memory, and calls the "pagealloc" and "pagefree" routines to manage the
- far memory. The "sort" program distributed with ACE does this. Please
- note that you CANNOT simply free the unused memory of the application
- program area and expect the system to manage it. Bad stuff would
- happen.
-
- Some applications will want to have a byte-oriented memory allocation
- service rather than a page-oriented service. You can build a
- byte-oriented service on top of the page-oriented service in your
- application programs that manage memory for the application and ask the
- system for pages whenever more memory is required by the application.
- Note that this still means that allocated memory will be freed
- automatically when an application exits. The "sort" program implements
- this byte-oriented service, so you can check its source code to see how
- this is done (or to simply cut and paste the code into your own
- program).
-
- NAME : pagefree
- ARGS : [mp] = far memory pointer to start of memory to be freed
- .A = number of pages to be freed
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- This deallocates memory that was allocated to a process by using the
- "pagealloc" system call. You will get an error return if you try to
- deallocate memory that you don't own.
-
- 2.4. SCREEN CONTROL CALLS
-
- This section describes the system calls that are available to
- application programmers for full-screen applications. These calls are
- intended to be general enough to handle different screen hardware (the
- VIC and VDC chips and a VIC soft-80-column bitmap screen, and possibly
- others). These calls are also designed to be efficient as possible, to
- discourage progammers from attempting to bypass using them. Bypassing
- these calls would be a bad thing.
-
- The calls are designed around the C-128/PET concept of a window. There
- is only one active window on the display at a time, which may be is
- large as the entire screen or as small as 1x1 character cells. This
- window is very cheap to setup and tear down. An application can have
- multiple windows on the screen by switching the active window around.
-
- In the calls below, all mention of "sw" in the arguments and return
- values refer to the "syswork" array. For many calls, there is a
- "char/color/ high-attribute" argument. This argument determines which
- parts of a screen location will be modified. There are three components
- to each screen location: the character code, the color code, and the
- high-attributes. The character code is exactly the same as the PETSCII
- code for the character that you want to display (unlike the screen-code
- arrangement that Commodore chose). There are 128 individual characters
- in the normal PETSCII positions, and 128 reversed images of the
- characters in the most sensible other positions. The codes are as
- follows:
-
- CODES (hex) DESCRIPTION
- ----------- -----------
- $00-$1f reverse lowercase letters
- $20-$3f digits and punctuation
- $40-$5f lowercase letters
- $60-$7f reverse graphics characters
- $80-$9f reverse uppercase letters
- $a0-$bf graphics characters
- $c0-$df uppercase letters
- $e0-$ef reverse digits and punctuation
-
- There are sixteen color codes, occupying the lower four bits of the color
- value. These are RGBI codes, as follows:
-
- CODE(dec) (hex) (bin) DESCRIPTION
- --------- ----- -rgbi -----------
- 0 $0 %0000 black
- 1 $1 %0001 dark grey
- 2 $2 %0010 blue
- 3 $3 %0011 light blue
- 4 $4 %0100 green
- 5 $5 %0101 light green
- 6 $6 %0110 dark cyan on VDC, medium grey on VIC-II
- 7 $7 %0111 cyan
- 8 $8 %1000 red
- 9 $9 %1001 light red
- 10 $a %1010 purple
- 11 $b %1011 light purple on VDC, orange on VIC-II
- 12 $c %1100 brown
- 13 $d %1101 yellow
- 14 $e %1110 light grey
- 15 $f %1111 white
-
- Finally, there are the high-attribute bits. These occupy the four most
- significant bits of the color value. Depending on the type of display
- (VIC text, VDC text, or VIC/VDC bitmap), these bits have one of three
- meanings: character attributes, background character color, or no
- effect. Thus, care must be taken in using these bits; they will have
- different effects on different displays. The background character codes
- are the same as the foreground character codes listed above. The
- character attributes have the following meanings:
-
- BIT VALUE (dec) (hex) DESCRIPTION
- -avub---- ----- ----- -----------
- %10000000 128 $80 alternate characterset (italic)
- %01000000 64 $40 reverse character
- %00100000 32 $20 underline
- %00010000 16 $10 blink
-
- These values are additive (or, should I say, "or-ative"); you can use
- any combination of them at one time. Normally, you may wish to leave
- the high-attribute bits alone, unless you take the values to give them
- from the color palettes (next section). To specify which of you wish to
- have changed, set bits in the "char/color/high-attribute" argument to
- system calls. The flags have the following values. They are or-ative
- as well:
-
- BIT VALUE (dec) (hex) DESCRIPTION
- -cah----- ----- ----- -----------
- %10000000 128 $80 modify character
- %01000000 64 $40 modify color
- %00100000 32 $20 modify high-attribute bits
-
- The screen calls that deal with placing characters on the screen refer
- to screen locations using absolute addresses of locations in screen
- memory. This scheme is used for increased efficiency. You can obtain
- information about the absolute screen address of the top left-hand
- corner of the current window and the number of screen addresses between
- successive rows, to figure out screen addresses for your applications.
- For added convenience, there is a call which will accept row and column
- numbers and return the corresponding absolute screen address.
-
- The screen-control system calls are as follows:
-
- NAME : winmax
- ARGS : <none>
- RETURNS: <none>
- ALTERS : .A, .X, .Y
-
- Sets the current window to cover the entire screen.
-
- NAME : winclear
- ARGS : .A = char/color/high-attribute modification flags
- .X = character fill value
- .Y = color fill value
- RETURNS: <none>
- ALTERS : .A, .X, .Y
-
- This call "clears" the current window by filling it with the
- character/color you specify. You can use the char/color/hi-attr to
- limit what gets cleared. [Note: The arguments for this call are slightly
- different in Release #9].
-
- NAME : winset
- ARGS : .A = number of rows in window
- .X = number of columns in window
- sw+0 = absolute screen row of top left corner of window
- sw+1 = absolute screen column of top left corner of window
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Sets the current window to the size you specify. You will get an error
- return if the window will not fit on the screen or of it does not
- contain at least one character. [Note: This call is not implemented in
- Release #9].
-
- NAME : winsize
- ARGS : <none>
- RETURNS: .A = number of rows in window
- .X = number of columns in window
- sw+0 = absolute screen row of top left corner of window
- sw+1 = absolute screen column of top left corner of window
- (sw+2)= screen address of top left corner
- (sw+4)= screen address increment between successive rows on screen
- ALTERS : <none>
-
- Returns information about the current window. [Note: the arguments are
- slightly different in Release #9].
-
- NAME : winput
- ARGS : (sw+0)= absolute screen address to start putting data at
- (sw+2)= character string pointer
- .X = length of character string
- .Y = color
- .A = char/color/high-attribute modification flags
- sw+4 = fill character
- sw+5 = total field length
- RETURNS: <none>
- ALTERS : .A, .X, .Y
-
- Puts text onto the screen. The output region is given by the absolute
- starting screen address and the total field length. This region must be
- contained on one line of the current window, or bad things will happen.
- A pointer to the characters to be printed is given, as well as the
- length of the character array. Control characters in this string are
- ignored; they are poked literally onto the screen, including the null
- character. The length of the character string must be less than or
- equal to the total length of the field. Remaining spaces in the field
- will be filled in with the "fill character".
-
- The color of the total field length will be filled in with "color". You
- can use the "char/color/hi-attr" modification flags to specify what is
- to be changed. If you were to, for example, specify that the colors of
- the field are not to be changed, then the call would execute faster.
-
- NAME : wincolor
- ARGS : .X = new RGBI screen color
- .Y = new RGBI border color
- .A = which colors to change ($80=screen + $40=border)
- RETURNS: .X = resulting RGBI screen color
- .Y = resulting RGBI border color
- ALTERS : .A
-
- Sets the color of the screen and border. You may optionally set one,
- the other, both, or neither. The resulting colors for colors changed,
- and the existing colors for colors unchaned will be returned. Note that
- not all screens have an adjustable color, so the border argument may be
- ignored.
-
- NAME : winpos
- ARGS : .A = row
- .X = column
- RETURNS: (sw+0)= screen memory address of position
- ALTERS : .A, .X, .Y
-
- Given a row and column in the current window, returns the corresponding
- absolute screen memory location for use with other calls. No errors are
- returned, so garbage in, garbage out.
-
- NAME : wincursor
- ARGS : (sw+0)= screen address to place cursor
- .A = enable flag ($ff=cursor-on / $00=cursor-off)
- .Y = color to show cursor in
- RETURNS: <none>
- ALTERS : .A, .X, .Y
-
- Displays or undisplays the cursor at the given screen address. This
- call returns immediately in either case. No errors are returned. Do
- not display anything in or scroll the window while the cursor is being
- displayed, do not display the cursor twice, and do not undisplay the
- cursor twice in a row or bad things will happen. Also, make sure you
- give the same address when undisplaying the cursor as you did when
- displaying the cursor. When the system starts, the cursor will be in
- its undisplayed state (duh!). You also get to specify the color you
- want the cursor to be shown in. The high-attribute bits of this color
- are ignored.
-
- NAME : winscroll
- ARGS : .A = flags: char/color/hi-attr + $08=up + $04=down
- .X = number of rows to scroll up/down
- sw+4 = fill character
- .Y = fill color
- RETURNS: <none>
- ALTERS : .A, .X, .Y
-
- Scrolls the contents of the current window up or down. You can scroll
- any number of rows at a time. After scrolling, the bottom (or top) rows
- will be filled with the fill character and color. You can limit whether
- the characters and/or colors are to be scrolled by using the "flags"
- byte in the usual way. Scrolling only the characters, for example, will
- be twice as fast as scrolling both characters and attributes. Whether
- to scroll up or down is specified also using bits in the "flags" field,
- as indicated in the input arguments above. You can specify scrolling in
- more than one way, and the result will be to scroll in each specified
- direction in turn, in the order up, then down. In the future, scrolling
- left and right may be added to this call. [Note: The arguments and
- semantics of this call are a little different in Release #9].
-
- 2.5. CONSOLE CALLS
-
- The calls in this section refer to the system "console", which includes
- the screen and keyboard. The screen-related calls are at a higher level
- than the calls in the previous section.
-
- NAME : stopkey
- ARGS : <none>
- RETURNS: .CS = stop key pressed
- ALTERS : .A, .X, .Y, errno
-
- Indicates whether the STOP (RUN/STOP) key is currently being held down
- by the user. If so, carry flag is set on return (and clear if not). If
- the stop key is discovered to be pressed by this call, then the keyboard
- buffer will also be cleared.
-
- NAME : getkey
- ARGS : <none>
- RETURNS: .A = keyboard character
- ALTERS : .X, .Y
-
- Waits for the user to type a key (or takes a previous keystroke from the
- keyboard buffer). Regular characters are returned in their regular
- PETSCII codes, but there are many special control keystrokes. They are
- not listed here (yet) because I haven't figured out what all of the
- special codes should be, but all 256 possible character values will be
- covered. Special codes like "page up", etc. should help in
- standardizing control keystrokes for applications. The key code is
- returned in the accumulator. No errors are possible.
-
- NAME : concolor
- ARGS : .A = which colors to modify: $02=character + $01=cursor
- + $80=modify high-attributes of colors
- .X = new RGBI character color
- .Y = new RGBI cursor color
- RETURNS: .X = resulting character color
- .Y = resulting cursor color
- ALTERS : .A
-
- Sets the character and cursor colors to be used by the console for the
- "read" and "write" system calls that refer to files opened to the
- console device. You can use the flags argument to limit what gets
- changed. [Note: flags argument is slightly different in Release #9].
-
- NAME : conpalette
- ARGS : <none>
- RETURNS: sw+0 = main character color
- sw+1 = cursor color
- sw+2 = status character color
- sw+3 = separator character color
- sw+4 = highlight character color
- sw+5 = alert character color
- sw+6 = screen border color
- sw+7 = screen background color
- ALTERS : .A, .X, .Y
-
- Returns the palette of colors that are recommended to be used in
- applications. These colors are chosen by the user in the system
- configuration, so they can be interpreted as being what the user wants
- and expects applications to use. A different selection is made by the
- user for each different screen type, and the palette returned will be
- for the screen type currently in use. The high-attribute bits of these
- colors are valid. Eight colors are included in the palette, and you may
- interpret their meaning according to the application. The suggested
- usages are given in the return arguments listed above.
-
- NAME : conscreen
- ARGS : .A = number of text rows required, minimum
- .X = number of text columns required, minimum
- RETURNS: .A = number of text rows you get
- .X = number of text columns you get
- .CS = error occurred flag (requested size cannot be given)
- ALTERS : .Y, errno
-
- This call selects an appropriate display device, screen, and layout for
- displaying text. You ask for the minimum number of rows and columns you
- require on the screen, and the call returns to you what you receive. If
- the system cannot match your minimum requirements, an error will be
- returned, and the current screen will be unchanged. The clock speed of
- the processor will be changed to match the screen selected, if
- appropriate.
-
- NAME : conpos
- ARGS : .A = row
- .X = column
- RETURNS: .CS = error encountered flag
- ALTERS : .A, .X, .Y
-
- This call will set the screen location that the next console "read" or
- "write" system call will operate from. If the "cursor" position is
- outside the boundaries of the current window on the screen, an error
- will be returned. [Note: this function is not implemented in Release
- #9].
-
- 2.6. PROCESS CONTROL CALLS
-
- This section describes calls that are used to control the execution of
- processes (active programs). From within one program, you can call for
- the execution of another program, have it execute, and then return to
- the calling program. Since only one program is allowed in memory at a
- time, some special problems arise. Also, only rudimentary versions of
- these system calls are implemented in Release #9 and I haven't decided
- completely how they should work. So, this section is a bit tentative.
-
- NAME : exec
- PURPOSE: execute external program as a child process
- ARGS : (zp) = program name of executable
- (zw) = start address of argument vector
- .AY = number of arguments
- [mp] = pointer to far memory volatile storage
- RETURNS: .A = exit code
- .X = number of bytes in "aceExitData" used
- [mp] = pointer to far memory volatile storage
- .CS = error occurred flag
- ALTERS : .Y, errno
-
- Calling this routine will cause a new "frame" to be set up on the
- "system stack" (lowering the available application area memory a
- little), the specified program to be loaded into memory over top of the
- current one, the new program to be executed, the old program to be
- reloaded from whatever disk unit it came from originally upon exit of
- the new program, and control to be returned to the old process with the
- return values from the executed program. This is a complicated procedure
- and many things can go wrong.
-
- The first thing that a process that wants to call another program must
- do is set up the arguments to be passed in. All arguments must be
- null-terminated strings. These arguments are to be put into high
- memory, starting from one less than the location pointed to by
- "aceMemTop" and working downward. It does not matter in which order the
- strings are placed, as long as they are all grouped together. Then,
- immediately below the strings comes the vector of two-byte RAM0 pointers
- that point to the strings. This array must be in order, with the lowest
- entry pointing to the first (zero subscript) string, etc., the second
- highest entry pointing to the last string, and the highest entry
- containing the value $0000. An asciigram follows:
-
- HIGHER ADDRESSES
- | |
- | | <--(aceMemTop)
- +-----------+
- | |
- | string |
- | | : collection of null-terminated strings
- | contents |
- | |
- | |
- +-----------+
- | $0000 | : argv[N] : null argument pointer
- +-----------+
- | strptrN-1 | : argv[N-1]
- +-----------+
- | strptrN-2 | : argv[N-2]
- +-----------+
- . .
- . .
- +-----------+
- | strptr 1 | : argv[1] : first actual argument
- +-----------+
- | strptr 0 | <--(zw) : argv[0] : filename of program to be executed
- +-----------+
- | |
- LOWER ADDRESSES
-
- The first entry should indicate the filename or command name of the
- program being executed, and the subsequent arguments are the actual
- input arguments to the program being called. The address of the first
- argument vector table entry is loaded into (zw), and the number of
- arguments is loaded into .AY. Note that this value also includes the
- command name, so if, for example, you were to call program "wc" to count
- two filenames "hello" and "goodbye", then you would pass an argument
- count of 3. The name pointed to by "argv[0]" does not actually have to
- be the literal command name, but the one pointed to by (zp) does. If a
- relative executable name is given in (zp), then the search path will be
- used to locate the executable. Oh, don't screw up the organization of
- the arguments or bad things will happen; there is no structure checking.
-
- After setting up the arguments, you'll want to set up any redirections
- of stdin, stdout, or stderr you'll be needing. Because there is only
- one open file table in the whole uni-tasking system, you'll have to
- manipulate existing entries using the "fdswap" system call described
- earlier. The open file table is inherited by the child process. Note
- that if it closes any of the open files it inherited, then they are also
- closed to your use also. If the child accidentally leaves open any
- files it opened, they will be closed by the system before you are
- reactivated.
-
- Finally, before the call is made, you have to save any volatile local
- information into "far" memory. All application zeropage and application
- area memory will be modified by the called program, so you must save
- whatever you will need to continue after the return to be able to
- continue. As mentioned earlier, all of the "far" memory that a parent
- program owns will be safe, so you can save your volatile information
- there, in any format you wish. All you have to do is save the pointer
- to the far memory into the [mp] pointer. Upon return of the child
- process, the value you put into [mp] will be restored, and you can then
- restore your volatile information out of far storage. If you wish to
- save no volatile information, then you can just leave garbage in the
- [mp] value, since it will not be interpreted by the system.
-
- Alright, so now you call the "exec" primitive, the child program is
- loaded, executed, and it returns.
-
- At this time, the parent program (that's you) is reloaded from wherever
- it was loaded originally and you are returned to the instruction
- immediately following the "jsr exec", with your processor stack intact
- but the rest of your volatile storage invalid. Even if there is an
- error return (carry flag set), your volatile storage will still need to
- be restored, since the application area may have been overwritten before
- the error was discovered. In the case of an error return, the child
- process will not have been executed. If the system is unable to reload
- the parent program (you), then an error return is given to your parent,
- and so on, as far back as necessary. (This is a minor exception to the
- rule that an error return indicates that a child didn't execute; in this
- case, the child didn't complete).
-
- You are also returned an "exit code", which will have
- application-specific meaning, although standard programs (e.g., shell
- script) interpret the value as: 0==normal exit, anything else==error
- exit. The X register is also set to indicate the amount of
- "aceExitData" that is used, to allow for more complicated return values.
-
- [Note: This call is different in Release #9].
-
- NAME : execsub
- PURPOSE: execute internal subroutine as a separate process
- ARGS : (zp) = address of subroutine
- (zw) = address of argument vector
- RETURNS: .A = exit code
- .X = number of bytes in "aceExitData" used
- .CS = error occurred flag
- ALTERS : .Y, errno
-
- This call is very similar to "exec", except that it calls an internal
- subroutine rather than an external program. Thus, you don't have to
- save or restore your volatile storage, or worry about loading the child
- or reloading the parent. You do, however, set up the arguments and file
- redirections as you would for a full "exec". [Note: this call is
- different in Release #9].
-
- NAME : exit
- PURPOSE: exit current program, return to parent
- ARGS : .A = exit code
- .X = number of bytes in "aceExitData" used
- RETURNS: <there is no return, brah-ha-ha-ha-ha-ha!!!>
- ALTERS : <don't bloody well matter>
-
- This call causes the current program to exit back to its parent. A
- program that exits simply by returning to its environment will give back
- an exit code of 0, which should be interpreted as a normal return. If
- you wish to indicate a special return, you should use some exit code
- other than zero. Many utilities will interpret non-zero error codes as
- actual errors and may abort further operations because of this.
-
- You may set up a return data in "aceExitData", up to 255 bytes worth,
- and load the number of bytes used into .X if you wish. It is
- recommended that the first field of this data be a special identifier
- code so programs that cannot interpret your data will not try. You
- cannot give any far pointers in your return data, since all far memory
- allocated to you will be freed by the system before returning to your
- parent.
-
- NAME : memstat
- PURPOSE: get "far" memory status plus process id
- ARGS : <none>
- RETURNS: .A = current process id
- [sw+0]= amount of "far" memory free
- [sw+4]= total amount of "far" memory
- ALTERS : .X, .Y
-
- This call returns the current process id, the number of bytes of far
- memory currently free, and the total amount of far memory.
-
- 2.7. MISCELLANEOUS CALLS
-
- NAME : utoa
- PURPOSE: convert unsigned 32-bit number to a decimal PETSCII string
- ARGS : .A = minimum length for return string
- .X = zero-page address of 32-bit number
- (sw+0)= pointer to string buffer to store string
- RETURNS: .Y = length of string
- ALTERS : .A, .X
-
- This is a utility call in the kernel. It is really not necessary for it
- to be in the kernel, but so many programs make use of it that it makes
- sense for it to be factored out. You give a pointer to a 32-bit
- unsigned value in zero page memory, a pointer to a buffer to store that
- string that is at least as long as necessary to store the value plus the
- null-character terminator that will be put on the end of the string, and
- a minimum length value for the string. If the number requires fewer
- digits than the minimum length, the string will be padded with spaces on
- the left. Since a 32-bit quantity can only contain an maximum of ten
- decimal digits, the string buffer will only need to be a maximum of
- eleven bytes in size.
-
- NAME : getdate
- PURPOSE: get the current date and time
- ARGS : (.AY) = address of buffer to put BCD-format date into
- RETURNS: <none>
- ALTERS : .A, .X, .Y
-
- Returns the current date and time in the BCD format described in the
- paragraph on "aceDirentDate". It puts it into the at-least-eight-byte
- storage area pointed to by (.AY).
-
- NAME : setdate
- PURPOSE: set the current date and time
- ARGS : (.AY) = address of date in BCD format
- RETURNS: <none>
- ALTERS : .A, .X, .Y
-
- Sets the current date and time in the system. (.AY) points to the BCD
- date string whose format is discussed in the paragraph on
- "aceDirentDate". No validity checking is performed on the date given.
-
- NAME : cmdopen
- PURPOSE: open command channel to Commodore disk drives
- ARGS : (zp) = device name
- RETURNS: .A = file descriptor number
- .CS = error occurred flag
- ALTERS : .X, .Y, errno
-
- This "cmd" set of system calls really should not be present, but they
- will be needed until the full complement of disk-utility system calls
- are implemented. It is really not recommended that any application
- program rely on these calls being around very long. This call opens the
- command channel on the named device (standard ACE device name string)
- and returns the file descriptor number to use thereafter.
-
- NAME : cmdclose
- PURPOSE: close command channel to Commodore disk drives
- ARGS : .A = file descriptor number
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- This closes an opened command channel to a disk drive. Closing the
- status will NOT affect any other open files on the disk unit at the
- time.
-
- NAME : cmdsend
- PURPOSE: send command over command channel to Commodore disk drives
- ARGS : .X = file descriptor number
- (.AY) = pointer to null-terminated command string
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- This sends a command string to a disk drive. Since a null-terminated
- string representation is used, not all Commodore/CMD-DOS commands can be
- sent, but the important ones can be.
-
- NAME : cmdstatus
- PURPOSE: receive current status from command channel of Commodore disk drives
- ARGS : .X = file descriptor number
- (.AY) = pointer to buffer for null-terminated status string
- RETURNS: .A = status code in binary
- .CS = error occurred
- ALTERS : .X, .Y, errno
-
- This returns the status of a disk drive in a string as well as the
- binary disk status number in the accumulator. The given status buffer
- must be at least 50 or so characters long (whatever is the longest
- possible disk status string).
-
- 3. USER PROGRAM ORGANIZATION
-
- The ACE system itself is written using the Buddy-128 assembler, so it is
- recommended that applications be written in this also. User programs
- for ACE have a very simple structure. Here is the standard "hello,
- world" example program written in Buddy assembler for ACE:
-
- -----=-----
- .seq acehead.s
- .org aceAppAddress
- .obj "@0:hello"
-
- jmp main
- .byte aceID1,aceID2,aceID3
-
- main = *
- lda #<helloMsg
- ldy #>helloMsg
- sta zp+0
- sty zp+1
- lda #<helloMsgEnd-helloMsg
- ldy #>helloMsgEnd-helloMsg
- ldx #stdout
- jsr write
- rts
-
- helloMsg = *
- .asc "Hello, cruel world."
- .byte 13
- helloMsgEnd = *
- -----=-----
-
- This would normally be put into a file called "hello.s". The ".s"
- extension means that this is an assembler file (a la Unix). The first
- thing this program does is include the "acehead.s" file. This is the
- Buddy assembler file that contains the header information declarations
- required to access the ACE system interface. The next line gives the
- start address to start assembling to; it must be "aceAppAddress", which
- is the address that ACE will load the program at. The next line is a
- directive to the assembler to write the executable code to a
- Commodore-DOS "PRG" file named "hello". This will be the command to
- enter at the ACE shell prompt.
-
- The next six bytes of object code (which are the first six bytes of a
- program) describe the header required by ACE programs. The first three
- bytes must be a JMP to the main routine of the program. The next three
- bytes must have the values "aceID1", "aceID2", and "aceID3",
- respectively. And that's all there is to it. The rest of the program
- can be organized however you want it to be.
-
- In this example, we set up the arguments for the "write" system call to
- print the string "Hello, cruel world." plus a carriage return to
- standard output. Note that this string does not need a terminating null
- ($00) character since the write call takes a buffer length. The program
- then returns to its calling environment via an RTS. This will cause an
- implied "exit(0)" to be performed by the system, returning to the parent
- program.
-
- Although this program does not take advantage of this, an application
- program may use zero-page locations $0002 through $007f for storage
- without fear of having the storage trodden upon by the system. Also,
- the processor stack may be used from the point it was at upon entry to
- your program all the way down to the bottom. I will be doing something
- about ensuring there is always enough processor space for an application
- to use in the future, but for now, all applications have to share the
- single page of processor stack storage.
-
- Finally, an application program starts at location "aceAppAddress" (plus
- six) and is allowed to use memory all the way up to one byte less than
- the address pointed to by "aceMemTop" for its own purposes. Currently,
- this amount of space is on the order of magnitude of about 24K. This
- will be increased in the future.
-
- Application programs are not to access I/O features or even change the
- current memory configuration during execution. All I/O and unusual
- contortions must be performed by ACE system calls; otherwise, we could
- end up in as bad a shape as MESS-DOS.
-
- 4. CONCLUSION
-
- Cool, eh?
- =============================================================================
- Looking Ahead: (Learned my lesson about "In The Next Issue" :-) (re: the
- mouse article etc....) )
-
- Either a Multi-Tasking article or a look at the Internals of Ace.
-
- More graphics techniques.
-
- Answers to the Trivia in this issue.
-
- More articles and other information.
-
- (Sorry that this is a little bit more vague than last time - Just have some
- authors actually finding real jobs, and others that forgot to include what
- they were going to do for the next issue.)
-