magazines:chacking11
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
— | magazines:chacking11 [2015-04-17 04:34] (current) – created - external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | < | ||
+ | ######## | ||
+ | ################## | ||
+ | ###### | ||
+ | ##### | ||
+ | ##### #### #### ## ##### | ||
+ | ##### ## ## #### ## | ||
+ | ##### | ||
+ | ##### ## ## ######## | ||
+ | ##### #### #### #### #### ##### | ||
+ | ##### ## | ||
+ | ###### | ||
+ | ################## | ||
+ | ######## | ||
+ | |||
+ | ------------------------------------------------------------------------------- | ||
+ | </ | ||
+ | ====== Table of Contents ====== | ||
+ | < | ||
+ | |||
+ | |||
+ | Features | ||
+ | 6. Speed up RAMLink transfers with the Double-DMA Technique | ||
+ | (Reference: dbldma) | ||
+ | RAMLink Designer Mark Fellows and Technical Editor Doug Cotton of | ||
+ | CMD describe a way of using a Commodore REU to increase transfer | ||
+ | rates of the CMD RAMLink to one-half the speed of the REU transfer | ||
+ | rate. | ||
+ | 8. The Graphics Toolbox by Stephen Judd | ||
+ | (Reference: toolbox) | ||
+ | To add another tool to our toolbox, Stephen details a new algorithm | ||
+ | for drawing ellipses. | ||
+ | a previous column that will enable it to draw perfect circles of any | ||
+ | radius is discussed, as well as details on using logarithms to | ||
+ | perform division. | ||
+ | 10. Design and Implementation of an Advanced Text Editor by Craig Bruce | ||
+ | (Reference: zedace) | ||
+ | Peer into the internal organization and implementation of an | ||
+ | advanced text editor/word processor for the ACE environment. | ||
+ | Relevant data structure, global variables, display maintenance, | ||
+ | text " | ||
+ | detailed. | ||
+ | |||
+ | Columns | ||
+ | 4. Hi Tech Trickery by George Taylor | ||
+ | (Reference: trick) | ||
+ | Don't let anyone ever tell you the SID chip is only capable of 4 bit | ||
+ | sample playback. | ||
+ | technique to increase the SID's resolution. | ||
+ | 12. Hacking Graphics by Rick Mosdell | ||
+ | (Reference: gfx) | ||
+ | Dig into this overview on how to set up the VIC-II to display Doodle | ||
+ | and KOALA format pictures. | ||
+ | formats are referenced. | ||
+ | |||
+ | Departments | ||
+ | 1. The (cough, | ||
+ | (Reference: editor) | ||
+ | 2. Input/ | ||
+ | (Reference: io) | ||
+ | 3. Newsfront | ||
+ | (Reference: news) | ||
+ | 5. Hacking the Mags | ||
+ | (Reference: mags) | ||
+ | 7. UseNuggets | ||
+ | (Reference: usenet) | ||
+ | 9. Hack Surfing | ||
+ | (Reference: surf) | ||
+ | 11. Commodore Trivia | ||
+ | (Reference: trivia) | ||
+ | 13. ? DS, DS$: rem The Error Channel | ||
+ | (Reference: error) | ||
+ | 14. The Next Hack | ||
+ | (Reference: next) | ||
+ | |||
+ | ------------------------------------------------------------------------------- | ||
+ | |||
+ | </ | ||
+ | ====== Commodore Hacking Legal Notice ====== | ||
+ | < | ||
+ | |||
+ | Commodore and the respective Commodore product names are trademarks or | ||
+ | registered trademarks of ESCOM GmbH. Commodore hacking is in no way | ||
+ | affiliated with ESCOM GmbH, owners of said trademarks. | ||
+ | published 4 times yearly by: | ||
+ | |||
+ | Brain Innovations Inc. | ||
+ | 602 N. Lemen | ||
+ | Fenton MI 48430 | ||
+ | |||
+ | The magazine is published on on-line networks free of charge, and a nominal | ||
+ | fee is charged for alternate mediums of transmission. | ||
+ | |||
+ | Permission is granted to re-distribute this " | ||
+ | entirety for non-profit use. A charge of no more than US$5.00 may be | ||
+ | charged by redistribution parties to cover printed duplication and no more | ||
+ | than US$10.00 for other types of duplication to cover duplication and media | ||
+ | costs for this publication. | ||
+ | compilation, | ||
+ | part of a non-profit compilation. | ||
+ | |||
+ | This publication, | ||
+ | various elements, is copyright(c) 1995 by Brain Innovations, | ||
+ | unless otherwise noted. | ||
+ | copyrights pertaining to the individual work's contents. | ||
+ | redistribution rights to individual works, please contact the author of said | ||
+ | work or Brain Innovations, | ||
+ | |||
+ | Brain Innovations, | ||
+ | editorial, article, or program listing content. | ||
+ | |||
+ | ------------------------------------------------------------------------------- | ||
+ | |||
+ | </ | ||
+ | ====== Commodore Hacking Information ====== | ||
+ | < | ||
+ | |||
+ | |||
+ | Commodore Hacking is published via the Internet 4 times yearly, and is | ||
+ | presented in both ISO-8859-1 and HTML versions. | ||
+ | be found at the Commodore Hacking Home Page | ||
+ | (http:// | ||
+ | (ftp:// | ||
+ | |||
+ | In addition, the Commodore Hacking mail server can be used to retrieve each | ||
+ | issue. | ||
+ | mail message: | ||
+ | |||
+ | To: brain@mail.msen.com | ||
+ | Subject: MAILSERV | ||
+ | Body of Message: | ||
+ | |||
+ | help | ||
+ | catalog | ||
+ | send c=hacking11.txt | ||
+ | quit | ||
+ | |||
+ | To subscribe to the Commodore Hacking and receive new issues as | ||
+ | they are published, add the following command to you MAILSERV message | ||
+ | prior to the quit command: | ||
+ | |||
+ | subscribe c=hacking Firstname Lastname msglen | ||
+ | |||
+ | (msglen is largest size of file in kilobytes you can receive in an email | ||
+ | message. | ||
+ | |||
+ | example: | ||
+ | |||
+ | subscribe c=hacking Jim Brain 100 | ||
+ | |||
+ | Although no fee is charged for this magazine, donations are gladly accepted | ||
+ | from corporate and individual concerns. | ||
+ | any administrative costs, subscribe to publications for review, and | ||
+ | compensate the individual authors contributing to this issue. | ||
+ | |||
+ | Any persons wishing to author articles for inclusion in Commodore Hacking are | ||
+ | encouraged to view the submission guidelines on the WWW | ||
+ | (http:// | ||
+ | server (send c-hacking-submit.txt). | ||
+ | |||
+ | ============================================================================ | ||
+ | |||
+ | </ | ||
+ | ====== Reading C=Hacking ====== | ||
+ | < | ||
+ | |||
+ | Starting with Issue 11 of Commodore Hacking, the new QuickFind indexing | ||
+ | system is utilized to aid readers of the text version in navigating the | ||
+ | magazine. | ||
+ | magazine, a word prefixed with a special string is present. | ||
+ | title of this article for an example. | ||
+ | article is mentioned, it will be followed by a reference string. | ||
+ | example, if we mentioned this article, we would add (Reference: rch) after | ||
+ | the name. By using your favorite editor' | ||
+ | for the string after the word " | ||
+ | string, will move you directly to the article of choice. | ||
+ | the next article in the magazine, search only for the magic prefix string. | ||
+ | |||
+ | Some handy indexing strings possibly not referenced anywhere are: | ||
+ | |||
+ | top top of issue | ||
+ | bottom | ||
+ | contents table of contents | ||
+ | legal legal notice | ||
+ | |||
+ | For those with access to a UNIX system, the command " | ||
+ | run on the issue, which will result in all the article titles being | ||
+ | printed. | ||
+ | |||
+ | A slightly different magic prefix string "# | ||
+ | sub-topics or main heading in articles. | ||
+ | differs depending on article content. | ||
+ | (Reference: io), the text after the magic prefix will either be " | ||
+ | comment, or " | ||
+ | the prefix indicates the ordinal of that heading or sub-topic in the | ||
+ | article. | ||
+ | a sub-topic reference will be indicated. | ||
+ | be written as " | ||
+ | |||
+ | As time goes on, the role of this indexing system will be expanded and | ||
+ | changed to ease navigation of the text version, but minimize the clutter | ||
+ | added by these extra items. | ||
+ | |||
+ | ============================================================================ | ||
+ | |||
+ | </ | ||
+ | ====== The Hacking Editor ====== | ||
+ | < | ||
+ | by Jim Brain (brain@mail.msen.com) | ||
+ | |||
+ | Two new faces appear in this month' | ||
+ | while the other is its new look. I hope neither causes anyone to worry about | ||
+ | the content of the magazine. | ||
+ | to provide leading edge technical information about the Commodore computers | ||
+ | we all know and love. The magazine will continue to cater to the Commodore | ||
+ | computer programmer, whether it be in the areas of sound, graphics, algorithms, | ||
+ | disk media access, or communications. | ||
+ | |||
+ | However, the role of the magazine continues to expand. | ||
+ | many people other than CBM programmers read the magazine, and programmers have | ||
+ | requested other information besides technical content be included in the | ||
+ | magazine. | ||
+ | |||
+ | o " | ||
+ | | ||
+ | | ||
+ | will alert readers to specific issues that may be of interest. | ||
+ | |||
+ | o " | ||
+ | and user up to date on developments in the Commodore community. | ||
+ | | ||
+ | of the newest technologies affecting the CBM line. | ||
+ | |||
+ | o "The Error Channel" | ||
+ | of fixing errors in earlier issues. | ||
+ | in most issues, but it will be here just in case. | ||
+ | |||
+ | o " | ||
+ | for comments and concerns. | ||
+ | | ||
+ | This spot will detail which is which and why. | ||
+ | |||
+ | o Article separators. | ||
+ | | ||
+ | of the article. | ||
+ | |||
+ | o Smaller size. The last issue was over 400kB in size, which generated | ||
+ | many complaints. | ||
+ | more issues can be published. | ||
+ | two sides of a 1541 disk, a 1571 disk, or a 1581 disk. | ||
+ | |||
+ | o Stable publication dates. | ||
+ | hard for the previous editor to maintain a schedule, so no blame is laid, | ||
+ | but the magazine does need some stability. | ||
+ | I am striving to publish C=Hacking quarterly, with the following schedule: | ||
+ | | ||
+ | Publication Date Submission Deadline | ||
+ | March, 1996 | ||
+ | June, 1996 May 10, 1996 | ||
+ | September, 1996 | ||
+ | December 1996 | ||
+ | |||
+ | If article submissions keep up, a switch to bi-monthly publication might | ||
+ | be warranted, but I won't get too far ahead. | ||
+ | |||
+ | o Fully HTML-ized version of the magazine. | ||
+ | | ||
+ | | ||
+ | this and older issue at URL: http:// | ||
+ | |||
+ | Many people have compared Commodore Hacking to the defunct _Transactor_ | ||
+ | magazine, which is encouraging. | ||
+ | appeal of Commodore Hacking. | ||
+ | |||
+ | Although many of you know me or of me through previous Commodore work, this | ||
+ | is my first editorship, so please comment on the changes I have made and what | ||
+ | your opinions on each are. As the magazine is for you, the reader, it is | ||
+ | always important to keep the reader happy. | ||
+ | |||
+ | Sadly, some things, like the WWW browser for C=Hacking, did not get done, | ||
+ | but there is always next time. | ||
+ | |||
+ | Enjoy YOUR magazine, | ||
+ | |||
+ | Jim Brain (brain@mail.msen.com) | ||
+ | editor | ||
+ | |||
+ | ============================================================================ | ||
+ | |||
+ | </ | ||
+ | ====== Input/Ouput ====== | ||
+ | < | ||
+ | |||
+ | Obviously, Commodore Hacking depends on the comments and article submissions | ||
+ | from the Commodore community to flourish. | ||
+ | let's not forget those comments. | ||
+ | is made to address concerns in them. Address any comments, concerns, or | ||
+ | suggestions to: | ||
+ | |||
+ | Commodore Hacking | ||
+ | 602 N. Lemen | ||
+ | Fenton, MI 48430 | ||
+ | brain@mail.msen.com (Internet) | ||
+ | |||
+ | #(A)c: Need Samples of Samples | ||
+ | |||
+ | From: " | ||
+ | |||
+ | Dear C=Hacking, | ||
+ | Hey. Just writing to mention something I'd like to see in C=Hacking, if | ||
+ | you can find someone to write about it. I am interested in knowing more | ||
+ | about how samples work on the 64, how to play, etc. | ||
+ | ----- | ||
+ | | ||
+ | Si vales, valeo | ||
+ | |||
+ | #(A)r: | ||
+ | Your wish is granted. | ||
+ | (Reference: trick) by George Taylor for some insight into playing | ||
+ | samples. | ||
+ | |||
+ | #(A)c: You Index, I Index, We all Index | ||
+ | |||
+ | From: coyote@wakko.gil.net | ||
+ | |||
+ | Dear C=Hacking, | ||
+ | I would like to offer an idea for the Chacking mag. Every now and then | ||
+ | I'll come across a reference to an article in this or that Chacking Issue. | ||
+ | I run Zed and load that issue in (Thanks Mr Bruce) and start hunting for | ||
+ | the start of the article. | ||
+ | |||
+ | This process would be made a lot easier if Chacking used a method of | ||
+ | indexing I have seen used in several publications. | ||
+ | |||
+ | It involves the search function of most text editors. A 2/3/4 ? letter | ||
+ | code (with a delimiter char to prevent unintentional matches) that the | ||
+ | reader uses to find the beginning of the article. | ||
+ | |||
+ | (Outline of suggestion deleted) | ||
+ | |||
+ | I would like to add a personal thanks for all your efforts on behalf of | ||
+ | the C= community. | ||
+ | |||
+ | Al Anger | ||
+ | 13841 SW 139 Ct. | ||
+ | Miami Fl. 33186 | ||
+ | (305) 233-4689 | ||
+ | |||
+ | #(A)r: | ||
+ | Fire up that search function in your favorite editor. | ||
+ | contains the QuickFind indexing system that should fit your needs. | ||
+ | " | ||
+ | indexing system. | ||
+ | personal thanks. | ||
+ | |||
+ | #(A)c: Are We Talking the Same Language? | ||
+ | From: Jack Vander White < | ||
+ | |||
+ | Dear C=Hacking, | ||
+ | Noticed something that may be a potential problem and thought I would | ||
+ | let you know. | ||
+ | | ||
+ | Way back when hacking mag started I didn't have Internet access. the first | ||
+ | couple of issues were sent to me by fellows who had downloaded them and in | ||
+ | downloading had set their terms to translate them to PETSCII. This of | ||
+ | course changed the coding in the uuencoding parts of the magazine and made | ||
+ | them decode improperly. | ||
+ | |||
+ | Since then I have my own access and have re-downloaded them and posted | ||
+ | them on my BBS in the original straight ASCII so that those who download | ||
+ | them can uudecode the relevant parts and then translate the text for | ||
+ | reading. | ||
+ | | ||
+ | Since different Terminal Programs are using different Translation tables | ||
+ | I can see all kinds of problems in this for the average user. | ||
+ | | ||
+ | Any comment???? | ||
+ | | ||
+ | Jack VW | ||
+ | |||
+ | #(A)r: | ||
+ | The HTML version of Commodore Hacking utilizes the ISO-8859-1 text | ||
+ | encoding standard, while the text version utilizes its 7-bit subset, | ||
+ | commonly called ASCII. | ||
+ | problem, as text uses but a nominal set of characters which can be | ||
+ | translated between PETSCII and ASCII. | ||
+ | uucode format uses more characters, which may or may not be | ||
+ | translated correctly. | ||
+ | in the text version, the files embedded in a Commodore Hacking issue | ||
+ | should be uudecoded prior to converting the file to anoy alternate | ||
+ | format. | ||
+ | |||
+ | ============================================================================ | ||
+ | |||
+ | </ | ||
+ | ====== Newsfront ====== | ||
+ | < | ||
+ | |||
+ | * Although not new news, Some still may not know that Creative Micro Designs, | ||
+ | Inc., is currently designing the Super64CPU accelerator. | ||
+ | | ||
+ | to execute programs at either 10MHz or 20MHz (actually, 9 and 18 MHz, | ||
+ | | ||
+ | which is object code compatible with the 6502/ | ||
+ | in the Super Nintendo Entertainment System as well as other products, can | ||
+ | be switched between 6502 emulation mode and " | ||
+ | the following: | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | The unit is scheduled for production in February, 1996, and will cost | ||
+ | | ||
+ | |||
+ | * The following information was relayed to the USENET newsgroup comp.sys.cbm | ||
+ | by Jack Vanderhite, editor and publisher of COMMODORE CEE disk magazine: | ||
+ | |||
+ | Rather than reply to all the messages asking about DIEHARD I will tell | ||
+ | all what has been happening over the last few days. | ||
+ | |||
+ | Brian Crosthwaite, | ||
+ | Commodore CEE this week with the following form letter faxed to each of | ||
+ | us: | ||
+ | ----------- | ||
+ | | ||
+ | Diehard, the Flyer for commodore 8bitters is planning to cease | ||
+ | publication and we are looking to transfer our subscription fulfillment. | ||
+ | Our number of outstanding subscribers is approximately 8,400 and I | ||
+ | would be willing to throw in the balance of the list, totaling | ||
+ | approximately 12,000. | ||
+ | |||
+ | Please call me at (xxx)xxx-xxxx if you are interested in acquiring these | ||
+ | readers and names. | ||
+ | | ||
+ | Sincerely, | ||
+ | | ||
+ | Brian L. Crosthwaite | ||
+ | Publisher | ||
+ | | ||
+ | ---------- | ||
+ | | ||
+ | Each of us did contact Brian for further details. They are bleak. The | ||
+ | total number of paper issues due to subscribers is approximately 64,000. | ||
+ | This does not count the approximately 1,200 spinner subscribers which | ||
+ | would make approximately 10,000 disks due. | ||
+ | | ||
+ | The cost of publishing alone would amount to approximately $100,000 for | ||
+ | printing, layout, disks, ,mail cost, etc. Not taking into account the | ||
+ | cost of articles, etc. | ||
+ | | ||
+ | when asked about money Brian' | ||
+ | gone." | ||
+ | |||
+ | a further complication is that Tom Netsel told me last week that General | ||
+ | Media says that Brian has assumed the obligation to deliver the balance | ||
+ | of the Gazette subscriptions. I questioned Brian about this. Brian says | ||
+ | that general media faxed him the terms of transference of the | ||
+ | obligation and that he faxed back an acceptance of the terms. | ||
+ | have not seen the actual faxes involved it does sound like offer and | ||
+ | acceptance of a binding contract from here. | ||
+ | | ||
+ | Obviously, all of us have rejected this offer. I have been told that | ||
+ | there is an issue of Diehard at the printers, probably printed. | ||
+ | However, the printing bill alone is over $8,000 plus the cost | ||
+ | of mailing. Since there is no money it sits there. | ||
+ | | ||
+ | If anyone were willing to assume the total obligations they would have | ||
+ | to assume a liability of well over $100,000 over the next year before | ||
+ | any returns from renewals would even make a dent in this huge | ||
+ | obligation. | ||
+ | | ||
+ | Please Note: I am putting this out as a public message. This is ALL I | ||
+ | know. | ||
+ | |||
+ | Please do not come back at me asking questions. I have nothing more I can | ||
+ | add to this. | ||
+ | | ||
+ | Jack VW | ||
+ | | ||
+ | So, if you have outstanding issues of dieHard due you, as the editor | ||
+ | | ||
+ | the dieHard " | ||
+ | |||
+ | * The LOADSTAR disk magazine has been recently purchased from Softdisk | ||
+ | | ||
+ | owned by J and F Publishing, a corporation founded by Mr. Tucker and Mrs. | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | In related news, J and F Publishing has agreed to fulfill the remainder | ||
+ | of the outstading dieHard " | ||
+ | | ||
+ | is commendable that these subscriptions will be fulfilled with | ||
+ | | ||
+ | for every two issues of the Spinner, as the Spinner was a single | ||
+ | disk, whereas LOADSTAR is double that. No word has been heard yet on | ||
+ | the fate of dieHard paper subscriptions. | ||
+ | | ||
+ | | ||
+ | |||
+ | * For those people wishing to use the Internet with their Commodore 64, | ||
+ | only to find out that the local Internet Service Provider (ISP) only | ||
+ | | ||
+ | | ||
+ | | ||
+ | been developed by Daniel Dallmann | ||
+ | | ||
+ | via the Internet (ftp:// | ||
+ | means complete, but does include the basic TCP/IP stack, the SLIP driver, | ||
+ | and a rudimentary Telnet application. | ||
+ | |||
+ | * Another Commodore hardware/ | ||
+ | | ||
+ | and BB units (BBGRAM, BBRTC, and BBGRam), PPI published an online catalog | ||
+ | that users can retrieve via the C=Hacking WWW Site | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | which has the basic 6551 functionality with the addition of switch | ||
+ | | ||
+ | | ||
+ | |||
+ | * PPI has one more trick up its sleeve. | ||
+ | the newest version of Nick Rossi' | ||
+ | | ||
+ | |||
+ | Novaterm 9.6 is a complete terminal emulation program on cartridge for | ||
+ | the C64. Novaterm has several features such as 80 column ANSI on a stock | ||
+ | C64, and compatibility with CommPort, RAMDrive, BBGRam, and many other | ||
+ | hardware devices. Just connect a BBGRam, and Novaterm can use it as a | ||
+ | " | ||
+ | downloading files. Definately the perfect setup for Internet usage. And | ||
+ | since Novaterm is in cartridge form, the program loads in seconds, not | ||
+ | minutes. Novaterm 9.6 is the latest version programmed by NICK ROSSI. | ||
+ | Includes autoboot switch. | ||
+ | |||
+ | ============================================================================ | ||
+ | |||
+ | </ | ||
+ | ====== Hi Tech Trickery: Sample Dither ====== | ||
+ | < | ||
+ | by George Taylor (yurik@io.org) | ||
+ | |||
+ | #(A): Introduction | ||
+ | |||
+ | You may know of dithering in graphics. | ||
+ | colors are used to simulate more. This is done by randomly arranging the | ||
+ | pixels so they blend at a distance, creating an average of the shades. | ||
+ | Here, screen space is being averaged, and more shades are being produced. | ||
+ | In playing samples, time is being averaged, and more bits are being produced. | ||
+ | |||
+ | #(A): Dithering Sound | ||
+ | |||
+ | Let's say we do the following: | ||
+ | |||
+ | lda #8 | ||
+ | sta $d418 This code toggles the low bit of the output. | ||
+ | lda #9 | ||
+ | sta $d418 | ||
+ | |||
+ | Over an average of time, this is the same as: | ||
+ | |||
+ | lda #8.5 But we can't really do this. | ||
+ | sta $d418 | ||
+ | |||
+ | This idea can be used to easily do 5 bit sound. | ||
+ | 5 bit sample, shift right, then add 0. If bit 0 was high, | ||
+ | it will increment the 4 bit number. | ||
+ | toggling bit 0, it will average out to give half a bit. | ||
+ | |||
+ | #(A): Is There a Catch? | ||
+ | |||
+ | There is one drawback though. | ||
+ | frequency square wave it resembles. | ||
+ | rate so this can't be heard. | ||
+ | 5th bit, so you must double the sample rate. In order to play 8.5, for | ||
+ | example, you must play 8 and then 9, so the 8 and 9 must take half the normal | ||
+ | time, or your sample will play too slow. | ||
+ | One other problem is that there is the possibility of overflow. | ||
+ | case you can use hard clipping on the signal. | ||
+ | sample 31 will be played at 16, so instead play 15. | ||
+ | |||
+ | This is actually called pulse width modulation. | ||
+ | illustrating sample dithering. | ||
+ | even with one bit. To do this, take the 16 bit sample, add a 12 bit random | ||
+ | number, then play the high 4 bits of this result. | ||
+ | problem as mentioned above. | ||
+ | |||
+ | @(A): How Is This Like Pulse Width Modulation? | ||
+ | |||
+ | The random number range is proportional to the 16 bit sample. | ||
+ | number is high, then it is very likely the 0 bit (toggle bit) is high. It is | ||
+ | the random number which allows the toggle bit to change. | ||
+ | bit sound with 16db signal to noise ratio. | ||
+ | |||
+ | There are some more advanced technical issues to this. The kind of random | ||
+ | number you choose affects the results. | ||
+ | for perfect linearity (ie., for no distortion). | ||
+ | of random numbers in the sequence, and does not affect the probability | ||
+ | distribution, | ||
+ | tradeoff between added noise and linearity. | ||
+ | in my demo, which is non-filtered random numbers, and it's ok but I can | ||
+ | still hear some noise pumping. | ||
+ | |||
+ | #(A): Conclusion | ||
+ | |||
+ | Enjoy the ditherdigi! | ||
+ | |||
+ | #(A)5bit: Listing One: 5 bit play routine | ||
+ | |||
+ | Memory map: | ||
+ | 3: start page of sample | ||
+ | 4: end page of sample | ||
+ | 5: | ||
+ | fb,fc: pointer to sample | ||
+ | |||
+ | start lda 3 | ||
+ | sta $fc | ||
+ | lda #0 | ||
+ | sta $fb ; initialize sample pointer | ||
+ | lda #$b | ||
+ | sta $d011 ; blank screen for better timing | ||
+ | sei ; disable interrupts for better timing | ||
+ | play lda ($fb),y | ||
+ | lsr | ||
+ | sta $d418 ; push sample | ||
+ | ldx 5 | ||
+ | d dex | ||
+ | bne d | ||
+ | pha | ||
+ | nop | ||
+ | adc #0 | ||
+ | cmp #$10 | ||
+ | beq s1 | ||
+ | sta $d418 | ||
+ | bpl s | ||
+ | s1 nop | ||
+ | nop | ||
+ | nop | ||
+ | s pla | ||
+ | ldx 5 | ||
+ | d1 dex | ||
+ | bne d1 | ||
+ | iny | ||
+ | bne play | ||
+ | inc fc | ||
+ | lda fc | ||
+ | cmp 4 | ||
+ | bne play | ||
+ | lda #$1b | ||
+ | sta $d011 | ||
+ | cli | ||
+ | end rts | ||
+ | |||
+ | #(A): References | ||
+ | |||
+ | Consult the proceedings of the ACM for further info on digi dithering. | ||
+ | |||
+ | ============================================================================ | ||
+ | |||
+ | </ | ||
+ | ====== Hacking the Mags ====== | ||
+ | < | ||
+ | |||
+ | Not everything good and/or technical comes from Commodore Hacking, which is | ||
+ | as it should be. (I still think we have the most, though...) | ||
+ | spotlight some good and/or technical reading from the other Commodore | ||
+ | publications. | ||
+ | |||
+ | If you know of a magazine that you would like to see summarized here, let | ||
+ | C=Hacking know about it. These summaries are only limited by Commodore | ||
+ | Hacking' | ||
+ | publications available. | ||
+ | complimentary copies of their publications for review. | ||
+ | |||
+ | #(A): COMMODORE CEE | ||
+ | | ||
+ | | ||
+ | I/O and/or memory maps for the VIC, 64, 128, and PET computers. | ||
+ | | ||
+ | final compilation of the Commodore 64 Prorammer' | ||
+ | of interest to Commodore Haking readers. | ||
+ | | ||
+ | list of all the CSG produced IC numbers with descriptions. | ||
+ | files are also available on the Internet, if you have access. | ||
+ | those who don't know where to look or for those without access, the | ||
+ | | ||
+ | | ||
+ | | ||
+ | menu program, as the current one is somewhat hard to navigate. | ||
+ | |||
+ | #(A): Commodore World | ||
+ | Issue 10 just arrived at the computer room, with a snazzy front cover. | ||
+ | Slick paper aside, the picture of Al Anger' | ||
+ | | ||
+ | for the Super 64 CPU accelerator are present. | ||
+ | mods, you can't miss page 4, which shows some other Al Anger hacked | ||
+ | | ||
+ | | ||
+ | | ||
+ | issue details the high level routines, while #11 will tackle the low level | ||
+ | disk I/O. Maurice Randall goes over event handling in GEOS, while Al Anger | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | those abstract graphics sprinkled throughout the mag? There' | ||
+ | wrong with them, but some look like those psycho-analyst inkblot test | ||
+ | | ||
+ | |||
+ | #(A): Driven | ||
+ | | ||
+ | help those Internet " | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | make for good reading, but the best (in our opinion) was the pessimism | ||
+ | | ||
+ | that modem or SCSI drive was for a Commodore? | ||
+ | |||
+ | #(A): LOADSTAR | ||
+ | Issue 138 just finished loading on the 1581 disk drive, and the disk is | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | a month off from the LOADSTAR letter in #28, but is expected back next | ||
+ | | ||
+ | | ||
+ | |||
+ | #(A): LOADSTAR 128 | ||
+ | In Issue 29, Fender apologizes for not paying enough attention to the 800 | ||
+ | | ||
+ | pause program on the issue, but the rest is pretty light stuff, not to knock | ||
+ | | ||
+ | |||
+ | #(A): Vision | ||
+ | |||
+ | In Issue 7, Rick Mosdell has an article on graphics formats, updated and | ||
+ | | ||
+ | | ||
+ | also presented. | ||
+ | | ||
+ | | ||
+ | |||
+ | Other magazines not covered in this rundown include _The Underground_, | ||
+ | _Gatekeeper_, | ||
+ | as those C=Hacking is simply not aware of. As soon as we can snag a copy of | ||
+ | any of these, or get the foreign language ones in English :-), we will give | ||
+ | you the scoop on them. | ||
+ | |||
+ | ============================================================================ | ||
+ | </ | ||
+ | ====== Speed up RAMLink transfers with the Double-DMA Technique ====== | ||
+ | < | ||
+ | by Doug Cotton (cmd-doug@genie.com) and Mark Fellows | ||
+ | |||
+ | #(A): Introduction | ||
+ | |||
+ | When CMD designed the RAMLink, we tried to make the system as fast as possible, | ||
+ | but costs and complexity prohibited us from duplicating the operation of the | ||
+ | DMA operation found in the Commodore RAM Expansion Unit (REU), | ||
+ | controller found in the REU is a very complex item that allows the REU to | ||
+ | transfer one byte per 1 MHz CPU clock cycle (1 microsecond). | ||
+ | hand, the RAMLink uses the 6510/8502 CPU load and store operations to transfer | ||
+ | memory from the RAMLink memory to main memory. | ||
+ | and RAMDOS, the difference is not noticeable, because although the RAMLink | ||
+ | transfer is slower, RAMDOS continually pages its code in and out of main | ||
+ | memory, effectively slowing its effective transfer speed down significantly. | ||
+ | |||
+ | But, what if the programmer isn't using RAMDOS? | ||
+ | becomes an issue. | ||
+ | of a byte, while the REU does it in 1. This is significant. | ||
+ | user owns both a RAMLink and an REU, there is a way to boost the transfer rate | ||
+ | of the RAMLink via software. | ||
+ | |||
+ | #(A): Double-DMA Description | ||
+ | |||
+ | Basically, the process is quite simple. | ||
+ | transfe memory at 1 byte/ | ||
+ | memory from the RAMLink to main memory. | ||
+ | remember that the normal RL-DOS transfer routines use the CPU to perform the | ||
+ | memory transfer. | ||
+ | mapped into main memory. | ||
+ | utilize the Double-DMA technique, the programmer simply makes the | ||
+ | appropriate 256 bytes of RAMLink memory to be transferred visible in the | ||
+ | main memory map, uses the REU to transfer that 256 bytes to the REU, and then | ||
+ | uses the REU to transfer the 256 bytes in the REU to its destination in the | ||
+ | main memory map. Thus, the Double-DMA technique will allow the RAMLink to | ||
+ | transfer data at rouyghly 1/2 the speed of the REU, or 3-4 times faster than | ||
+ | using the CPU to perform transfers. | ||
+ | |||
+ | #(A): The RAMLink memory map | ||
+ | |||
+ | To achieve this transfer speed gain, the programmer must forego RL-DOS | ||
+ | usage and write specialized transfer routines. | ||
+ | discuss how the RAMLink maps itself into main memory and detail the various | ||
+ | RAMLink registers needed to make this feat possible: | ||
+ | |||
+ | Address Description | ||
+ | ------- ----------- | ||
+ | $de00 256 bytes of data (See $dfc0-$dfc3 for more information) | ||
+ | $df7e write to this location to activate the RAMLink hardware | ||
+ | $df7f write to this location to deactivate the RAMLink hardware. | ||
+ | $dfa0 lo byte of requested RAMCard memory page | ||
+ | $dfa1 hi byte of requested RAMCard memory page | ||
+ | $dfc0 write to this location to show RL variable RAM at $de00 (default) | ||
+ | $dfc1 write to this location to show RAMCard memory at $de00 | ||
+ | $dfc2 write to this location to show the RAM Port device $de00 page at $de00 | ||
+ | $dfc0 write to this location to show Pass-Thru Port dev. $de00 page at $de00 | ||
+ | |||
+ | |||
+ | For all locations that have the description "write to this address...", | ||
+ | program can safely write any byte to those locations, as the RAMLink hardware | ||
+ | simply waits for an access, not any particular byte to be written. | ||
+ | |||
+ | #(A): Order of Operations | ||
+ | |||
+ | Although the Double-DMA technique relies on use of the REU, it is beyond the | ||
+ | scope of this article to detail how to access the REU RAM under programmatic | ||
+ | control. | ||
+ | and the 17XX REU, refer to the back of a REU owner' | ||
+ | |||
+ | The following steps will realize the Double-DMA method: | ||
+ | |||
+ | Notes: | ||
+ | A = PAGE of RAM in main memory to be transferred to/from | ||
+ | X = single page of memory in REU used as temp RAM | ||
+ | |||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | Now, with the RAMLink hardware enabled in this way, the REU registers are | ||
+ | also visible, so one can do a double DMA transfer at this point. | ||
+ | are two choices: | ||
+ | |||
+ | Transfer A->P: | ||
+ | |||
+ | 10) set up REU for A->X transfer | ||
+ | 11) initiate REU DMA transfer | ||
+ | 12) set up REU for X->$de00 transfer | ||
+ | 13) initiate REU DMA transfer | ||
+ | |||
+ | Transfer P->A | ||
+ | |||
+ | 10) set up REU for X->$de00 transfer | ||
+ | 11) initiate REU DMA transfer | ||
+ | 12) set up REU for A->X transfer | ||
+ | 13) initiate REU DMA transfer | ||
+ | |||
+ | Now, to go on: | ||
+ | |||
+ | 14) If more byte need transferrring, | ||
+ | 15) sta $dfc1 - restore contents of $de00 | ||
+ | 15) sta $df7f - deactivate RAMLink hardware | ||
+ | 16) if computer = 128, restore bank | ||
+ | 17) restore I/O visibility if needed | ||
+ | 18) cli | ||
+ | |||
+ | #(A): Address Translation | ||
+ | |||
+ | To effectively use the Double-DMA technique, a programmer will want to | ||
+ | set up a DACC partition in the RAMLink for use as external RAM. The | ||
+ | programmer will need to determine the start address of the partition with the | ||
+ | RL-DOS G-P command (or its sister command, G-[shift]P) | ||
+ | return the address of the DACC partition, or will it? | ||
+ | |||
+ | The answer is: Maybe. | ||
+ | port and has the Normal/ | ||
+ | as the lowest RAM in the RAMLink memory map. However, when directly accessing | ||
+ | the RAMLink and bypassing RL-DOS, the REU is not mapped into the RAMLink | ||
+ | memory map. So, for such a condition, the code that determines the start of | ||
+ | the DACC partition must SUBTRACT the size of the REU from the address returned | ||
+ | by the G-P command. | ||
+ | However, for such an REU configuration, | ||
+ | least 256 bytes of REU RAM is available and not already in use before | ||
+ | utilizing the Double-DMA technique. | ||
+ | |||
+ | #(A): Performance | ||
+ | |||
+ | Craig Bruce, who has implemented this technique in his ACE operating system, | ||
+ | provides the following performance figures for different access techniques: | ||
+ | |||
+ | Type Bandwidth | ||
+ | (bytes/sec) (~usec) | ||
+ | ------------- | ||
+ | REU | ||
+ | REU thru RL | ||
+ | RAMLink | ||
+ | RL with REU | ||
+ | Internal RAM0 | ||
+ | Internal RAM1 80, | ||
+ | |||
+ | So, using this technique in ACE results in a 3.7x increase in transfer speed. | ||
+ | For some applications, | ||
+ | |||
+ | #(A): Conclusion | ||
+ | |||
+ | Obviously, CMD recommends that the RL-DOS be used for most operations, but | ||
+ | we realize that some programmers simply need faster transfer rates. | ||
+ | Double-DMA technique should provide the speed needed from the RAMLink. | ||
+ | Obviously, since this technique bypasses RL-DOS, code using it can | ||
+ | potentially corrupt RAMLink memory if errors occur or if the technique is | ||
+ | improperly used. When using the technique, we recommend extensive testing | ||
+ | using various DACC partitions and different REU configurations to ensure | ||
+ | proper operation. | ||
+ | |||
+ | #(A)ddcode: Double-DMA Code | ||
+ | |||
+ | Following is a set of functions that will perform transfers using Double-DMA. | ||
+ | They are copied from the routines used in Craig Bruce' | ||
+ | Release 14, which incorporates the Double-DMA method. | ||
+ | the code below: | ||
+ | |||
+ | ; Name: Double-DMA memory transfer | ||
+ | ; Author: | ||
+ | ; Date: 1995-12-4 | ||
+ | ; Description: | ||
+ | ; memory to/from main RAM and the RAMLink. | ||
+ | ; normal CPU transfer methods are utilized. | ||
+ | ; | ||
+ | ; Variables: | ||
+ | ; ramlinkNearPtr hold the address of main memory to transfer | ||
+ | ; ramlinkLength is length of data to transfer | ||
+ | ; ramlinkOpcode = $90: main memory -> RL | ||
+ | ; = $91: RL -> main memory | ||
+ | |||
+ | reu = $df00 | ||
+ | rlActivate | ||
+ | rlDeactivate = $df7f | ||
+ | rlSram | ||
+ | rlPageSelect = $dfa0 | ||
+ | rlPageActivate = $dfc1 | ||
+ | rlPageData | ||
+ | |||
+ | ramlinkOpcode .buf 1 | ||
+ | ramlinkLength .buf 2 | ||
+ | ramlinkNearPtr .buf 2 | ||
+ | ramlinkMpSave .buf 3 | ||
+ | ramlinkZpSave .buf 2 | ||
+ | |||
+ | ramlinkOp = * ;( [mp]=farPtr, | ||
+ | lda mp+0 | ||
+ | ldy mp+1 | ||
+ | ldx mp+2 | ||
+ | sta ramlinkMpSave+0 | ||
+ | sty ramlinkMpSave+1 | ||
+ | stx ramlinkMpSave+2 | ||
+ | lda zp+0 | ||
+ | ldy zp+1 | ||
+ | sta ramlinkZpSave+0 | ||
+ | sty ramlinkZpSave+1 | ||
+ | lda ramlinkNearPtr+0 | ||
+ | ldy ramlinkNearPtr+1 | ||
+ | sta zp+0 | ||
+ | sty zp+1 | ||
+ | clc | ||
+ | lda mp+1 | ||
+ | adc aceRamlinkStart+0 | ||
+ | sta mp+1 | ||
+ | lda mp+2 | ||
+ | adc aceRamlinkStart+1 | ||
+ | sta mp+2 | ||
+ | - lda ramlinkLength+0 | ||
+ | ora ramlinkLength+1 | ||
+ | beq + | ||
+ | jsr rlTransferChunk | ||
+ | jmp - | ||
+ | + lda ramlinkMpSave+0 | ||
+ | ldy ramlinkMpSave+1 | ||
+ | ldx ramlinkMpSave+2 | ||
+ | sta mp+0 | ||
+ | sty mp+1 | ||
+ | stx mp+2 | ||
+ | lda ramlinkZpSave+0 | ||
+ | ldy ramlinkZpSave+1 | ||
+ | sta zp+0 | ||
+ | sty zp+1 | ||
+ | clc | ||
+ | rts | ||
+ | |||
+ | | ||
+ | |||
+ | | ||
+ | ;** figure maximum page operation | ||
+ | lda ramlinkLength+1 | ||
+ | beq + | ||
+ | lda #0 | ||
+ | ldx mp+0 | ||
+ | beq rlTrDo | ||
+ | sec | ||
+ | sbc mp+0 | ||
+ | jmp rlTrDo | ||
+ | + lda mp+0 | ||
+ | beq + | ||
+ | lda #0 | ||
+ | sec | ||
+ | sbc mp+0 | ||
+ | cmp ramlinkLength+0 | ||
+ | bcc rlTrDo | ||
+ | + lda ramlinkLength+0 | ||
+ | |||
+ | ;** do the transfer | ||
+ | | ||
+ | tay | ||
+ | sty rlTrSize | ||
+ | jsr rlPageOp | ||
+ | |||
+ | ;** update the pointers and remaining length | ||
+ | clc | ||
+ | lda rlTrSize | ||
+ | bne + | ||
+ | inc mp+1 | ||
+ | inc zp+1 | ||
+ | dec ramlinkLength+1 | ||
+ | rts | ||
+ | + adc mp+0 | ||
+ | sta mp+0 | ||
+ | bcc + | ||
+ | inc mp+1 | ||
+ | + clc | ||
+ | lda zp+0 | ||
+ | adc rlTrSize | ||
+ | sta zp+0 | ||
+ | bcc + | ||
+ | inc zp+1 | ||
+ | + sec | ||
+ | lda ramlinkLength+0 | ||
+ | sbc rlTrSize | ||
+ | sta ramlinkLength+0 | ||
+ | bcs + | ||
+ | dec ramlinkLength+1 | ||
+ | + rts | ||
+ | |||
+ | | ||
+ | php | ||
+ | sei | ||
+ | sta rlActivate | ||
+ | lda mp+1 | ||
+ | sta rlPageSelect+0 | ||
+ | lda mp+2 | ||
+ | sta rlPageSelect+1 | ||
+ | sta rlPageActivate | ||
+ | lda aceReuRlSpeedPage+3 | ||
+ | bne rlPageOpReu | ||
+ | | ||
+ | tya | ||
+ | clc | ||
+ | adc mp+0 | ||
+ | tax | ||
+ | |||
+ | lda ramlinkOpcode | ||
+ | cmp #$91 | ||
+ | bne rlPageOpWrite | ||
+ | dex | ||
+ | dey | ||
+ | beq + | ||
+ | - lda rlPageData, | ||
+ | sta (zp),y | ||
+ | dex | ||
+ | dey | ||
+ | bne - | ||
+ | + lda rlPageData, | ||
+ | sta (zp),y | ||
+ | jmp rlPageOpContinue | ||
+ | |||
+ | | ||
+ | dex | ||
+ | dey | ||
+ | beq + | ||
+ | - lda (zp),y | ||
+ | sta rlPageData, | ||
+ | dex | ||
+ | dey | ||
+ | bne - | ||
+ | + lda (zp),y | ||
+ | sta rlPageData, | ||
+ | |||
+ | | ||
+ | sta rlSram | ||
+ | sta rlDeactivate | ||
+ | plp | ||
+ | rts | ||
+ | |||
+ | | ||
+ | ;** ramlink hardware already switched in | ||
+ | ldx #1 | ||
+ | tya | ||
+ | beq + | ||
+ | ldx #0 | ||
+ | cmp #0 ;xx cut-off value | ||
+ | bcc rlPageOpNonReu | ||
+ | + ldy ramlinkOpcode | ||
+ | cpy #$90 | ||
+ | beq + | ||
+ | ldy #$90 ; | ||
+ | jsr rlPageOpReuRl | ||
+ | ldy #$91 | ||
+ | jsr rlPageOpReuIntern | ||
+ | jmp ++ | ||
+ | + ldy #$90 ; | ||
+ | jsr rlPageOpReuIntern | ||
+ | ldy #$91 | ||
+ | jsr rlPageOpReuRl | ||
+ | + sta rlSram | ||
+ | sta rlDeactivate | ||
+ | plp | ||
+ | rts | ||
+ | |||
+ | | ||
+ | sta reu+7 ;len | ||
+ | stx reu+8 | ||
+ | sty temp1 | ||
+ | pha | ||
+ | lda zp+0 | ||
+ | ldy zp+1 | ||
+ | sta reu+2 | ||
+ | sty reu+3 | ||
+ | lda aceReuRlSpeedPage+0 | ||
+ | ldy aceReuRlSpeedPage+1 | ||
+ | sta reu+4 | ||
+ | sty reu+5 | ||
+ | lda aceReuRlSpeedPage+2 | ||
+ | sta reu+6 | ||
+ | .if computer-64 | ||
+ | ldy vic+$30 | ||
+ | lda #0 | ||
+ | sta vic+$30 | ||
+ | .ife | ||
+ | lda temp1 | ||
+ | sta reu+1 | ||
+ | .if computer-64 | ||
+ | sty vic+$30 | ||
+ | .ife | ||
+ | pla | ||
+ | rts | ||
+ | |||
+ | | ||
+ | sta reu+7 ;len | ||
+ | stx reu+8 | ||
+ | sty temp1 | ||
+ | pha | ||
+ | lda mp+0 | ||
+ | ldy #> | ||
+ | sta reu+2 | ||
+ | sty reu+3 | ||
+ | lda aceReuRlSpeedPage+0 | ||
+ | ldy aceReuRlSpeedPage+1 | ||
+ | sta reu+4 | ||
+ | sty reu+5 | ||
+ | lda aceReuRlSpeedPage+2 | ||
+ | sta reu+6 | ||
+ | .if computer-64 | ||
+ | ldy vic+$30 | ||
+ | lda #0 | ||
+ | sta vic+$30 | ||
+ | .ife | ||
+ | lda temp1 | ||
+ | sta reu+1 | ||
+ | .if computer-64 | ||
+ | sty vic+$30 | ||
+ | .ife | ||
+ | pla | ||
+ | rts | ||
+ | |||
+ | ============================================================================ | ||
+ | </ | ||
+ | ====== UseNuggets ====== | ||
+ | < | ||
+ | |||
+ | COMP.SYS.CBM: | ||
+ | see what topics are showing up this month: | ||
+ | |||
+ | #(A): We Want More Power! | ||
+ | | ||
+ | in the newsgroup. | ||
+ | on a C64 or on a C128 in 64 mode only, some angry C128 128 mode users | ||
+ | | ||
+ | extra work the 128 version would require to threats of non-purchase of | ||
+ | the unit ensued. | ||
+ | next wave started, programmers worried about RAM transfer speed bottlenecks | ||
+ | | ||
+ | speed data transfers. | ||
+ | |||
+ | From: Doug Cotton < | ||
+ | Newsgroups: comp.sys.cbm | ||
+ | Subject: Re: Power Users! | ||
+ | Date: 28 Nov 1995 00:59:26 GMT | ||
+ | Organization: | ||
+ | | ||
+ | There were some earlier questions about how fast memory transfers | ||
+ | could be accomplished with the accelerator, | ||
+ | individual emailed me over the lack of a DMA controller. I obtained | ||
+ | some figures from Mark concerning this. Presently, the DMA transfers | ||
+ | using an REU transfers a byte in 1 microsecond. The accelerator can | ||
+ | achieve this same speed when transferring data from either | ||
+ | on-board static RAM, or from expansion memory (slower DRAM) to the | ||
+ | host computer RAM. Transfers internally (from static RAM to static | ||
+ | RAM) will take .35 microseconds per byte (350 nanoseconds). | ||
+ | Transfers from RAMLink RAMCard RAM (direct style) to the host | ||
+ | computer RAM will take about 2 microseconds per byte. The only figures | ||
+ | I don't have yet are for transfers between on-board static RAM | ||
+ | and expansion DRAM, but this will be governed by the speed of the | ||
+ | DRAM itself, and the number of wait-states required. It definately | ||
+ | will be faster than 1 byte per microsecond though. So the only | ||
+ | thing slower than a current DMA operation is transferring to and | ||
+ | from RAMLink RAMCard memory, which is still pretty impressive at | ||
+ | half the speed of present DMA transfers. | ||
+ | | ||
+ | Given these speeds, the cost of high-speed DMA controllers ($$$$), and | ||
+ | a real lack of anywhere to put one on the main board, I think | ||
+ | going without a DMA controller is reasonable. If you really want | ||
+ | one, though, there' | ||
+ | a do-it-yourself project. | ||
+ | | ||
+ | Doug Cotton | ||
+ | | ||
+ | | ||
+ | | ||
+ | but it is still undetermined whether a single connector or a small | ||
+ | | ||
+ | as more options for hardware mods are available. | ||
+ | |||
+ | #(A): Let's all design the Commodore 64 Laptop! | ||
+ | |||
+ | Yes, the dreamers are at it once again. | ||
+ | net was abuzz with thoughts on what should be included on a Commodore | ||
+ | | ||
+ | | ||
+ | a power sipper and have an LCD screen and a keyboard. | ||
+ | was where agreement ended. | ||
+ | |||
+ | CPU: | ||
+ | |||
+ | | ||
+ | | ||
+ | |||
+ | Disk: | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | RAM | ||
+ | |||
+ | | ||
+ | |||
+ | Video | ||
+ | |||
+ | | ||
+ | | ||
+ | |||
+ | Sound | ||
+ | |||
+ | | ||
+ | | ||
+ | |||
+ | So, on and on it went. Some got down to the nitty gritty of planning | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | battery power. | ||
+ | |||
+ | | ||
+ | require. | ||
+ | |||
+ | | ||
+ | CMD FD drive could/ | ||
+ | |||
+ | | ||
+ | fabbibng of the CBM chips was power hungry and ill-suited to battery | ||
+ | operation. | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | the best entries next issue. | ||
+ | |||
+ | | ||
+ | | ||
+ | on at CMD, but we haven' | ||
+ | | ||
+ | |||
+ | #(A): The Tower of Power | ||
+ | |||
+ | It seems Al Anger' | ||
+ | Issue 10 cover got everyone excited. | ||
+ | email about it, Commodore Hacking asked some questions, and some USENETters | ||
+ | were deciding how to do it themselves. | ||
+ | about cover it, which turned a few enquiring minds away, we're sure. | ||
+ | | ||
+ | are getting tired of all the clutter and mess cables, power cords, | ||
+ | | ||
+ | | ||
+ | but the cost is evidently more than what most folks are willing to fork | ||
+ | over (~US$300 - US$550). | ||
+ | | ||
+ | |||
+ | #(A): Dave Letterman, Eat Your Heart Out! | ||
+ | |||
+ | The latest thread is the top ten list of games. | ||
+ | their 10 most favorite games for the CBM machines. | ||
+ | | ||
+ | are reminiscing about the old games, and the Commodore users are noting | ||
+ | that the new games "just aren't as good" | ||
+ | |||
+ | So, that wraps up the USENET this time. We try to keep an eye out for | ||
+ | stuff of interest, but drop us a line if you think we might miss an IMPORTANT | ||
+ | topic... | ||
+ | |||
+ | ============================================================================ | ||
+ | </ | ||
+ | ====== The Graphics Toolbox: Ellipses ====== | ||
+ | < | ||
+ | by Stephen L. Judd (sjudd@nwu.edu) | ||
+ | |||
+ | |||
+ | #(A): Introduction | ||
+ | |||
+ | After a much needed break from Commodore 64 programming, | ||
+ | would be nice to construct another algorithm for the 2D graphics toolbox. | ||
+ | Since we did circles last time, a natural successor would be an algorithm | ||
+ | to draw eclipses. | ||
+ | upon it to draw eclipses. | ||
+ | with small-radius circles. | ||
+ | cover that issue as well. | ||
+ | |||
+ | #(A): Circles | ||
+ | |||
+ | | ||
+ | |||
+ | x^2 + y^2 = r^2 | ||
+ | |||
+ | After taking differentials of both sides, we find that | ||
+ | |||
+ | dy = -x/y dx | ||
+ | |||
+ | That is, if we take a step of size dx in the x-direction, | ||
+ | want to take a step of size dy in the y-direction. | ||
+ | |||
+ | Next we start at the top of the circle, so that y=r and x=0. We | ||
+ | start increasing x in step sizes of one. We only care about step sizes | ||
+ | of one, since our basic unit is now a pixel. | ||
+ | start piling up these dy's, and at some point the integer part of y will | ||
+ | increase, and we get a new y-coordinate for the pixel. | ||
+ | keep adding the dy's together, and once their sum is greater than one, we | ||
+ | decrease y (remember that y starts at the top of the circle). | ||
+ | |||
+ | The sneaky way to do this is to treat y as an integer " | ||
+ | it is very easy to add the dy's together, since they have a common denominator | ||
+ | equal to y. So really all we need to do is start adding x-coordinates together, | ||
+ | and once their sum is larger than y, we decrease y and hang on to the | ||
+ | remaining fractional part of dy. The algorithm then looks like: | ||
+ | |||
+ | y=r | ||
+ | x=0 | ||
+ | a=r | ||
+ | loop: x=x+1 | ||
+ | a=a-r | ||
+ | if a<=0 then a=a+y:y=y-1 | ||
+ | plot (x,y) | ||
+ | if x<y then loop: | ||
+ | |||
+ | Now, Chris McBride pointed something out to me. As you may recall, | ||
+ | the algorithm breaks down for small r. Chris said that if a is initially | ||
+ | set to r/2 instead of r, the algorithm works perfectly. | ||
+ | Recall that we add dy to itself until it is greater than one. Wouldn' | ||
+ | it make more sense to add dy to itself until it is greater than 0.5? | ||
+ | That would have the effect of rounding things up. Thus, starting at r/2 | ||
+ | is like adding 0.5 to the fractional part of y -- it is the difference | ||
+ | between INT(y) and INT(y+0.5). | ||
+ | |||
+ | Thus, the above line | ||
+ | |||
+ | a=r | ||
+ | |||
+ | should be changed to | ||
+ | |||
+ | a=r/2 | ||
+ | |||
+ | for a perfect circle every time. Thus, this corresponds to adding an LSR | ||
+ | to the machine code. Incidentally, | ||
+ | but it was placed in such a crazy place that you probably never saw it. | ||
+ | |||
+ | #(A): Ellipses, HO! | ||
+ | |||
+ | Now we can move on to eclipses. | ||
+ | squashed circle, it seems reasonable that we could modify the above circle | ||
+ | algorithm. | ||
+ | |||
+ | Everyone knows the equation of an eclipse: | ||
+ | |||
+ | | ||
+ | |||
+ | Upon taking differentials of both sides we have, | ||
+ | |||
+ | | ||
+ | |||
+ | or, equivalently, | ||
+ | |||
+ | dy = -b^2/a^2 * x/y * dx | ||
+ | |||
+ | As you can see, life becomes suddenly becomes more complicated by a factor of | ||
+ | b^2/ | ||
+ | through the x- and y-axis. | ||
+ | just drawing an eighth of the circle, but now we have to draw a full quarter | ||
+ | of the eclipse. | ||
+ | |||
+ | We will start drawing the eclipse at x=0, y=b, so that initially x | ||
+ | will increase by one at each step, and y will wait a few steps to increase. | ||
+ | At some point, though, we will want y to increase by one at each step, and | ||
+ | x to wait a few steps before increasing; in the circle algorithm we just quit | ||
+ | once we reached this point, but now we are going to need an equation for dx: | ||
+ | |||
+ | dx = -a^2/b^2 * y/x * dy | ||
+ | |||
+ | In the circle algorithm, we used a single variable to count up and | ||
+ | tell us when it was time to increase y. Perhaps your intuition suggests | ||
+ | that we can do an eclipse with _two_ variables; mine said the same thing, | ||
+ | so that is exactly what we will do. | ||
+ | |||
+ | First, let us assume we have a way of calculating b^2/a^2: | ||
+ | |||
+ | E = b^2/a^2 | ||
+ | |||
+ | I will suggest a way to perform this calculation later. | ||
+ | the first few terms in the dy summation, starting at x=0, y=b: | ||
+ | |||
+ | dy1 + dy2 + ... = -E * (x0 + x1 + x2 + x3 + ...)/y | ||
+ | = -E * (0 + 1 + 2 + 3 + ...)/b | ||
+ | = - (0 + E + 2E + 3E + ...)/b | ||
+ | |||
+ | So, the basic structure of the algorithm is: add up 0, E, 2E, etc. until | ||
+ | the sum is larger than y. At that point, reset the counter, keeping the | ||
+ | remainder, and decrease y. This is where the two variables come in: | ||
+ | |||
+ | X=X+1 | ||
+ | | ||
+ | | ||
+ | IF T1>=Y THEN T1=T1-Y: | ||
+ | |||
+ | Do you see how it works? | ||
+ | and T1 is the counter. | ||
+ | than Y, dy will be larger than one at each step. We need a new algorithm | ||
+ | to continue the calculation, | ||
+ | |||
+ | Look at the expression for dx above. | ||
+ | but somehow that goes against the spirit of the calculation so far. Let's | ||
+ | instead rewrite dx slightly: | ||
+ | |||
+ | dx = - y/(E*x) * dy | ||
+ | |||
+ | Here we have simply written a^2/b^2 as 1/(b^2/a^2) = 1/E. But E*x is | ||
+ | exactly the variable T2 above, so we can continue the calcuation without | ||
+ | even stopping for breath: | ||
+ | |||
+ | Y=Y-1 | ||
+ | | ||
+ | IF T1>=T2 THEN T1=T1-T2: | ||
+ | |||
+ | (remember that T1 keeps track of the fractional part of y). So, we now | ||
+ | have a complete algorithm for drawing an eclipse: | ||
+ | |||
+ | 0 REM ELLIPSE ATTEMPT #N SLJ 11/3/95 | ||
+ | 10 A=150: | ||
+ | 20 X=0: | ||
+ | 30 GRAPHIC1, | ||
+ | 40 X=X+1: | ||
+ | 50 T1=T1+T2 | ||
+ | 60 IF T1>=Y THEN T1=T1-Y: | ||
+ | 70 DRAW1, | ||
+ | 80 IF T2<Y THEN 40 | ||
+ | 90 Y=Y-1 | ||
+ | 100 T1=T1+Y | ||
+ | 110 IF T1>=T2 THEN T1=T1-T2: | ||
+ | 120 DRAW1, | ||
+ | 130 IF Y>0 THEN 90 | ||
+ | |||
+ | Lines 40-80 are the top part of the eclipse, and lines 90-130 handle the | ||
+ | bottom part. Note that T2 starts at 0.5, to round off the calculation in the | ||
+ | same spirit as we did in the circle algorithm. | ||
+ | |||
+ | Naturally, this algorithm has a few limitations. | ||
+ | and end points are plotted, so you can see how close the algorithm really is. | ||
+ | In my experiments it occasionally missed the endpoint by a pixel or two. As | ||
+ | usual, I was a little too lazy to investigate possible ways to get around this. | ||
+ | If you require a perfect eclipse, you need to start the calculation at x=0, y=b | ||
+ | and run it forwards (e.g. lines 40-80 above), and then do another, similar | ||
+ | calcuation, starting at x=a, y=0, and running backwards. | ||
+ | second calculation, | ||
+ | lines 40-80, interchanging X and Y. | ||
+ | |||
+ | Now we need to translate this algorithm into assembly. | ||
+ | to make a few assumptions: | ||
+ | particular, I require that b^2/a < 256. This insures that b^2/a^2 < 256, | ||
+ | and also insures that T2 will not overflow (note that when x=a, T2=E*a, | ||
+ | e.g. T2=b^2/ | ||
+ | |||
+ | Next, we need to deal with the fraction E=b^2/ | ||
+ | like this consists of two parts, an integer part plus a fractional part | ||
+ | (e.g. a number and a decimal). | ||
+ | where EL represents the decimal part and EH the integer. | ||
+ | consists of adding together the fractional parts, and if there is an overflow, | ||
+ | increasing the integer part. For example, if E=1.62, then EH=1 and EL=0.62. | ||
+ | We add EL to our number, and if it is greater than one, we carry the one to | ||
+ | when we add EH to our number. | ||
+ | |||
+ | The best thing to do is to represent EL as a fractional part of 256. | ||
+ | That is, our EL above should really be 0.62*256. | ||
+ | overflows will be handled automatically (this will become clear in a moment). | ||
+ | |||
+ | Let me give some pseudo-assembly code and we'll push off the | ||
+ | explanation until later: | ||
+ | |||
+ | 35 GOTO 200 | ||
+ | 190 REM *********************** | ||
+ | 200 XM=0: | ||
+ | 210 XM=XM+1 | ||
+ | 220 C=0: | ||
+ | 230 X=A: | ||
+ | 235 A=A+T1 | ||
+ | 240 IF A>=YM THEN A=A-YM: | ||
+ | 250 T1=A:DRAW1, X0+XM, Y0-YM | ||
+ | 260 IF Y<=YM THEN 210 | ||
+ | 265 T2=Y:A=T1 | ||
+ | 270 YM=YM-1 | ||
+ | 280 A=A+YM:IF A<T2 THEN 300 | ||
+ | 290 A=A-T2: | ||
+ | 295 X=A: | ||
+ | 300 DRAW1, X0+XM, Y0-YM | ||
+ | 310 YM=YM-1:IF YM>=0 THEN 280 | ||
+ | |||
+ | XM and YM are the x and y coordinates of the point to be plotted. | ||
+ | that in line 200 X starts at 128, and this again is to round up all our | ||
+ | calculations; | ||
+ | above code I store T2 in the X and Y registers for the first part of the | ||
+ | code. Note that in lines 220 and 290 there is some extraneous code to | ||
+ | simulate things that in assembly are taken care of by the 6502. Note | ||
+ | also that the comparison in line 260 has been changed from < to < | ||
+ | makes the branch easier, and I'm not sure how it affects the calculation | ||
+ | (I didn't notice any difference in the few runs I tried it on). | ||
+ | |||
+ | Moving through the code, we increase x, and then add the decimal | ||
+ | part of E to the counter. | ||
+ | along with any carries. | ||
+ | y, it is time to decrease y and reset the counter. | ||
+ | |||
+ | Moving to the second part of the code, we do a little rearranging | ||
+ | in line 265. Really a better thing to do would be to let A=T1-T2, so that | ||
+ | the compare in line 280 becomes simpler. | ||
+ | becomes freed up at this point. | ||
+ | thing as before. | ||
+ | |||
+ | The full assembly code is then: | ||
+ | |||
+ | ; | ||
+ | ; | ||
+ | ; | ||
+ | ;EL and EH contain remainder and integer parts of E, resp. | ||
+ | |||
+ | LDX #128 | ||
+ | LDY #00 | ||
+ | CLC | ||
+ | L1 INC XM | ||
+ | TXA | ||
+ | ADC EL | ||
+ | TAX | ||
+ | TYA | ||
+ | ADC EH | ||
+ | TAY | ||
+ | ADC T1 | ||
+ | CMP YM | ||
+ | BCC :CONT1 | ||
+ | SBC YM | ||
+ | DEC YM | ||
+ | : | ||
+ | JSR PLOT | ||
+ | CPY YM | ||
+ | BCC L1 | ||
+ | |||
+ | STY T2 | ||
+ | LDA T1 | ||
+ | SBC T2 | ||
+ | DEC YM | ||
+ | L2 ADC YM | ||
+ | BCC :CONT2 | ||
+ | SBC T2 | ||
+ | STA T1 | ||
+ | INC XM | ||
+ | TXA | ||
+ | ADC EL | ||
+ | TAX | ||
+ | LDA T2 | ||
+ | ADC EH | ||
+ | STA T2 | ||
+ | LDA T1 | ||
+ | : | ||
+ | DEC YM | ||
+ | BPL L2 ;Assuming y<128 | ||
+ | |||
+ | |||
+ | #(A): Logarithms | ||
+ | |||
+ | Finally, we need a way of calculating b^2/ | ||
+ | logarithms for this. I do believe I discussed this concept in an earlier | ||
+ | issue of C=Hacking. | ||
+ | |||
+ | x = b^2/a^2 | ||
+ | |||
+ | then | ||
+ | |||
+ | | ||
+ | |||
+ | so that | ||
+ | |||
+ | x = exp(2*(log(b) - log(a)) | ||
+ | |||
+ | Thus, three tables need to be created: one for log(x), and one each for | ||
+ | the integer and remainder parts of e^(2*x). | ||
+ | the first table might be a table of f(x)=222/ | ||
+ | constant is chosen so that f(255) is roughly 255. 222 was chosen because | ||
+ | the inversion (i.e. the e^x part) works best at that value. | ||
+ | much assumes that x is not zero or one, either. | ||
+ | more tables for somewhat better accuracy. | ||
+ | |||
+ | One really nice thing about this is that you don't have to worry | ||
+ | about squaring things, since that part can be taken care of automatically | ||
+ | in logarithm space. | ||
+ | the types of numbers we can divide (e.g. log(a)-log(b) can't be larger | ||
+ | than 127 or so). | ||
+ | |||
+ | Division then consists of a table lookup, subtraction of another | ||
+ | table lookup, and two more table lookups. | ||
+ | demonstrate the use of logs in this sort of division, and a very rough | ||
+ | feel for the type of accuracy to expect -- note that it doesn' | ||
+ | decimal parts, or convert the decimal parts into fractions of 256, etc.: | ||
+ | |||
+ | 1 FAST: | ||
+ | 10 DIM L(256), | ||
+ | 20 FOR I=1 TO 256 | ||
+ | 25 PRINT " | ||
+ | 30 L(I)= INT(FC*LOG(I/ | ||
+ | 40 S=I:IF I>127 THEN S=I-256 | ||
+ | 50 EX=EXP(2*S/ | ||
+ | 60 EI(I)=INT(EX+0.5) | ||
+ | 70 ER(I)=EX-EI(I) | ||
+ | 80 NEXT I | ||
+ | 90 EI(0)=1: | ||
+ | 100 FOR A=2 TO 250 | ||
+ | 110 FOR B=2 TO 250 | ||
+ | 120 X=L(B)-L(A) | ||
+ | 123 IF X>127 THEN PRINT" | ||
+ | 126 IF X<0 THEN X=X+256 | ||
+ | 130 A1=EI(X)+ER(X): | ||
+ | 135 BL=INT(A2+0.5)-INT(A1+0.5) | ||
+ | 140 PRINT A; | ||
+ | 150 NEXT:NEXT | ||
+ | |||
+ | #(A): Conclusion | ||
+ | |||
+ | Sorry, no 3D graphics this time around. | ||
+ | bitmapped solid 3D virtual world sometime in the not too distant future. | ||
+ | Otherwise, may your ellipses never be square :). | ||
+ | |||
+ | |||
+ | ============================================================================ | ||
+ | </ | ||
+ | ====== Hack Surfing ====== | ||
+ | < | ||
+ | |||
+ | For those who can access that great expanse of area called the World Wide | ||
+ | Web, here is some new places to visit that are of interest to the Commodore | ||
+ | community. | ||
+ | of sites online that catered to Commodore numbered in the 10' | ||
+ | number is in the 100' | ||
+ | |||
+ | If you know of a site that is not listed here, please feel free to send it | ||
+ | to the magazine. | ||
+ | changed or added to the US Commodore WWW Site Links page | ||
+ | (http:// | ||
+ | |||
+ | To encourage these sites to strive to continually enhance their creations, | ||
+ | and because we like to gripe :-), we'll point out an improvements that | ||
+ | could be made at each site. | ||
+ | |||
+ | #(A): Companies | ||
+ | |||
+ | o http:// | ||
+ | ESCOM Interactive, | ||
+ | its offices and some general information. | ||
+ | | ||
+ | No Commodore 8-bit inforation yet. | ||
+ | |||
+ | o http:// | ||
+ | | ||
+ | the accelerator, | ||
+ | | ||
+ | just announced the Super64CPU, no mention of it is to found anywhere on | ||
+ | the WWW site. Bummer. | ||
+ | |||
+ | #(A): Publications | ||
+ | |||
+ | o http:// | ||
+ | | ||
+ | out here. Some Commodore links are included, and the and a few magazine | ||
+ | | ||
+ | of its related software titles is provided. | ||
+ | | ||
+ | |||
+ | o http:// | ||
+ | Atta Bitar (8 Bitter) magazine. | ||
+ | as information on how to subscribe. | ||
+ | read German (At least we THINK it's German), and the English transmation | ||
+ | page isn't done yet. Anyway, if you would like to subscribe or need to | ||
+ | | ||
+ | C=H gripe: Yes, we know this is English-centric, | ||
+ | | ||
+ | |||
+ | #(A): User's Groups | ||
+ | |||
+ | o http:// | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | o http:// | ||
+ | | ||
+ | some newsletters are present. | ||
+ | to this new address. | ||
+ | what the CBM 8-bitters are doing in Pittsburgh. | ||
+ | |||
+ | o http:// | ||
+ | The Central Coast Commodore User's Group. | ||
+ | CA area will be glad to know that CCCUG is there for them. Past | ||
+ | | ||
+ | | ||
+ | | ||
+ | need a little help, as it is down on members. | ||
+ | Maria area, consider joining... | ||
+ | |||
+ | #(A): Miscellaneous | ||
+ | |||
+ | o http:// | ||
+ | Byte Magazine' | ||
+ | of the things that Commodore DID do right in its lifetime, and reflects | ||
+ | on the blunders CBM made. The article makes for very good reading, but | ||
+ | will depress some. C=H gripe: The pictures in the real article aren't | ||
+ | | ||
+ | |||
+ | o http:// | ||
+ | GEOS Warp 1.0. For the Mac user who needs or wants to run GEOS, this | ||
+ | | ||
+ | the Mac. The system looks very impressive, to the point of us not asking, | ||
+ | | ||
+ | | ||
+ | doom the project to failure. | ||
+ | |||
+ | o http:// | ||
+ | Dan Fandrich' | ||
+ | use multiple programming languages with the C64/128, bookmark this page. | ||
+ | Very current info, and lots of it is presented. | ||
+ | mags are indexed, and pointers are provided to many of the current crop of | ||
+ | | ||
+ | more organization to make it easier to get at juicy info. | ||
+ | |||
+ | o http:// | ||
+ | | ||
+ | from BASIC or something else, this page has a beginner' | ||
+ | might find useful. | ||
+ | what there is is available. | ||
+ | |||
+ | o http:// | ||
+ | Pete Gonzalez' | ||
+ | | ||
+ | in progress cross assembler for the PC. C=H gripe: When's the game coming | ||
+ | out again? :-) | ||
+ | |||
+ | o http:// | ||
+ | The Commodore Computer Cult Corner. | ||
+ | | ||
+ | | ||
+ | even light a " | ||
+ | | ||
+ | page automatically, | ||
+ | |||
+ | o http:// | ||
+ | John Wilbur' | ||
+ | check back. C=H gripe: We'd like to see a little more about John as it | ||
+ | | ||
+ | |||
+ | o http:// | ||
+ | | ||
+ | | ||
+ | LCD laptop computer. | ||
+ | about Marc-Jano as it relates to Commodore. | ||
+ | |||
+ | ============================================================================ | ||
+ | </ | ||
+ | ====== Design and Implementation of an Advanced Text Editor ====== | ||
+ | < | ||
+ | by Craig Bruce (csbruce@ccnga.uwaterloo.ca) | ||
+ | |||
+ | Note: Due to the size of the article, no executable or source code | ||
+ | is included, but both will be included in ACE Release #15 | ||
+ | (ftp:// | ||
+ | |||
+ | #(A)1: 1. INTRODUCTION | ||
+ | |||
+ | This article discusses the design and implementation of the ZED text editor | ||
+ | for the ACE operating system (Release #15 and higher). | ||
+ | source code will be freely available when they are ready. | ||
+ | entirely in assembly language (ACEassembler) and makes heavy use of the | ||
+ | full-screen control capabilities of ACE. However, part of the genius of the | ||
+ | design of the ACE interface is that its facilities could be replicated into | ||
+ | a standalone environment and a new ZED could be made into a one-part program | ||
+ | (for greater convenience, | ||
+ | |||
+ | There was a previous version of ZED, which WAS a standalone program. | ||
+ | written entirely in _machine_ language (as opposed to assembly language; | ||
+ | y' | ||
+ | to say, upgrading and maintaining the program was a real problem, even | ||
+ | though it was only 17K in size. The program also had a couple of | ||
+ | limitations, | ||
+ | a maximum of 80 characters (plus a carriage return), or they would be split | ||
+ | into two physical lines internally. | ||
+ | 80-column C128. | ||
+ | |||
+ | Still, the standalone version had a number of outstanding capabilities, | ||
+ | including the ability to edit EXTREMELY large files with an REU and dynamic | ||
+ | data structures, the ability to use "burst mode" on devices that supported | ||
+ | it, TAB and character-set translation on loading and saving, global search | ||
+ | and replace, range delete and recall, and a paragraph " | ||
+ | It is truly an outstanding program (if I do say so myself), and it is my | ||
+ | pleasure to use it every day. (I also use Unix's " | ||
+ | getting tired of its clumsy user interface... I may just have to port ZED to | ||
+ | the Unix environment one of these days). | ||
+ | |||
+ | The ACE version has/will have all of these features and then some. The ACE | ||
+ | version supports even larger files by using the ACE dynamic memory | ||
+ | management system (see C= Hacking #7 or a newer ACE Programmer' | ||
+ | Guide) in addition to its own byte-oriented memory management (see C= | ||
+ | Hacking #2) with internal memory (up to 512K on a C128), REUs up to 16 Megs, | ||
+ | and RAMLink DACC memory up to 16 Megs. Burst-mode support isn't currently | ||
+ | available in ACE (see C= Hacking #3), nor does the ACE version of ZED | ||
+ | currently implement the other outstanding editing features of the original | ||
+ | ZED mentioned above. | ||
+ | three-key rollover for typing convenience (see C= Hacking #6)). | ||
+ | |||
+ | However, the ACE version supports extremely long physical lines (paragraphs) | ||
+ | by providing automatic word wrapping and "soft returns" | ||
+ | sloshing" | ||
+ | functionality of a word processor. | ||
+ | modes that ACE supports on both the C128 and C64. | ||
+ | |||
+ | #(A)2: 2. DATA STRUCTURES, FILE LOADING | ||
+ | |||
+ | Now we start talking about the implementation of ZED. What a text editor | ||
+ | is, basically, is a program that holds a text document in memory that allows | ||
+ | you to use certain commands to alter tiny pieces or large-scale chunks of | ||
+ | the document and then to save the changed document permanently back to | ||
+ | disk. The way in which the document is held in memory is the content of | ||
+ | this section. | ||
+ | |||
+ | #(A)2.1: 2.1. DOCUMENT DATA STRUCTURE | ||
+ | |||
+ | ZED uses a bi-directionally linked list to hold the text document in | ||
+ | memory. | ||
+ | " | ||
+ | whole list is in the form of a big ring (the links run around in circles). | ||
+ | Here is an asciigram of a document with two data lines: | ||
+ | |||
+ | / | ||
+ | | / | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | \-------------------/ | ||
+ | |||
+ | I should mention that all pointers are 32-bit values, so that they can point | ||
+ | to anywhere in ACE's " | ||
+ | for ZED are 32 bits in size, to avoid all arbitrary restrictions on the | ||
+ | magnitudes of various things). | ||
+ | diagram, the value that is stored for the pointer is the address of the | ||
+ | starting byte of the record that is being pointed to. | ||
+ | |||
+ | I should also mention that lines are stored as they are displayed. | ||
+ | physical line (terminated by a carriage return) has to be split (using "soft | ||
+ | returns" | ||
+ | linked-record position in the document data structure. | ||
+ | |||
+ | Using a bi-directionally (doubly) linked list (instead of a uni-directionaly | ||
+ | (singly) linked list is a practical necessity in this environment for two | ||
+ | reasons. | ||
+ | accesses the document: he normally moves cursor up and down, page up and | ||
+ | down. It would take a lot of time to move the cursor up using a singly | ||
+ | linked list. Second, using a double linked list makes it easier to insert | ||
+ | or delete a line from the document. | ||
+ | to point beyond the record being deleted, but the previous record is | ||
+ | difficult to locate in a singly linked list; you must keep and manage a | ||
+ | pointer to it (and if the user moves the cursor up, you lose what you've got | ||
+ | for it). I prefer doubly liked lists for any job anyway, even if the | ||
+ | ability to go backwards isn't needed, because they are easier to work with | ||
+ | (and to construct reusable library routines for). | ||
+ | |||
+ | Using a large block of memory for the data isn't really an option either. | ||
+ | Anyone who has used SpeedScript knows what happens when you try to insert | ||
+ | text near the beginning of a long document: it takes a lot of time to insert | ||
+ | one space in the document memory, and the delay is annoying. | ||
+ | played out for a document that is N megabytes in size. (Some auxiliary data | ||
+ | structure would be needed in this case anyway, to break the 64K barrier). | ||
+ | I'm guessing that most other word processors/ | ||
+ | computers use this data structure (a " | ||
+ | |||
+ | The decision to store each display line in a single record is really one of | ||
+ | convenience and efficiency. | ||
+ | the cursor and whizzing between display pages, so we don't want to be | ||
+ | wasting any time uselessly re-formatting the text while he (sic) is doing | ||
+ | this. We only want to re-format the text when an actual modification is | ||
+ | made to the document. | ||
+ | physical and logical line numbers may not always match up, but if the | ||
+ | " | ||
+ | is set to be longer than the maximum physical-line length of a file (often | ||
+ | 80 characters), | ||
+ | |||
+ | Accessing the document is fairly simple. | ||
+ | entire document is the address of the special trailer line. With this, we | ||
+ | know directly where the bottom line is, so we can instantly go to the bottom | ||
+ | of the document (Commodore-DOWN) and then follow the links backward to | ||
+ | access preceeding lines. | ||
+ | since the document is in a ring. We just locate the trailer line and then | ||
+ | follow the " | ||
+ | should be no surprise that a pointer is kept to the trailer line in ZED in | ||
+ | order to locate a document. | ||
+ | in memory at the same time, including the "kill buffer" | ||
+ | a complete and independent document). | ||
+ | should be noted that this trailer line never changes (therefore, we never | ||
+ | have to update the pointer to the trailer line of a document). | ||
+ | |||
+ | #(A)2.2: 2.2. LINE DATA STRUCTURE | ||
+ | |||
+ | The format of each individual display line within a document held in the | ||
+ | linked-list structure described above is as follows: | ||
+ | |||
+ | OFF | ||
+ | --- | ||
+ | 0 | ||
+ | 4 | ||
+ | 8 | ||
+ | 9 | ||
+ | | ||
+ | n+10 - SIZE | ||
+ | |||
+ | The two 32-bit pointers have already been mentioned. | ||
+ | tells whether the line ends in a "hard return" | ||
+ | return (indicated by the $80 bit being set) is recorded for every place in | ||
+ | the text file where a carriage-return character is present. | ||
+ | (indicated by the $80 bit being clear) is formatted into the document every | ||
+ | place where a line must be broken in order to avoid it exceeding the target | ||
+ | line length. | ||
+ | pulled back around a soft return in order to insure that display lines are | ||
+ | as full as possible (whereas they cannot be wrapped around a hard return). | ||
+ | |||
+ | When a file is being written back to disk, lines that have a hard return | ||
+ | flag will be written with a trailing carriage-return character, whereas | ||
+ | lines ending with a soft return will be written with only the characters | ||
+ | displayed on the line (no CR), and, as such, they will be logically | ||
+ | concatenated together into the same physical line (again) in the output | ||
+ | file. The " | ||
+ | special trailer line of the document or not. We need a convenient way to | ||
+ | check for running into the trailer line, and we cannot use null pointers | ||
+ | since the document is in a ring (note that there won't be any null pointers | ||
+ | even if the document contains zero data lines; the trailer line will point | ||
+ | to itself). | ||
+ | |||
+ | The lower six bits of the flags field are currently unused, but they could | ||
+ | be used, for example, to record the number of leading spaces that a | ||
+ | line has before the first non-blank character. | ||
+ | hold a file with a lot of indentation (a program, for example) using less | ||
+ | memory per line. This feature is not currently implemented. | ||
+ | |||
+ | The next field tells the number of displayable characters that are on the | ||
+ | line and then the next field stores the actual characters in a simple | ||
+ | string. | ||
+ | character is NOT stored in the line data, since its presence is already | ||
+ | indicated in the line header. | ||
+ | dynamic-memory space, only the number of bytes that are actually needed are | ||
+ | allocated. | ||
+ | line header. | ||
+ | the number of bytes requested rounded up to the nearest multiple of eight | ||
+ | bytes, for technical reasons discussed in C= Hacking #2. A single display | ||
+ | line can contain up to 240 characters (not counting the CR). | ||
+ | |||
+ | Every time that a line needs to be accessed, it must be fetched from far | ||
+ | memory into a buffer in the program space. | ||
+ | problem in accessing a line that there isn't when allocating and storing a | ||
+ | line. When going to read the line, you don't know how big it is, since you | ||
+ | know nothing about it other than its far location. | ||
+ | to do would be to read the first ten bytes of the line record (the header | ||
+ | information) and then use the value in the line-length field to figure out | ||
+ | how many more bytes you need to fetch. | ||
+ | it so that I read the first twenty bytes of a line and then see if the line | ||
+ | has ten or fewer displayable characters on it. If so, then I have | ||
+ | successfully fetched the whole line and I am done in one access. | ||
+ | there is no problem with fetching far memory beyond one record' | ||
+ | (although there certainly would be a problem with stashing)). | ||
+ | I fetch the remaining characters and I am done in two fetches (actually, I | ||
+ | fetch all of the characters for simplicity). | ||
+ | |||
+ | However, often times I don't actually have to fetch the data of a line at | ||
+ | all and I only need to access its header information (to follow or change | ||
+ | its linkage, for example). | ||
+ | of the line and I only need one access to get it since I already know how | ||
+ | long the header is (ten bytes). | ||
+ | place since it is of fixed length. | ||
+ | characters to a line, then I would have to re-allocate a larger line record | ||
+ | for it, free the old line-record storage, and link the new line record in | ||
+ | with the rest of the document (by updating the previous record' | ||
+ | pointer and updating the next record' | ||
+ | necessary global variables... quite a bit or work). | ||
+ | |||
+ | #(A)2.3: 2.3. GLOBAL VARIABLES | ||
+ | |||
+ | This section describes all of the global variables that ZED keeps in order | ||
+ | to edit a document. | ||
+ | areas: | ||
+ | |||
+ | work1 = $02 ;(16) ;used by malloc | ||
+ | work2 = $12 ;(16) ;used by file-load | ||
+ | work3 = $22 ;(14) | ||
+ | |||
+ | Each work area is used by successively higher levels of software in order to | ||
+ | avoid conflicts between layers. | ||
+ | dynamic-memory routines and " | ||
+ | process of loading a file involves a lot of memory-allocation work, so it is | ||
+ | good that they use separate working storage and don't clobber each other. | ||
+ | |||
+ | The following variables are used for managing the screen and the current | ||
+ | cursor column: | ||
+ | |||
+ | scrTopAddr | ||
+ | scrRow | ||
+ | scrCol | ||
+ | scrRows | ||
+ | scrCols | ||
+ | scrStartRow: | ||
+ | scrStartCol: | ||
+ | scrRowInc | ||
+ | scrLeftMargin | ||
+ | statusMargin: | ||
+ | conColor: | ||
+ | |||
+ | Most of these fields are used for interfacing with ACE's direct-access | ||
+ | full-screen-control calls. | ||
+ | to zero-page locations (to reduce code size and to increase performance) and | ||
+ | the others are allocated to absolute memory. | ||
+ | programs to use zero-page locations $02 to $7F for their own purposes. | ||
+ | |||
+ | The current displayed cursor location is stored in " | ||
+ | " | ||
+ | (where display rows start at 2 since the control and separator lines take up | ||
+ | rows 0 and 1), and " | ||
+ | from 0 up to the length of the line. Since this version of ZED features | ||
+ | horizontal scrolling to handle really long display lines, " | ||
+ | also maintained to tell what the column number of the left margin of the | ||
+ | display is. When we refresh the screen, we will display all lines starting | ||
+ | from this character position. | ||
+ | from 0 whereas they are numbered starting from 1 in all dialogue with the | ||
+ | ape at the keyboard. | ||
+ | right or left edge of the screen, a check is made and if this happens, then | ||
+ | the " | ||
+ | giving us horizontal scrolling). | ||
+ | |||
+ | The following variables are used to keep track of various parameters: | ||
+ | |||
+ | targetLen | ||
+ | wrapFlag | ||
+ | modified | ||
+ | modeFlags | ||
+ | statusUpdate | ||
+ | markedLinePtr: | ||
+ | markedLineNum: | ||
+ | markedCol: | ||
+ | |||
+ | " | ||
+ | without exceeding. | ||
+ | of the screen, but it can be set to 240 characters by the " | ||
+ | will eventually be manually settable to any value you want (10< | ||
+ | The " | ||
+ | or whether lines should just be broken at the target length regardless of | ||
+ | whether it gets broken in the middle of a word or not ($80 clear), and | ||
+ | second, tells whether carriage-return characters should be displayed to the | ||
+ | user ($40 set) or not ($40 clear). | ||
+ | represent the carriage return is displayed, taken from the graphical palette | ||
+ | of the current character set). You will normally want carriage returns | ||
+ | displayed when you are using ZED as a word processor, and you will normally | ||
+ | want them not displayed when using ZED as a text editor. | ||
+ | |||
+ | The " | ||
+ | ($80 clear) mode is in effect, and second, whether auto-indent ($40 set) or | ||
+ | no-indent ($40 clear) mode is in effect. | ||
+ | supported and auto-indent is not. Auto-indent is intended to eventually | ||
+ | make programming easier by not requiring you to type a bunch of spaces to | ||
+ | indent a new line of a source file that should be at the same nesting level | ||
+ | as the previous line. | ||
+ | |||
+ | The " | ||
+ | to be done in order to keep the status line at the top of the screen up to | ||
+ | date. If any of the variables that control the values displayed on the | ||
+ | status line change, then the corresponding bit in this variable should be | ||
+ | set. After processing a keystroke but before waiting for the next | ||
+ | keystroke, ZED will update all of the fields that have a ' | ||
+ | variable. | ||
+ | message is currently being displayed on the separator line (between the | ||
+ | status line and the first document line), and if there is, then the message | ||
+ | should be erased (overwritten by the separator characters) _after_ the user | ||
+ | presses the next key (since it wouldn' | ||
+ | couple of milliseconds to read the message). | ||
+ | |||
+ | The " | ||
+ | commands (like delete). | ||
+ | version clear the mark after every modification to the file. The main | ||
+ | reason for this is that it would be a pain in the but to keep track of the | ||
+ | mark in some cases like when the line that is marked gets deleted or | ||
+ | updated, and that having set-mark/ | ||
+ | ape at the keyboard from accidentally hitting a range-destroy key and wiping | ||
+ | out his document (he will get a "range not set" error message instead). | ||
+ | |||
+ | The following variables are used to keep track of the current position in | ||
+ | the document: | ||
+ | |||
+ | linePtr | ||
+ | lineNum | ||
+ | headLinePtr | ||
+ | lineCount | ||
+ | byteCount | ||
+ | |||
+ | " | ||
+ | This is probably the most important global variable. | ||
+ | needed so that we know what line to modify/etc. if the user enteres a | ||
+ | letter/ | ||
+ | line numbers start from 1. This needs to be maintained in order to tell the | ||
+ | ape at the keyboard where in the document he is. These two fields are | ||
+ | sequentially updated as the user moves from line to line in the document. | ||
+ | |||
+ | " | ||
+ | trailer line. As explained above, it is used to find the top and the bottom | ||
+ | of the document. | ||
+ | lines in the current document, and " | ||
+ | Each carriage-return character counts as one byte. Keeping track of line | ||
+ | and byte counts is for convenience rather than necessity. | ||
+ | |||
+ | The following variables manage the "kill buffer", | ||
+ | been deleted but before it's completely discarded (a sort of purgatory): | ||
+ | |||
+ | killBufHeadPtr: | ||
+ | killLineCount: | ||
+ | killByteCount: | ||
+ | |||
+ | The kill buffer is maintained in exactly the same structure that the main | ||
+ | document is: a ring of doubly linked line records. | ||
+ | store the pointer to the special trailer line, the number of data lines in | ||
+ | the kill buffer, and the number of data bytes in the kill buffer, | ||
+ | respectively. | ||
+ | |||
+ | In addition to the kill buffer, there is also a "rub buffer": | ||
+ | |||
+ | RUB_BUFFER_SIZE = 50 | ||
+ | rubBufPtr: | ||
+ | rubBufSize: .buf 1 | ||
+ | rubBuffer: | ||
+ | |||
+ | It is used to hold the fifty single characters that have most recently been | ||
+ | deleted by using either the DEL or Commodore-DEL (Rub). | ||
+ | using the old version of ZED, I would sometimes unintentionally delete a | ||
+ | single character and then want it back, and I had to expend mental effort to | ||
+ | figure out what it was. This mechanism takes the effort out of that job by | ||
+ | maintaining a LIFO (Last In First Out) (circular) buffer controlled by the | ||
+ | variables given above (note that " | ||
+ | be easily changed up to 255 in the source code). | ||
+ | actually contained in the uninitialized-storage section of the program | ||
+ | (" | ||
+ | implemented in the ACEassembler, | ||
+ | equates that replace it). | ||
+ | |||
+ | The Shift-Ctrl-R (rub recall) keystroke is used to recall the previous | ||
+ | character (as if you had typed it in) and has the effect of resetting the | ||
+ | " | ||
+ | row, the " | ||
+ | the one just recalled. | ||
+ | the " | ||
+ | You can recall as few characters as you wish. | ||
+ | |||
+ | Interpreting command keys is done with the following global variables: | ||
+ | |||
+ | keychar | ||
+ | keyshift | ||
+ | sameKeyCount: | ||
+ | sameKeyChar: | ||
+ | sameKeyShift: | ||
+ | |||
+ | ACE returns both a shift pattern and a key character code, so both are | ||
+ | stored. | ||
+ | like Ctrl-R and Shift-Ctrl-R. | ||
+ | keystroke and the number of times that the exact keystroke has been made, so | ||
+ | that slightly different actions can be taken when the same keystroke is made | ||
+ | multiple times, such as with Shift-Ctrl-R (or maybe HOME). | ||
+ | |||
+ | The following global variables are also maintained for various purposes: | ||
+ | |||
+ | exitFlag: | ||
+ | arg: .buf 2 | ||
+ | temp: .buf 4 | ||
+ | stringbuf: | ||
+ | filebuf: | ||
+ | tpaFreemap: | ||
+ | linebuf: | ||
+ | line = linebuf+headLength ;(241) | ||
+ | headBuffer | ||
+ | headNext | ||
+ | headPrev | ||
+ | headLineLe | ||
+ | headFlags | ||
+ | headLength | ||
+ | documentBuf: | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | " | ||
+ | calling program. | ||
+ | " | ||
+ | string processing, and " | ||
+ | processing. | ||
+ | free-memory-page map for making allocations out of the application program | ||
+ | area (or TPA, Transient Program Area). | ||
+ | allocate pages in the application space (since this cannot normally be done | ||
+ | reliably), so a mechanism is needed inside of ZED to make use of this | ||
+ | memory. | ||
+ | |||
+ | " | ||
+ | when it is being accessed or modified. | ||
+ | where the actual line data is stored. | ||
+ | in zeropage and the record-header information from " | ||
+ | these variables whenever a line is fetched and copied from these variables | ||
+ | when a line is stashed to far memory. | ||
+ | since they are manipulated all of the time. | ||
+ | |||
+ | Finally, " | ||
+ | document. | ||
+ | implemented, | ||
+ | switch between an arbitrary number of documents held in memory at any time. | ||
+ | |||
+ | 2.4. LOADING A FILE | ||
+ | |||
+ | When ZED is first started up, its usual first job is to load in the document | ||
+ | that was named on the command line (plus you can load a file at any time | ||
+ | with Ctrl-L). | ||
+ | calls to do this, although there is a bit of business that has to happen to | ||
+ | get the data into the internal form that ZED uses. The job is split into a | ||
+ | number of routines to make it easier to program. | ||
+ | |||
+ | The main routine opens the file for reading and initializes that variables | ||
+ | that the load routine uses. Among other things, the load routine counts up | ||
+ | the number of display lines and physical bytes in the file and must wrap | ||
+ | physical lines into display lines while reading. | ||
+ | perform on-the-fly translation from other file formats to PETSCII and will | ||
+ | perform TAB expansion if requested. | ||
+ | |||
+ | The main routine repeatedly calls subroutines to read a line into the line | ||
+ | buffer, wrap it, and store it to memory. | ||
+ | discussion, we will assume that the " | ||
+ | although it can be set to anything that you want. The Read routine copies | ||
+ | characters from the " | ||
+ | re-filled with file-data characters as necessary in 254-byte chunks (the | ||
+ | natural size of Commodore data sectors, for efficiency). | ||
+ | copied until either a carriage-return (CR) character is encountered or we | ||
+ | reach the 81st character (target+1). | ||
+ | because it may be a CR, and if we are in the normal text-editor mode, we can | ||
+ | store a full 80 data characters on a display line, even if it ends in a CR | ||
+ | (some editors, quite annoyingly, cannot do this). | ||
+ | selects the mode where CRs are visibly displayed on the screen, then we stop | ||
+ | scanning the current display line at a maximum of 80 characters if a CR | ||
+ | isn't encountered. | ||
+ | |||
+ | After the characters of the display line have been put into the line buffer | ||
+ | in the above step, it may be the case that the word at the end of the line | ||
+ | has been abruptly broken in the middle. | ||
+ | this doesn' | ||
+ | " | ||
+ | wrapped to the next line. To do this, we scan from the end of the line back | ||
+ | until we encounter the last space character on the line. Then, we cut the | ||
+ | line immediately after that space, and remember where we cut it so that we | ||
+ | can later process the overflown characters. | ||
+ | line (i.e., the first and only word on the line is longer than the target | ||
+ | length), then we keep it as-is and end up breaking the word abruptly. | ||
+ | that we break the line with a "soft return", | ||
+ | the data by word wrapping. | ||
+ | |||
+ | After the fat (if any) has been trimmed off the current display line, we | ||
+ | want to store it into far memory, into the doubly linked ring structure | ||
+ | discussed above. | ||
+ | to the address of the previous line record (we keep track of this) and set | ||
+ | the pointer to the next line to Null (for now). Then we we allocate memory | ||
+ | for the current line and Stash it out. But we're not done yet; we need to | ||
+ | set the " | ||
+ | allocated line. This can be done by simply writing the 32-bit pointer value | ||
+ | to the start address of the previous line (there is no need to re-fetch the | ||
+ | previous-line contents or header). | ||
+ | |||
+ | And after stashing out the line, we recall where we wrapped it (if we did) | ||
+ | and copy the characters that were cut off to the beginning of the line | ||
+ | buffer and we pretend that we have fetched these from the file as if in the | ||
+ | Load Line step above. | ||
+ | |||
+ | When loading is finished (after we hit End-Of-File (EOF) on the file being | ||
+ | read), we flush the last incomplete line segment, if there was one (a file | ||
+ | is not required to end in a CR) and then we cap things off with the special | ||
+ | trailer line. This trailer line is allocated before we start loading the | ||
+ | file (although I didn't mention it above), and now we set up its links so | ||
+ | that our entire file is the nice doubly linked ring that we like so much. | ||
+ | Now we are finished, and we return the trailer-line pointer, the number of | ||
+ | display lines read in, and the number of physical bytes read in to whomever | ||
+ | called us (it could be the command-line parser, the Ctrl-L (Load) command, | ||
+ | or the Ctrl-I (Insert) command). | ||
+ | |||
+ | There are three reasons why I like having this special trailer line around. | ||
+ | (1) It allows us to not have to worry about Null pointers. | ||
+ | will notice that while stashing a loaded line, I allocated the trailer line | ||
+ | first so that we would always have a " | ||
+ | allows the user to move the cursor beyond the physical end of the document | ||
+ | to do operations like recall (Ctrl-R) a block of text. This was a problem | ||
+ | with the original ZED; you had to go the the end of the file, press RETURN | ||
+ | to open up a blank line, recall the text, and then delete the bogus blank | ||
+ | line. (3) It allows a document to have zero characters in it in a | ||
+ | consistent fashion. | ||
+ | |||
+ | There is also a subtle but complicated issue dealing with dynamic memory | ||
+ | allocation that I haven' | ||
+ | we run out of memory? | ||
+ | gracefully, maintain the integrity of the document as best we can, and | ||
+ | inform the user. In some cases, maintaining the integrity will involve | ||
+ | un-doing committed changes to the document, which is a real pain in the | ||
+ | butt, but which is still very important. | ||
+ | you just made the last keystroke on five hours of editing work and the | ||
+ | program aborted on an "out of memory" | ||
+ | great bit bucket in the sky. | ||
+ | |||
+ | #(A)3: 3. SCREEN DISPLAY, MOVING AROUND | ||
+ | |||
+ | This section discusses the operations that have to do with maintaining the | ||
+ | current secion of the document on the display and moving the cursor around | ||
+ | within the document. | ||
+ | |||
+ | #(A)3.1: 3.1. PAINTING THE SCREEN | ||
+ | |||
+ | This is the essential operation that keeps the screen up to date with the | ||
+ | docment in memory. | ||
+ | it is called with the arguments: a pointer to the starting line to display, | ||
+ | the starting screen line number to start painting at, and the ending screen | ||
+ | line number to end painting at, plus one (lots of endings are 'plus one' | ||
+ | since this allows me to use the BCC instruction). | ||
+ | include general information about the screen for use with the " | ||
+ | kernel functions and the left margin for displaying lines. | ||
+ | |||
+ | This subroutine simply goes through the display lines one by one, displays | ||
+ | the line contents, and advances the line pointer. | ||
+ | the line is fetched into the line buffer from far memory and the number of | ||
+ | displayable characters is calculated according to the line length and the | ||
+ | left-hand display margin. | ||
+ | written to the screen memory and if the line isn't completely full, then the | ||
+ | remainder of the line is filled in with space characters. | ||
+ | completely performed by the " | ||
+ | to be handled is running out of document lines before filling the screen | ||
+ | range. | ||
+ | |||
+ | Attributes (colors) are not used for this operation, since they are not | ||
+ | needed and using them would only slow us down. They display-area color | ||
+ | cells are initialized when ZED starts (as are the status-line and | ||
+ | separator-line color cells) and don't change during operation. | ||
+ | come from the ACE palette (which the user can configure to his own liking). | ||
+ | |||
+ | This subroutine is used to both repaint the entire screen (when necessary) | ||
+ | and to repaint only one line or a few lines (when I can get away with | ||
+ | this). | ||
+ | However, repainting isn't too slow, especially when compared to serial-line | ||
+ | speeds, since screen updates are written directly to screen memory, although | ||
+ | the C64's soft-80 screen is significantly slower than the other screen types | ||
+ | since so much more processor work needs to be done just to make a single | ||
+ | character appear. | ||
+ | |||
+ | In the future, it may be useful to allow this function to abort in the | ||
+ | middle of this operation if the user presses a key before the repainting is | ||
+ | finished, in order to allow the user to work faster. | ||
+ | hold down the Page-Down keystroke, the speed that you go forward in the | ||
+ | document is limited by how fast the screen can be repainted. | ||
+ | operation were abortable, then you could always go forward as fast as the | ||
+ | key repeates, and when you get to where you are going and release the | ||
+ | Page-Down key, the screen would repaint one final time and everything would | ||
+ | be consistent. | ||
+ | consistent or not, in order to make this work. | ||
+ | |||
+ | There is also a function that displays a message in the separator line on | ||
+ | the screen. | ||
+ | the user to scroll through it if the screen is not wide enough to display it | ||
+ | in its entirety. | ||
+ | overwriting it with separator characters. | ||
+ | that updates all of the fields that have changed on the status line. | ||
+ | |||
+ | #(A)3.2: 3.2. MAIN CONTROL | ||
+ | |||
+ | Before I start talking about the implementations of the individual commands, | ||
+ | I should say something about the main control for the program. | ||
+ | initializes and loads the initial document (even if you don't specify one, | ||
+ | ZED will default to the name " | ||
+ | to a small main loop of simply displaying the cursor, waiting for a | ||
+ | keystroke, undisplaying the cursor, calling the subroutine associated with | ||
+ | the keystroke, and repeating. | ||
+ | |||
+ | #(A)3.3: 3.3. END UP, DOWN, LEFT, RIGHT | ||
+ | |||
+ | Moving the current line to the top and bottom of the document is straight | ||
+ | forward, because of the organization that was discussed in the data- | ||
+ | structure secion above. | ||
+ | trailer-line pointer to the current line pointer and then fetch the next | ||
+ | pointer from the trailer line's header; this will give a pointer to the top | ||
+ | line. Then we set the current line number to one and a couple of other | ||
+ | variables and call the subroutine discussed above to repaint the screen. | ||
+ | |||
+ | Going to the bottom of the document would be just as easy as going to the | ||
+ | top, except that we want the last line (the trailer line) to be displayed on | ||
+ | the bottom of the screen in order to present as much useful document content | ||
+ | to the user as possible. | ||
+ | fill a screen, then we cannot, of course, display an entire screen. | ||
+ | |||
+ | To make this business easier, a subroutine is provided that, given a | ||
+ | starting line pointer and a count, will scan until it either hits the | ||
+ | count-th line previous to the given one or it hits the top line of the | ||
+ | document. | ||
+ | (possibly zero), the pointer to the line that it stopped scanning at, and a | ||
+ | flag indicating whether it stopped because it hit the top of the document or | ||
+ | not. This subroutine is quite generally useful. | ||
+ | subroutine that scans downward. | ||
+ | |||
+ | So, after locating the bottom line of the document and setting the line | ||
+ | number, the scan-upwards subroutine is called to scan upwards the number of | ||
+ | displayable lines on the screen. | ||
+ | entirety from the line that was scanned up to, and the new cursor-display | ||
+ | location is computed from the count of the lines that were scanned over. | ||
+ | This works equally well for a long document, a document shorter than the | ||
+ | height of the screen, and an empty document. | ||
+ | |||
+ | The End-Left and End-Right commands are very simple in that they don't even | ||
+ | have to change the current line pointer, but they do have to check if the | ||
+ | cursor has moved off either the left or right edge (margin) of the screen. | ||
+ | The visible columns go from the column number of the left margin, up to that | ||
+ | plus the width of the screen. | ||
+ | then the new left margin will have to be computed and the entire display | ||
+ | will need to be repainted. | ||
+ | |||
+ | This repainting effectively achieves horizontal scrolling. | ||
+ | course, can be up to 240 characters across (241 if you count the carriage- | ||
+ | return character), but the widest screen that ACE supports is 80 columns. | ||
+ | Arguably, the horizontal scrolling could be done more efficiently by moving | ||
+ | the contents of the display left or right by the requred number of columns | ||
+ | and then filling in the opened spaces with the data from the correct columns | ||
+ | of the display lines in memory. | ||
+ | non-trivial and the speedup may not be all that great except for the soft-80 | ||
+ | screen of the C64. A better approach might be to go with the interruptable- | ||
+ | repainting idea that I spoke of earlier, if the current line were updated | ||
+ | first (so that you can see what you're doing) and the rest of the lines | ||
+ | afterwards. | ||
+ | |||
+ | #(A)3.4: 3.4. PAGE UP, DOWN, CURSOR UP, DOWN, LEFT, RIGHT, WORD LEFT & RIGHT | ||
+ | |||
+ | All of these functions follow quite naturally from what is above. | ||
+ | Up and Down, the scan-up or scan-down subroutines already described are | ||
+ | called to find the new current line for the cursor and then the entire | ||
+ | screen is repainted, effectively paging up or down. | ||
+ | |||
+ | For cursor up and down, we just go up or down to the next line in the | ||
+ | document and adjust adjust the cursor location on the screen. | ||
+ | goes off the top or bottom of the screen, then we scroll the screen up or | ||
+ | down as appropriate (ACE can scroll the screen up or down and will | ||
+ | eventually be able to scroll it left and right (although this will be a bit | ||
+ | painful for the soft-80 screen since it may mean scrolling left and right | ||
+ | nybbles)). | ||
+ | the screen to fill in the blank line that we just opened up. Because we use | ||
+ | scrolling and painting only a single line, we can scroll the screen fairly | ||
+ | quickly, easily keeping up with the cursor repeat rate, except on the | ||
+ | soft-80 screen. | ||
+ | |||
+ | For cursor left and right, we advance the cursor one position on the line | ||
+ | and see if it has gone over the edge. If not, then we are done; nothing | ||
+ | needs to be redisplayed. | ||
+ | cursor-up or cursor-down routines to go to the previous/ | ||
+ | position the cursor to either the end or start of the new line. | ||
+ | |||
+ | The word left/right functions are similar to the cursor left/right | ||
+ | functions, except that we keep scanning until we run into the start of the | ||
+ | next word. For word left, this is defined as running into a non-whitespace | ||
+ | character that is preceeded by a whitespace character. | ||
+ | character is defined as either a space, a TAB, a hard return, or the | ||
+ | beginning or ending of the document. | ||
+ | word is defined as a non-whitespace character that is preceeded by a | ||
+ | whitespace character, where we start searching from one position to the | ||
+ | right of the current cursor position. | ||
+ | of the document, then we stop there. | ||
+ | |||
+ | BTW, all of these moving-around functions check the cursor position against | ||
+ | the display bounds and " | ||
+ | gone off the screen. | ||
+ | If the current line is the target-length number of characters long, and the | ||
+ | target length equals the screen width, and carriage returns are selected not | ||
+ | to be displayed, and the left margin of the display is column one | ||
+ | (external), and the cursor is in the target-length-plus-one position of the | ||
+ | line, then the screen is NOT scrolled right. | ||
+ | displayed on the last position of the line and is made to blink fast (an ACE | ||
+ | feature). | ||
+ | right when you are editing a text file on, say, an 80-column screen that has | ||
+ | up to 80-character lines in it. The standalone ACE does this too, when you | ||
+ | logically hit the 81st column. | ||
+ | |||
+ | #(A)4: 4. TEXT INPUT AND " | ||
+ | |||
+ | So far, we can load up a document and whiz around inside of it, but we can't | ||
+ | actually change anything. | ||
+ | modification operations of character input, rub, and delete, and the text | ||
+ | " | ||
+ | full as they can be without going over the target length ("Come on down!" | ||
+ | |||
+ | #(A)4.1: 4.1. TEXT INPUT, DELETION | ||
+ | |||
+ | Adding a single character to a document isn't really very difficult. There | ||
+ | are two modes for single-character inputting: insert and overtype. | ||
+ | mode is generally more useful and more often used, but overtyping can be | ||
+ | very useful when dealing with tabular or specially formatted text. | ||
+ | Therefore, we must support both modes. | ||
+ | mode is the natural mode because the cost of inserting a character can be | ||
+ | so high, but not here. | ||
+ | |||
+ | Actually, there isn't a whole lot of difference in the implementations of | ||
+ | the two modes. | ||
+ | inputted character and store it into the line buffer at the current | ||
+ | position, stash the line back into memory, and repaint the line. For insert | ||
+ | mode, we do the same thing, except that we copy the line from the cursor to | ||
+ | the end to one position beyond the cursor (backwards) and bump its length up | ||
+ | by one before storing the new character on the line. | ||
+ | |||
+ | Rubbing out a character (Commodore-DEL) is done in quite the same way, | ||
+ | except that we copy the rest of the line back one space and decrement the | ||
+ | length. | ||
+ | length of the old line, we have to deallocate the old line and allocate new | ||
+ | memory for the new line, and surgically link it in with the rest of the | ||
+ | document. | ||
+ | |||
+ | The DEL key is handled as if you had typed Cursor Left then RUB, except when | ||
+ | you press DEL on the first column of a line and the previous line ends with | ||
+ | a hard return, the hard return of the previous line is removed instead. | ||
+ | decided to make the RUB (Co-DEL) key return an error instead of joining | ||
+ | lines together like DEL, because sometimes it is convenient to just lean on | ||
+ | the RUB key to delete to the end of a line. | ||
+ | |||
+ | #(A)4.2: 4.2. TEXT SLOSHING | ||
+ | |||
+ | But, we're not done with text modifications yet. If we just left the | ||
+ | modifications as described in the previous sections, we would be end up with | ||
+ | lines that are longer than the target length, with ragged lines, and with | ||
+ | lines that don't join together like they should after pressing DEL in the | ||
+ | first column. | ||
+ | |||
+ | After each of the modifications, | ||
+ | straighten everything up and figure out how to redisplay the screen. | ||
+ | only one line needs to change, but sometimes, many lines or even the whole | ||
+ | screen will have to be updated, as sloshing text can continue for many lines | ||
+ | as line overflows and underflows cascade forward from the line that has just | ||
+ | been modified. | ||
+ | and has many, many special cases. (Although, for all of its complexity, it | ||
+ | is only 400 lines long, although it still needs a few more features). | ||
+ | |||
+ | There are many more cases that could cause sloshing than you might think. | ||
+ | There are the obvious inserting/ | ||
+ | current line, but there is also the case that an insertion or deletion | ||
+ | causes a space character to move to the right position on a line to allow | ||
+ | the line to be sloshed backward, or maybe you remove a space from the end of | ||
+ | a line that creates a word that would be too long to be contained on one | ||
+ | line and therefore needs to be sloshed forward. | ||
+ | |||
+ | The sloshing algorithm doesn' | ||
+ | the body of the document; it just reorganizes the existing characters. | ||
+ | of the spaces are retained at the ends of wrapped lines. | ||
+ | delete spaces, since it is difficult to reconstruct them, since two spaces | ||
+ | are normally between two sentences in text, but it is difficult for a | ||
+ | computer to figure out where a sentence ends. In fact, keeping these spaces | ||
+ | can sometimes cause an anomaly: if all of the spaces won't fit on the end of | ||
+ | one line, then they will be displayed at the beginning of the next line. | ||
+ | |||
+ | The variables that are maintained by the algorithm are as follows: | ||
+ | |||
+ | sloshLinesAltered | ||
+ | sloshRedisplayAll | ||
+ | sloshRedisplayPrev = work2+2 ;(1) ;whether previous line needs to be repainted | ||
+ | sloshMaxChars | ||
+ | sloshTailChar | ||
+ | sloshTheCr | ||
+ | sloshLinesInserted = work2+6 ;(1) ;number of new line records created | ||
+ | sloshLinesDeleted | ||
+ | sloshCurAltered | ||
+ | sloshTerminate | ||
+ | sloshCurTailChar | ||
+ | |||
+ | The algorithm has a main loop that is repeated for each line that can be | ||
+ | sloshed. | ||
+ | into a line that does not need to be sloshed. | ||
+ | cursor line of the main document. | ||
+ | |||
+ | We first look at the previous line and see how many more characters it can | ||
+ | accommodate before being full. Then, we scan the current line from this | ||
+ | point (the number of characters that could potentially be sloshed backwards) | ||
+ | back to the start of the line searching for spaces. | ||
+ | then the current line cannot be sloshed back onto the previous line. If we | ||
+ | do run into a space, then we stop searching and know that we can (and must) | ||
+ | slosh back the current line. So, we remove the characters from the current | ||
+ | line and write it back (maintaining links as appropriate) and then go back | ||
+ | to the previous line and append these characters to it. | ||
+ | |||
+ | If the cursor happened to be on the line in a position that got sloshed | ||
+ | back, then we must adjust the cursor position and move it back to the | ||
+ | previous line. If the previous line is before the start of the screen, | ||
+ | we must set the flag to redisplay the entire screen later. | ||
+ | line is the first line of the slosh area but the cursor didn't get moved | ||
+ | back to the previous line, then we must set the flag to indicate that | ||
+ | we must redisplay the previous line too when we repaint the screen. | ||
+ | |||
+ | If it turns out that we have sloshed back ALL of the characters on the | ||
+ | current line, then we must remove the empty line record of the current line | ||
+ | from the document and adjust the global line count. | ||
+ | about sloshing back a hard return, and if we do, then we bail out of the | ||
+ | algorithm since we are done. Oh, and we have to keep in mind whether we are | ||
+ | displaying carriage returns or not in calculating line lengths. | ||
+ | |||
+ | After shoshing backward, we check if the current line needs to be sloshed | ||
+ | forward. | ||
+ | target length or it ends in a non-space character and the first | ||
+ | word on the next line cannot be sloshed back. The latter is a special case | ||
+ | and needs to be checked for specially, even thought the functionality | ||
+ | for doing so is redundant. | ||
+ | |||
+ | If we do need to slosh forward, we start scanning the current line at the | ||
+ | target-line-length point and scan backwards until we hit the first space. | ||
+ | If there is no space, then the current word is longer than the target length | ||
+ | and must remain abruptly broken over two (or more) lines. | ||
+ | target length. | ||
+ | line right after that space. | ||
+ | something special for lines that end with non-spaces for backward sloshing | ||
+ | too. If the previous line ends in a non-space (presumably because it | ||
+ | contains a single very long word), then we don't find any spaces to slosh | ||
+ | back to the end of the word, then we slosh back as many characters as will | ||
+ | fit, since the word is broken anyway, and we want it to have as many | ||
+ | characters as possible on a single line. | ||
+ | |||
+ | To wrap the line, we set the length of the current line to the new length | ||
+ | and replace the old version of the line in memory. | ||
+ | line record and store the characters that were wrapped in it and link this | ||
+ | line record in with the rest of the document. | ||
+ | here; we don't actually insert the wrapped characters into the next line, | ||
+ | since that would be more complicated, | ||
+ | overflow. | ||
+ | the next line (if necessary) on the next iteration of the main sloshing loop | ||
+ | in a slosh-back operation. | ||
+ | if the cursor was on the part of the line that got wrapped around. | ||
+ | |||
+ | At the end of a loop, we check to see if we have passed a hard return in | ||
+ | the document, in which case, we exit. Otherwise, if either the current | ||
+ | line has been modified or if the current line is the first line to | ||
+ | be sloshed, then we go on to the next line and repeat the above | ||
+ | procedure. | ||
+ | |||
+ | On our way out, we do a little fine tuning of the " | ||
+ | " | ||
+ | described earlier. | ||
+ | portions of the screen display. | ||
+ | comparing the number of lines that have been inserted and deleted from the | ||
+ | document. | ||
+ | doesn' | ||
+ | we need to repaint from the current line all the way to the bottom of the | ||
+ | screen. | ||
+ | |||
+ | The sloshing algorithm currently does not handle non-wrap mode; lines will | ||
+ | always be word wrapped. | ||
+ | if you are not in word-wrap mode. Also, the algorithm can produce an | ||
+ | anomalous wrapping in one case involving lines that end with non-spaces that | ||
+ | I can't seem to remember that this algorithm will fail in (but, the document | ||
+ | will still be interally consistent). | ||
+ | line length while editing a document (which you can't currently do), then | ||
+ | the algorithm may not be able to give optimal word wrapping in all cases | ||
+ | (though, again, the document will always be interally consistent). | ||
+ | |||
+ | #(A)5: 5. OTHER FEATURES | ||
+ | |||
+ | This secion discusses the other features of the editor that have not been | ||
+ | described yet. In general, the operation of this version follows closely | ||
+ | from the standalone version, so you can read its documentation for more | ||
+ | details. | ||
+ | commands, and then I will discuss the operation of a few selected commands. | ||
+ | |||
+ | #(A)5.1: 5.1. COMMAND SUMMARY | ||
+ | |||
+ | Here is a command summary. | ||
+ | feature is currently implemented or not. A blank means " | ||
+ | asterisk means " | ||
+ | read this" (which will be a couple of weeks after I have written this). | ||
+ | " | ||
+ | symbol following it means that the shift status of the key is checked to | ||
+ | distinguish this key. The " | ||
+ | (" | ||
+ | Alt). The " | ||
+ | |||
+ | I CODE KEY ACTION | ||
+ | - ---- ------- | ||
+ | $e0 | ||
+ | * $e1 | ||
+ | $e2 | ||
+ | $e2+ SH-CT-B | ||
+ | $e3 | ||
+ | * $e4 | ||
+ | * $e5 | ||
+ | * $e6 | ||
+ | $e6+ SH-CT-F | ||
+ | $e7 | ||
+ | $e7+ SH-CT-G | ||
+ | * $e8 | ||
+ | * $e9 | ||
+ | $ea | ||
+ | $eb | ||
+ | * $ec | ||
+ | $ed | ||
+ | * $ee | ||
+ | $ef | ||
+ | $f0 | ||
+ | * $f1 | ||
+ | * $f2 | ||
+ | * $f2+ SH-CT-R | ||
+ | * $f3 | ||
+ | $f4 | ||
+ | $f5 | ||
+ | $f6 | ||
+ | $f7 | ||
+ | $f8 | ||
+ | $f9 | ||
+ | * $fa | ||
+ | * $fb | ||
+ | * $fc | ||
+ | * $fd | ||
+ | $fe | ||
+ | $ff | ||
+ | |||
+ | I CODE KEY ACTION | ||
+ | - ---- --- ------ | ||
+ | * $91 | ||
+ | * $11 | ||
+ | * $9d | ||
+ | * $1d | ||
+ | * $06 | ||
+ | * $0b | ||
+ | * $16 | ||
+ | * $17 | ||
+ | * $19 | ||
+ | * $1a | ||
+ | * $0c | ||
+ | * $0f | ||
+ | * $10 | ||
+ | * $15 | ||
+ | |||
+ | * $0d | ||
+ | $8d | ||
+ | $01 | ||
+ | $09 | ||
+ | $02 | ||
+ | $18 | ||
+ | * $14 | ||
+ | * $08 | ||
+ | * $94 | ||
+ | * $13 | ||
+ | * $93 | ||
+ | $04 | ||
+ | $84 | ||
+ | * $0a | ||
+ | * $07 | ||
+ | * $1b | ||
+ | * $0e | ||
+ | * $03 | ||
+ | * $83 | ||
+ | |||
+ | $90 | ||
+ | $05 | ||
+ | $1c | ||
+ | $9f | ||
+ | $9c | ||
+ | $1e | ||
+ | $1f | ||
+ | * $9e | ||
+ | * $12 | ||
+ | * $92 | ||
+ | |||
+ | $81 | ||
+ | $95 | ||
+ | $96 | ||
+ | $97 | ||
+ | $98 | ||
+ | $99 | ||
+ | $9a | ||
+ | $9b | ||
+ | |||
+ | $85 | ||
+ | $89 | ||
+ | $86 | ||
+ | $8a | ||
+ | $87 | ||
+ | $8b | ||
+ | $88 | ||
+ | $8c | ||
+ | $80 | ||
+ | $82 | ||
+ | $8e | ||
+ | $8f | ||
+ | |||
+ | #(A)5.2: 5.2. TEXT SAVE | ||
+ | |||
+ | This function is, of course, implemented, | ||
+ | functions of the editor would be useless without it. It is really quite | ||
+ | simple, because of the data structure of the document. | ||
+ | open the file for writing. | ||
+ | error, then we scratch the old file. Then, we re-open for writing. | ||
+ | |||
+ | To save the file contents, we start at the top line, and fetch each line in | ||
+ | turn until we hit the trailer line of the document, at which point we are | ||
+ | finished. | ||
+ | and if so, we append the line buffer with a carriage return character and | ||
+ | bump up the line length. | ||
+ | line buffer as the argument to write out the line. Writing in this size of | ||
+ | chunk rather than in single bytes gives ACE the opportunity to carry out | ||
+ | this operation as efficiently as it can. | ||
+ | |||
+ | We then close the file and we are done. We display status information to | ||
+ | the user during all phases of this operation, and we certainly tell him if | ||
+ | anything goes wrong. | ||
+ | |||
+ | #(A)5.3: 5.3. RANGE DELETION & RECALL | ||
+ | |||
+ | Range delete and recall are implemented, | ||
+ | general editing. | ||
+ | mark with Ctrl-M (mark) to one end of the range to be deleted, and then move | ||
+ | the cursor to the other end of the range and press Ctrl-D (delete). | ||
+ | text then disappears into the kill buffer and can be recalled any number of | ||
+ | times at any point in the document using the Ctrl-R (recall). | ||
+ | |||
+ | One difference between this ZED and the operations mentioned here are | ||
+ | " | ||
+ | only portions of lines rather than entire lines. | ||
+ | mind that the cursor is logically located " | ||
+ | and the character that the cursor is currently over. For example, if the | ||
+ | cursor was on the " | ||
+ | " | ||
+ | you wanted to delete an entire line (that ended with a hard return), then | ||
+ | you would move the cursor to the first character of the line and press | ||
+ | Ctrl-M and then move the cursor to the first character of the NEXT line and | ||
+ | press Ctrl-D. | ||
+ | operation if you move the cursor to the end of the line to be deleted--this | ||
+ | is one of the reasons for having a displayable trailer line). | ||
+ | |||
+ | To implement the delete operation, all of the lines in the operation are | ||
+ | unlinked from the main document and are linked into the kill buffer. | ||
+ | there already was something in the kill buffer, then it is deallocated and | ||
+ | the kill buffer is cleared. | ||
+ | kill buffer, to make it work consistently with the main document. | ||
+ | lines (potentially, | ||
+ | pain and have to be split into two lines at the point of the mark/ | ||
+ | where one of the broken lines stays with the document and the other goes | ||
+ | into the kill buffer. | ||
+ | extracted region are sewn back together (" | ||
+ | " | ||
+ | lines involved are counted up and are subtracted from the global counts | ||
+ | for the main document. | ||
+ | |||
+ | Ctrl-C (copy) is very similar to the delete operation, except that the data | ||
+ | to be deleted is actually copied to the kill buffer and the document is left | ||
+ | unmodified. | ||
+ | can be emulated with a Ctrl-D followed immediately by a Ctrl-R. | ||
+ | |||
+ | To implement the recall operation, the kill buffer is replicated into a | ||
+ | temporary document and the current line of the main document is broken into | ||
+ | two lines at the recall point (if necessary). | ||
+ | is linked into the main document at the recall point and the text is | ||
+ | " | ||
+ | adjusted, and we are done. | ||
+ | |||
+ | #(A)5.4: 5.4. TEXT SEARCHING | ||
+ | |||
+ | Forward text searching is implemented, | ||
+ | finding things and for moving quickly around in a document. | ||
+ | and Range search and replace are not currently implemented, | ||
+ | less useful). | ||
+ | |||
+ | The implementation is quite straightforward. | ||
+ | (hunt-string) to set the string to search for. The user will input this on | ||
+ | the top line of the screen, and we don't have to do much work for inputting | ||
+ | the string, since ACE already provides a console-input routine complete with | ||
+ | left/right cursor movement and a scroll-back buffer (although it is a bit | ||
+ | hard to use if the input line is longer than the input window on the | ||
+ | screen). | ||
+ | |||
+ | After the search string is set, the user will press Ctrl-F (find) to find | ||
+ | the next occurrence of the string. | ||
+ | starting at the cursor position to the right of the current position. | ||
+ | simple algorithm of keeping a pointer to the current scan position in the | ||
+ | hunt string and pointers to both the current position in the document and to | ||
+ | the position in the document corresponding to the start of the string is | ||
+ | used. | ||
+ | |||
+ | If the current document character matches the current hunt-string character, | ||
+ | then both the document and hunt-string pointers are advanced. | ||
+ | string is exhausted by this, then we have found a match and can stop | ||
+ | searching. | ||
+ | of the hunt string and exit. If the characters don't match, then we move | ||
+ | the current document pointer back to the postition corresponding to the | ||
+ | start of the hunt string, advance it by one, save it, and start searching | ||
+ | again. | ||
+ | main document. | ||
+ | |||
+ | #(A)6: 6. CONCLUSION | ||
+ | |||
+ | So, here we finally have the basic ACE version of the ZED text editor that I | ||
+ | have been promising for a very long time. The new version doesn' | ||
+ | all of the features of the standalone version, but I am working on it. The | ||
+ | new version does, however, include a few features that the old version does | ||
+ | not, like long lines, horizontal scrolling, text " | ||
+ | use additional memory types for storage, the ability to work on the C64, | ||
+ | integration with a command-line environment, | ||
+ | availability (Real Soon Now(TM)). | ||
+ | |||
+ | In order to make ZED operational as a word processor, some means of giving | ||
+ | embedded commands and for formatting and printing these commands must be | ||
+ | provided. | ||
+ | of embedded-command structure, and then I was thinking abouta LaTeX kind of | ||
+ | structure (the LaTeX structure is superior), but I am now thinking that an | ||
+ | HTML type of format-command structure might be rather apropos. | ||
+ | would need to create a print formatter and previewer that might be usable | ||
+ | for other purposes, too. | ||
+ | |||
+ | ============================================================================ | ||
+ | |||
+ | </ | ||
+ | ====== Commodore Trivia ====== | ||
+ | < | ||
+ | by Jim Brain (brain@mail.msen.com) | ||
+ | | ||
+ | #(A): Introduction | ||
+ | |||
+ | Well, the cold has moved in on us in Michigan, but the Commodore information | ||
+ | coming into the house is keeping us warm. Some orphan computers have showed | ||
+ | up, including a Commodore 65 and C116, as well as a couple of Commodore B-128 | ||
+ | computers with all the fixin' | ||
+ | with some brain ticklers for the Commodore know-it-all. | ||
+ | |||
+ | As some may know, these questions are part of a contest held each month on | ||
+ | the Internet, in which the winner receives a donated prize. | ||
+ | those who can received the newest editions of trivia to enter the contest. | ||
+ | |||
+ | This article contains the questions and answers for trivia editions #19-22, | ||
+ | with questions for the current contest, # | ||
+ | |||
+ | If you wish, you can subscribe to the trivia mailing list and receive the | ||
+ | newest editions of the trivia via Internet email. | ||
+ | list, please mail a message: | ||
+ | |||
+ | To: brain@mail.msen.com | ||
+ | Subject: MAILSERV | ||
+ | Body: | ||
+ | subscribe trivia Firstname Lastname | ||
+ | help | ||
+ | quit | ||
+ | |||
+ | #(A): Trivia Questions | ||
+ | |||
+ | Q $120) What is the model number of the assembler/ | ||
+ | |||
+ | A $120) The KIM-5 was the model number of the editor/ | ||
+ | |||
+ | Q $121) How many LEDs are on the KIM-1? | ||
+ | |||
+ | A $121) The basic unit contains 6 7-segment LED displays, or 42 LEDs if | ||
+ | you count each LED in a segment. | ||
+ | |||
+ | Q $122) What is the model number of the REC chip used in the REU? | ||
+ | |||
+ | A $122) MOS 8726. | ||
+ | |||
+ | Q $123) At least two versions of the above chip exist. | ||
+ | physical difference between the versions? | ||
+ | |||
+ | A $123) The eraly versio of the chip (8726-R1) exists in DIP form, while the | ||
+ | 8726-r4-r8 exists as a " | ||
+ | |||
+ | Q $124) Why couldn' | ||
+ | Commodore Plus/4 series? | ||
+ | |||
+ | A $124) Instead of using the de-facto 9 pin D-subminuture connector for the | ||
+ | joysticks, the Plus/4 series used small mini-DIN connectors. | ||
+ | sources claim the older connectors were leaking a fair bit of | ||
+ | radio interference and were preventing the units from attaining | ||
+ | FCC approval, so the connectors were changed to the better-shielded | ||
+ | mini-DIN types. | ||
+ | |||
+ | Q $125) What was the first joystick model Commodore produced that would | ||
+ | function with the Plus/4 computer line? | ||
+ | |||
+ | A $125) The Commodore T-1341 Joystick, which had the special mini-DIN | ||
+ | connector | ||
+ | |||
+ | Q $126) How many computer models are included in the Plus/4 line? | ||
+ | |||
+ | A $126) At last count, 3 models in the Plus/4 series were produced: | ||
+ | |||
+ | The Commodore Plus/4 | ||
+ | The Commodore 16 | ||
+ | The Commodore 116 | ||
+ | |||
+ | Some Commodore 264 models are known to exist, but are not counted, | ||
+ | since the 264 was the prototype model of the Plus/ | ||
+ | model was planned, but only one unit is known to exist. | ||
+ | |||
+ | Q $127) In a normal Commodore disk drive Directory Entry, what relative | ||
+ | offset denotes the start of the program name? | ||
+ | |||
+ | A $127) The filename starts at the 4th byte in the directory entry. | ||
+ | |||
+ | Q $128) How many tracks in a 1541 or 4040 are normally available for use as | ||
+ | storage? | ||
+ | |||
+ | A $128) 35 tracks. | ||
+ | |||
+ | Q $129) How many bytes comprise a single disk drive directory entry? | ||
+ | |||
+ | A $129) 30 bytes. | ||
+ | |||
+ | Q $12A) What is the model number of the Commodore dual drive with a total | ||
+ | capacity per unit of 2.12MB? | ||
+ | |||
+ | A $12A) The Commodore 8250 or 8250LP dual disk drive. | ||
+ | |||
+ | Q $12B) On the drive denoted in $12A, how large could a single sequential | ||
+ | file be? | ||
+ | |||
+ | A $12B) 1.025 megabytes. | ||
+ | |||
+ | Q $12C) At least two version of the Commodore 64C keyboard exist. | ||
+ | the difference between them? Extra Credit: Why? | ||
+ | |||
+ | A $12C) One one keyboard style, the Commodore graphics are printed on the | ||
+ | front of the keys, while they appear above the letters on the keys | ||
+ | in the second type of keyboard. | ||
+ | part except to say that Commodore was always seeking the best deal. | ||
+ | aybe a new keyboard manufacturer got the bid and changed the layout. | ||
+ | |||
+ | Q $12D) On the Commodore 64, what area of memory is swapped out when using an | ||
+ | REU with RamDos? | ||
+ | |||
+ | A $12D) $6000 - $7fff is swapped out when a RAMDOS command is executing. | ||
+ | |||
+ | Q $12E) Commodore manufactured two different versions of the 1541-II drive. | ||
+ | What is the difference between them? | ||
+ | |||
+ | A $12E) The drive mechanisms differ in the two drives. | ||
+ | have by the appearance of the front of the drive. | ||
+ | a rest in the release position, you have the direct drive model. | ||
+ | the lever has no such rest visible, the drive cotains the belt drive | ||
+ | mechanism. | ||
+ | |||
+ | Q $12F) How many colors could the Commodore 1520 plotter plot in? | ||
+ | |||
+ | A $12F) 4. red, black, blue, and green. | ||
+ | |||
+ | Q $130) The Commodore Plus/4 was referred to as the " | ||
+ | |||
+ | A $130) Productivity. | ||
+ | |||
+ | Q $131) Although the Commodore 16 and 116 were functionally equivalent, what | ||
+ | two physical characteristics distinguished one from another? | ||
+ | |||
+ | A $131) Case style and keyboard. | ||
+ | case with keyboard, while the C116 sports a scaled down Plus/4 | ||
+ | style case and " | ||
+ | |||
+ | Q $132) How many pins are there on the Commodore plus/4 expansion port | ||
+ | connector? | ||
+ | |||
+ | A $132) 50 pins. | ||
+ | |||
+ | Q $133) On which side of the Commodore 65 (as it is facing you) did Commodore | ||
+ | place the power switch on? | ||
+ | |||
+ | A $133) The left side. Since the disk drive fills the entire right side, the | ||
+ | left side is an obvious choice, as the swith would require cabling if | ||
+ | installed on the right side. | ||
+ | |||
+ | Q $134) How many keys are on a standard Commodore 128 keyboard? | ||
+ | |||
+ | A $134) 92 keys. | ||
+ | |||
+ | Q $135) What color are the drive LEDs on the SX64 drive? | ||
+ | |||
+ | A $135) There is only one LED, a red in-use LED. | ||
+ | |||
+ | Q $136) True or False? | ||
+ | interchangeable. | ||
+ | |||
+ | A $136) True. | ||
+ | |||
+ | Q $137) On a 1526/MPS 802 printer, how many redefinable characters | ||
+ | were available for use per line of text? | ||
+ | |||
+ | A $137) 1. True fact: In order to print a line of graphics, one must | ||
+ | print a GFX char, do a returb without linefeed (resets the graphic | ||
+ | character, evidently), the tab over and repeat the cycle until 80 | ||
+ | characters were printed. | ||
+ | print 21 pages of GEOWrite text! | ||
+ | |||
+ | Q $138) To set up a redefinable character on the MPS 802/1526 printer, what | ||
+ | secondary address must be opened? | ||
+ | |||
+ | A $138) Secondary address #5. | ||
+ | |||
+ | Q $139) How many pins are in each Euro-DIN plug used on the Plus/4-C16 | ||
+ | joysticks? | ||
+ | |||
+ | A $139) 8 pins. | ||
+ | |||
+ | Q $13A) How many pins are on a regular Commodore VIC-20/C64 joystick | ||
+ | connector? | ||
+ | |||
+ | A $13A) 9 pins. | ||
+ | |||
+ | Q $13B) What BASIC command is used to change from C128 mode to C64 mode on a | ||
+ | C128? | ||
+ | |||
+ | A $13B) go 64. It will ask for confirmation. | ||
+ | |||
+ | Q $13C) What were the four integrated programs included in the infamous | ||
+ | " | ||
+ | |||
+ | A $13C) A word processor, spreadsheet, | ||
+ | program. | ||
+ | |||
+ | Q $13D) Which Commodore serial printer(s) had a small switch that allowed it | ||
+ | to be addressed as either device 4 or device 5? | ||
+ | |||
+ | A $13D) The 1525, MPS 801, and MPS 803 had such a switch. | ||
+ | confirm this, I believe the 1515, the precursor to the 1525, also | ||
+ | had the 4/5 switch. | ||
+ | |||
+ | Q $13E) How many addressable registers does the Commodore VIC-II IC have? | ||
+ | |||
+ | A $13E) There are 47 control registers in the Commodore VIC-II chip. | ||
+ | |||
+ | Q $13F) On a Commodore PET machine, what output appears on the screen after | ||
+ | typing in SAVE "", | ||
+ | |||
+ | A $13F) PRESS PLAY AND RECORD ON TAPE #2 | ||
+ | |||
+ | Q $140) What was the model number of the microprocessor used in the | ||
+ | first of the Commodore 264 Series? | ||
+ | |||
+ | A $140) The early Plus/4 units contained a 7501 microprocessor, | ||
+ | later units featured a 8501 microprocessor. | ||
+ | between the two units is the manufacturing process and die size. | ||
+ | |||
+ | Q $141) How fast could the microprocessor in the Commodore 264 Series | ||
+ | theoretically run at? | ||
+ | |||
+ | A $141) 1.76 MHz. | ||
+ | |||
+ | Q $142) How many colors can a Commodore Plus/4 display at once? | ||
+ | |||
+ | A $142) 8 shades each of 16 colors, but the 8 shades of black are still | ||
+ | still black, so a total of 121 colors are possible. | ||
+ | |||
+ | Q $143) What anomaly exists in the numbering of the BASIC interpreter | ||
+ | in the Plus/4 as 3.5? | ||
+ | |||
+ | A $143) This version contained almost all of the commands in Version 4.0, | ||
+ | plus some new commands for graphics and sound. | ||
+ | |||
+ | Q $144) After the very first 1581 disk drives were introduced, Commodore | ||
+ | found that the WD1770 disk controller chip in the drive could corrupt | ||
+ | the disk in some situations. | ||
+ | IC to fix the problem. | ||
+ | |||
+ | A $144) The Western Digital WD1772 IC. | ||
+ | |||
+ | Q $145) On some very early CBM 1541 drives, what would happen if the serial | ||
+ | bus CLOCK and DATA lines were high upon startup? | ||
+ | |||
+ | A $145) On the very first 1541 drives (I suspect the feature was also on the | ||
+ | 1540 as well), On power-up, the drive would jump to a subroutine at | ||
+ | $E780 after performing the reset routine. | ||
+ | for the high state of CLOCK and DATA. If found, the code would wait | ||
+ | until both go low and then store ' | ||
+ | filename length to 1, and then jumps to the & command, which loads | ||
+ | a USR file and executes it. | ||
+ | |||
+ | Since the Commodore computer never used this feature, and some machines | ||
+ | would boot with these lines randomly high, Commodore removed the | ||
+ | feature. | ||
+ | |||
+ | Q $146) In question $0F8, we learned that one must DIMension an array in | ||
+ | BASIC if it will have more than 11 elements. | ||
+ | produced reference book ncorrectly claims the need to DIMension | ||
+ | arrays for more than 10 elements. | ||
+ | |||
+ | A $146) The Commodore 128 Programmer' | ||
+ | |||
+ | Q $147) Why should serial device number 31 not be used? | ||
+ | |||
+ | A $147) While it is specified as a valid serial bus address, when " | ||
+ | certain commands, it results in a bad command, hanging the bus and | ||
+ | the serial drivers. | ||
+ | |||
+ | Q $148) On most VIC game cartridges from VIC-1910 up, toggling interlaced | ||
+ | screen display can be done with a keypress. | ||
+ | |||
+ | A $148) Press the F7 function key. | ||
+ | |||
+ | Q $149) Which cartidge fitting the criteria in $148 does not toggle interlace | ||
+ | display with the same keypress as the others? | ||
+ | on this cartridge? | ||
+ | |||
+ | A $149) Gorf, VIC-1923. | ||
+ | |||
+ | Q $14A) The Commodore 64 KERNAL and BASIC code use every opcode in the 6510 | ||
+ | CPU except three. | ||
+ | |||
+ | A $14A) BRK, CLV, and SED. | ||
+ | |||
+ | Q $14B) For what purpose does the BASIC interpreter in a Commodore 64 | ||
+ | require the Complex Interface Adaptor (CIA) IC? | ||
+ | |||
+ | A $14B) In order to calculate random values for the BASIC function RND(0), | ||
+ | the first 4 registers of the CIA whose address is provided by the | ||
+ | IOBASE KERNAL routine are read. | ||
+ | |||
+ | Q $14C) On the Commodore 128, the 80 column output is output by the VDC | ||
+ | chip. What does VDC stand for? | ||
+ | |||
+ | A $14C) Video Display Controller. | ||
+ | |||
+ | Q $14D) By now, most people know about the ill-fated Commodore 65. What | ||
+ | were the specifications on the original Commodore 65 idea? | ||
+ | |||
+ | A $14D) A Commodore C64C with a built-in 1581. | ||
+ | |||
+ | Q $14E) When referring to the Commodore 4032, one usually states that | ||
+ | one has a "thin 40" or a "fat 40" | ||
+ | signify? | ||
+ | |||
+ | A $14E) A "thin 40" had a 9" screen and could not be upgraded. | ||
+ | "fat 40" had a 12" screen, and could be upgraded to a 8000 series | ||
+ | machine with some upgrade chips. | ||
+ | |||
+ | Q $14F) If you own a Commodore 4032, how can you tell which kind (thin | ||
+ | or fat) you have? | ||
+ | |||
+ | A $14F) If you hold down the cursor key and it repeats, you have a "fat 40". | ||
+ | (Of course, inspection could also be used, as the " | ||
+ | | ||
+ | |||
+ | Q $150) How nmany keys are on a standard Commodore B-128 keyboard? | ||
+ | |||
+ | A $150) 94 keys. | ||
+ | |||
+ | Q $151) How many revisions of the 1541 printed circuit board are | ||
+ | known to exist? | ||
+ | |||
+ | A $151) For the 1541: | ||
+ | |||
+ | PCB# 1540001 | ||
+ | PCB# 1540008-01 Minor revisions to the 1540001 board. | ||
+ | PCB# 1540048 | ||
+ | PCB# 1540050 | ||
+ | -01 ALPS mechanism | ||
+ | -03 | ||
+ | PCB# 250442-01 | ||
+ | PCB# 250446-01 | ||
+ | PCB# 250446-03 | ||
+ | | ||
+ | For the 1541C: | ||
+ | |||
+ | PCB# 250448-01 | ||
+ | | ||
+ | For the 1541-II: | ||
+ | | ||
+ | PCB# 340503 | ||
+ | | ||
+ | There might be others, but these we can confirm. | ||
+ | if you count the 1541-II board as a 1541 board, 8 if not. | ||
+ | |||
+ | Q $152) The Commodore 6510 CPU has two internal I/O registers. | ||
+ | Commodore 64 are these two registers located at? | ||
+ | |||
+ | A $152) Location $0000 and $0001 | ||
+ | |||
+ | Q $153) The Commodore 64 cotains 64kB of memory. | ||
+ | 64kB? | ||
+ | |||
+ | A $153) 65536 bytes | ||
+ | |||
+ | Q $154) What is the name of the Commodore employee responsible for much of | ||
+ | the Commodore 128 and 65 software development, | ||
+ | accomplishments? | ||
+ | |||
+ | A $154) Fred Bowen. | ||
+ | |||
+ | Q $155) In question $13F, we found out the message that was displayed after | ||
+ | typing SAVE "", | ||
+ | VIC-20? | ||
+ | |||
+ | A $155) The original message, as detailed in Q $13F was: | ||
+ | |||
+ | PRESS PLAY AND RECORD ON TAPE #2 | ||
+ | |||
+ | Commodore found that people were pressing the play buttopn BEFORE the | ||
+ | record button, which would prevent the record button from functioning | ||
+ | in some cases. | ||
+ | |||
+ | PRESS RECORD AND PLAY ON TAPE | ||
+ | |||
+ | To circumvent the problem. | ||
+ | interfaces, so no cassette number was needed. | ||
+ | |||
+ | Q $156) What was the number of Commodore 64 machines sold, within 4 million? | ||
+ | |||
+ | A $156) 17 million | ||
+ | |||
+ | Q $157) What was the number of Commodore 128 machines sold, within 1 million? | ||
+ | |||
+ | A $157) 4.5 million (This information came from Dave Haynie) | ||
+ | |||
+ | Q $158) In 1985, Commodore previewed the Commodore LCD Laptop computer at the | ||
+ | January CES show. How many software packages were to be built-in? | ||
+ | |||
+ | A $158) 8: | ||
+ | | ||
+ | Word Processor | ||
+ | File Manager | ||
+ | Spreadsheet | ||
+ | Address Book | ||
+ | Scheduler | ||
+ | Calculator | ||
+ | Memo Pad | ||
+ | Telecommunications Package | ||
+ | |||
+ | Q $159) In the Commodore LCD unit, what were the text screen dimensions? | ||
+ | |||
+ | A $159) 80 coumns by 16 rows. 1200 characters on screen. | ||
+ | |||
+ | Q $15A) What is the version number of the only known " | ||
+ | IC? | ||
+ | |||
+ | A $15A) 6569-R5. | ||
+ | the Commodore 128 was introduced, so they used the 6569-R3 for the | ||
+ | development of the Vic-IIe chip (8563 series), which is buggy. | ||
+ | So, the newest PAL 64s have a better VIC than the C128. | ||
+ | |||
+ | Q $15B) Machine language programmer typically use the .X register to index | ||
+ | into small arrays. | ||
+ | handled in this way? | ||
+ | |||
+ | A $15B) 256 bytes. | ||
+ | |||
+ | Q $15C) In the mid-1980' | ||
+ | One of the models had a name which was a type of horse. | ||
+ | |||
+ | A $15C) The Commodore " | ||
+ | |||
+ | Q $15D) What is the model number of the first mouse introduced for the | ||
+ | Commodore 64? | ||
+ | |||
+ | A $15D) The 1350. | ||
+ | |||
+ | Q $15E) What was the problem with the mouse in question $15D? | ||
+ | |||
+ | A $15E) As Commodore was either still developing the (now more | ||
+ | popular) 1351 mouse or the 1350 was designed as a lower cost | ||
+ | alternative, | ||
+ | rolled it up, the joystick " | ||
+ | other directions. | ||
+ | |||
+ | Q $15F) If you hold down the cursor key on the CBM 4000 series machine and it | ||
+ | does not repeat, what fact about the machine do you now know? | ||
+ | (other than the key doesn' | ||
+ | |||
+ | A $15F) It is a thin 40XX machine, meaning it could not be upgraded to an | ||
+ | 80XX machine via chip swaps. | ||
+ | |||
+ | ------- A publication describing BASIC on the Commodore makes the claim that | ||
+ | BASIC variables are limited to 5 characters, with the first two being | ||
+ | significant. | ||
+ | |||
+ | ABCDE=5 | ||
+ | ABCDEF=6 | ||
+ | |||
+ | The following questions refer to this claim: | ||
+ | |||
+ | Q $160) What is wrong with the above statement? | ||
+ | |||
+ | Q $161) What causes the variable ABCDEF to fail? | ||
+ | |||
+ | Q $162) How long can variable names really be? | ||
+ | |||
+ | Extra Credit: | ||
+ | |||
+ | ------- The Commodore LCD Computer system, much like the Commodore 65, | ||
+ | was a product that never reached the market. | ||
+ | pint-size CBM machine? | ||
+ | |||
+ | Q $163) How many keys were on the CLCD keyboard? | ||
+ | |||
+ | Q $164) What does LCD in the Commodore LCD stand for? | ||
+ | |||
+ | Q $165) Was an internal modem to be includes? | ||
+ | |||
+ | Q $166) Like the Plus/4 the CLCD unit had integrated software. | ||
+ | were included? | ||
+ | |||
+ | Q $167) How many batteries of what type did the CLCD use for power? | ||
+ | |||
+ | Q $168) Approximately how much did the CLCD unit weigh? | ||
+ | |||
+ | Q $169) What version of BASIC was to be included with the CLCD computer? | ||
+ | |||
+ | Q $16A) The CLCD unit contained a port that could be used with a | ||
+ | Hewlett-Packard device. | ||
+ | |||
+ | Q $16B) What microprocessor did the CLCD unit utilize? | ||
+ | |||
+ | Q $16C) In addition to the usual inclusion of standard Commodore ports, | ||
+ | what two industry standard ports were included on the CLCD? | ||
+ | |||
+ | Q $16D) How much RAM did the CLCD computer include? | ||
+ | |||
+ | Q $16E) How many pixels are on the LCD screen on the CLCD machine? | ||
+ | |||
+ | Q $16F) How much ROM did the CLCD computer contain? | ||
+ | |||
+ | ============================================================================ | ||
+ | </ | ||
+ | ====== Hacking Graphics: Let's Get Graphical ====== | ||
+ | < | ||
+ | by Rick Mosdell (rick.mosdell@canrem.com) | ||
+ | |||
+ | (c) September 1995 (used by permission) | ||
+ | |||
+ | #(A): Introduction | ||
+ | |||
+ | High resolution graphics on the C64 is not all that complicated. How to set | ||
+ | up the VIC-chip to see your bitmap and colors IS, so this will not become | ||
+ | a discussion on which bits to flip or where to put your blocks of data | ||
+ | inside a computer already renowned for its lack of space. Instead, I | ||
+ | am interested in the internal data formats of the only two graphics formats. | ||
+ | |||
+ | #(A): Definitions | ||
+ | |||
+ | nybble | ||
+ | |||
+ | byte the fundamental 8 bit unit of our C64: an 8-bit computer. | ||
+ | |||
+ | word two bytes side by side and related, ie. 16 bits. c64 pointers | ||
+ | into RAM are lo/hi byte style. | ||
+ | |||
+ | bitmap | ||
+ | bits or bit-pairs take a fore-ground color and others take on | ||
+ | a background color. | ||
+ | |||
+ | color-ram | ||
+ | thus completing the picture. | ||
+ | |||
+ | color nybble | ||
+ | space 2 colors fit into 1 byte. | ||
+ | |||
+ | LORES | ||
+ | normal 256-byte character set. Extensive use of the graphics | ||
+ | characters in lowercase plus RVSon/ | ||
+ | graphic files and are text files stored in SEQ format. | ||
+ | |||
+ | MEDRES | ||
+ | |||
+ | HIRES this refers to Doodle files and their derivatives. | ||
+ | |||
+ | #(A): Doodle! | ||
+ | |||
+ | This graphics format is the simplest of all! Here the screen is | ||
+ | divided into 64000 pixels of light (320x200) and is truly HIRES. Neither | ||
+ | the text color-ram at $D800 nor the 4 background colors at $D021 apply at | ||
+ | all. The downside is that only 2 colors can be displayed at one time in an | ||
+ | 8x8 pixel block. This is the format geoPaint uses (but allows for a whole | ||
+ | page displayed a screenful at a time). These files are prefixed with | ||
+ | " | ||
+ | at $5C00. Internally, the 1K of color (1024 bytes) is first followed by 8K | ||
+ | of bitmap (8192 bytes). The " | ||
+ | which makes sense since they are 9K long (36+ disk sectors each 254 | ||
+ | bytes). | ||
+ | color-ram while the " | ||
+ | Simple, straight-forward and direct! Some artists might find this | ||
+ | color restriction too hazardous to their health. Since our screen is | ||
+ | 320x200 pixels (64000 total remember?) dividing by 8 will give us only | ||
+ | 8000 bytes needed for the bitmap and only 1000 bytes necessary for | ||
+ | the color-ram. So this format actually wastes 216 bytes! Careful placement | ||
+ | of colors can result in spectacular HIRES pictures though: look for | ||
+ | the " | ||
+ | and " | ||
+ | by Fuzzy Fox): | ||
+ | |||
+ | * OCP Art Studio | ||
+ | * RUN Paint HIRES | ||
+ | * SID/PIC HIRES | ||
+ | * (geoPaint) | ||
+ | |||
+ | #(A): Koala Paint | ||
+ | |||
+ | Koala is certainly the most colorful and interesting format. Here | ||
+ | the screen is MEDRES, resulting in dots double pixel width for a resolution | ||
+ | of 32000 elements (160x200). The loss of resol- ution is compensated by | ||
+ | the ability to display 4 colors at once in each 8x8 pixel block. Here you | ||
+ | have 2 blocks of color-ram, one wherever you put it AND the normal | ||
+ | color-ram at $D800. Your picture is also effected screen-wide by | ||
+ | the background color at $D021. These files, prefixed by " | ||
+ | PRG files that load at $6000. The same files, when compressed, are prefixed | ||
+ | by " | ||
+ | you cannot delete these files normally. It is made by pressing CBM-1 | ||
+ | (orange) and is hex $81 (decimal 129). The only way I know to scratch | ||
+ | these files is by typing: | ||
+ | |||
+ | | ||
+ | |||
+ | Where DV is your current device. Here the creators of Koala were smart | ||
+ | and wasted NO space. Internally the file contains 8000 bytes for the | ||
+ | bitmap(not 8192 bytes), 1000 bytes (not 1024) for the movable color-ram, | ||
+ | 1000 bytes for the color-ram at $D800, and (this IS important) ONE more | ||
+ | byte for the background color. The length ends up at 41 blocks which is | ||
+ | ok considering it is about 10K long. These double width dots are called | ||
+ | bit-pairs and they draw their colors from various sources: | ||
+ | |||
+ | %00 from the background color at $D021 | ||
+ | %01 from the high nybble of the movable color-ram | ||
+ | %10 from the low nybble of the movable color-ram | ||
+ | %11 from the low nybble of the normal color-ram at $D800. | ||
+ | |||
+ | Interesting eh? There' | ||
+ | formats would be: | ||
+ | |||
+ | * Advanced OCP Art Studio | ||
+ | * Artist64 | ||
+ | * Blazing Paddles | ||
+ | * RUN Paint MEDRES | ||
+ | * SID/PIC multi-color | ||
+ | |||
+ | #(A): Conclusion | ||
+ | |||
+ | Although I am not an expert on graphics screens (not am I claiming to be), | ||
+ | I think programmers should be aware of these two poular formats for | ||
+ | storing and displaying graphics on the Commodore 64/ | ||
+ | | ||
+ | ============================================================================ | ||
+ | </ | ||
+ | ====== ? DS, DS$: rem The Error Channel ====== | ||
+ | < | ||
+ | |||
+ | In Commodore Hacking Issue #10, the end of the " | ||
+ | article was omitted. | ||
+ | |||
+ | Certain early revisions of C=Hacking #10 are missing the end of the article | ||
+ | by Alan Jones entitled " | ||
+ | C64 Without Memory" | ||
+ | |||
+ | #(A)sid: Second SID Chip Installation (Line 137 on) | ||
+ | (c) 1987 Mark A. Dickenson | ||
+ | |||
+ | Here comes the difficult part to explain. | ||
+ | circuit for the audio output. | ||
+ | |||
+ | |||
+ | |||
+ | Pin 27 on | ||
+ | SID chip | ||
+ | --. 10k ohm | ||
+ | 27!----.--/ | ||
+ | --' | ||
+ | | ||
+ | < | ||
+ | > | ||
+ | < | ||
+ | | ||
+ | | ||
+ | | ||
+ | ground--- | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | ! | ||
+ | === 1000 pf (.001mf) | ||
+ | | ||
+ | ! | ||
+ | ---ground | ||
+ | - | ||
+ | |||
+ | |||
+ | You can get the 12 volts you need for the transistor directly from pin #28 of | ||
+ | the SID chip. | ||
+ | |||
+ | If you need any help on constructing this circuit check out any of the | ||
+ | many books that have schematics on the C-64. This is similar to the one | ||
+ | already inside the C-64. | ||
+ | |||
+ | The ground wire from the RCA plug can be soldered to the main grounding | ||
+ | strip between the serial and video ports. | ||
+ | connected to the negative side of the 10uf electrolitic capacitor. | ||
+ | |||
+ | I still think you should have someone familier with electronics install | ||
+ | this circuit for you. | ||
+ | |||
+ | If you have a problem with some cartridges, you will have to install | ||
+ | a switch between pin #25 of BOTH SID chips. | ||
+ | extra SID chip, effectivly turning it off. I would suggest that you turn | ||
+ | OFF the computer before you turn the extra SID chip ON or OFF with this | ||
+ | switch. | ||
+ | |||
+ | A good place to mount the switch and RCA plug is on the back of the | ||
+ | computer and above the monitor jack on the 64. I still haven' | ||
+ | place on the 128. A suggestion was made that if you are not going to use | ||
+ | the RF output on the computer, you can cut the wire going to that RCA plug. | ||
+ | Then connect your audio output wire to the center connector of the plug. This | ||
+ | does work but BE CAREFUL! | ||
+ | |||
+ | Good luck on the construction. | ||
+ | |||
+ | |||
+ | Mark A. Dickenson | ||
+ | |||
+ | #(A)linear: SOLVING LARGE SYSTEMS OF LINEAR EQUATIONS ON A C64 | ||
+ | by Alan Jones (alan.jones@qcs.org) WITHOUT MEMORY (Line 239 on) | ||
+ | |||
+ | PROC slv(n#, | ||
+ | OSED | ||
+ | // This routine solves a system of equations using the quartersolve | ||
+ | // algorithm with partial pivoting. | ||
+ | // It is called a "line at a time" and uses only | ||
+ | // 0.25*nn memory locations which enables larger problems to be solved | ||
+ | |||
+ | Slv calls the swap' | ||
+ | package. | ||
+ | |||
+ | It does exactly what it says, e.g. swap' | ||
+ | t:=a; a:=b; b:=t. | ||
+ | |||
+ | Slv calls the sdot, isamax#, sswap, sscal, saxpy, and scopy routines | ||
+ | from the blas package. | ||
+ | it could, and should, be placed on EPROM. | ||
+ | |||
+ | Basic Linear Algebra Subroutines, | ||
+ | |||
+ | The BLAS were originally written for the Fortran language to speed | ||
+ | execution and streamline code used for solving linear algebra and other | ||
+ | matrix problems. | ||
+ | perhaps the best known. | ||
+ | highly optimized for a particular computer, coded in ML or a High Order | ||
+ | Language. | ||
+ | Writing fast efficient programs is then a simple matter of selecting the | ||
+ | best solution algorithm and coding it in a manner that makes best use of | ||
+ | the blas routines. | ||
+ | precision, and complex numbers. | ||
+ | rows or columns of an array and typicaly do n scalar operations | ||
+ | replacing the inner most loop of code. There are also level 2 BLAS that | ||
+ | perform n*n operations and Level 3 BLAS that perform n*n*n operations. | ||
+ | Nicholas Higham has coded most of the single precision level 1 blas | ||
+ | routines and put them in a Comal 2.0 package. | ||
+ | included on the Packages Library Volume 2 disk. I am not aware of ML | ||
+ | blas routines coded for any other C64/128 languages although this is | ||
+ | certainly possible and recommended. | ||
+ | |||
+ | The Comal blas routines behave exactly the same way that the Fortran | ||
+ | blas routines do except that Fortran can pass the starting address of an | ||
+ | array with just " | ||
+ | allow you pass an array, by reference, of single or multiple dimensions | ||
+ | and start from any position in the array. | ||
+ | as ordinary Comal routines you have to pass additional parameters and | ||
+ | have separate routines for single dimensioned arrays and two dimensional | ||
+ | arrays. | ||
+ | columns, and Comal (like many other languages) stores two dimensional | ||
+ | arrays by rows. If you translate code between Fortran and Comal using | ||
+ | blas routines you will have to change the increment variables. | ||
+ | |||
+ | Fortran | ||
+ | dimension c(n), a(ilda, | ||
+ | scopy(n, | ||
+ | scopy(n, | ||
+ | |||
+ | The first scopy copies array c into the ith row of array a. The second | ||
+ | scopy copies array c into the jth column of array a. | ||
+ | |||
+ | This is what scopy does in Fortran: | ||
+ | |||
+ | subroutine scopy(n, | ||
+ | real sx(1),sy(1) | ||
+ | ix=1 | ||
+ | iy=1 | ||
+ | do 10 i = 1,n | ||
+ | sy(iy) = sx(ix) | ||
+ | ix = ix + incx | ||
+ | iy = iy + incy | ||
+ | 10 continue | ||
+ | return | ||
+ | end | ||
+ | |||
+ | The Comal BLAS does exactly the same thing. | ||
+ | rather than as a package it would have to be different. | ||
+ | change. | ||
+ | |||
+ | scopy(n#, | ||
+ | scopy(n#, | ||
+ | |||
+ | PROC scopy(n#, REF x(), ix#, incx#, REF y(,), iy#, jy#, sdy#, incy#) CLOSED | ||
+ | iyinc#: | ||
+ | jyinc#: | ||
+ | FOR i#=1 TO n# DO | ||
+ | y(iy#, | ||
+ | ix#:+incx#; iy#: | ||
+ | ENDFOR | ||
+ | ENDPROC scopy | ||
+ | |||
+ | Note that more information has to be passed to the procedure and used | ||
+ | that the ML blas picks up automatically. | ||
+ | procedures to handle every combination of single and multi dimensional | ||
+ | arrays. | ||
+ | considerations this should also be left as an open procedure or better | ||
+ | yet just use in line code. | ||
+ | |||
+ | Here is a very simplified description of what each of the routines in | ||
+ | the Comal BLAS package does. | ||
+ | |||
+ | sum: | ||
+ | sum:=0 | ||
+ | FOR i#:=1 TO n# DO sum: | ||
+ | |||
+ | saxpy(n#, | ||
+ | FOR i#:=1 TO n# DO y(i# | ||
+ | |||
+ | prod: | ||
+ | prod:=0 | ||
+ | FOR i#:=1 TO n# DO prod: | ||
+ | |||
+ | sswap(n#, | ||
+ | FOR i#:=1 TO n# DO t:=x(i#); x(i# | ||
+ | |||
+ | scopy(n#, | ||
+ | For i#:=1 TO n# DO y(i# | ||
+ | |||
+ | max#: | ||
+ | | ||
+ | t:=0; max#:=1 | ||
+ | FOR i#:=1 TO n# | ||
+ | IF ABS(x(i# | ||
+ | ENDFOR i# | ||
+ | |||
+ | sscal(n#, | ||
+ | FOR i#:=1 TO n# DO x(i# | ||
+ | |||
+ | snrm2(n#, | ||
+ | norm2:=0 | ||
+ | FOR i#:=1 TO n# DO norm2: | ||
+ | norm2: | ||
+ | |||
+ | srot(n#, | ||
+ | FOR i#:=1 TO n# DO | ||
+ | t:=c*x(i#) + s*y(i#) | ||
+ | y(i# | ||
+ | x(i#):=t | ||
+ | ENDFOR i# | ||
+ | |||
+ | |||
+ | Bear in mind that each of these simple examples can be more complex as | ||
+ | was given for scopy. | ||
+ | BLAS routines in ML or the programming language of your choice, or to | ||
+ | expand the BLAS routine calls in slv to ordinary in line code. | ||
+ | |||
+ | You can also apply the BLAS routines in creative ways besides just | ||
+ | operating on rows or columns. | ||
+ | matrix with: | ||
+ | |||
+ | DIM a(n#,n#) | ||
+ | a(1,1):=1; a(1,2):=0 | ||
+ | scopy(n# | ||
+ | scopy(n# | ||
+ | |||
+ | References | ||
+ | |||
+ | 1. Zambardino, R. A., " | ||
+ | Partial Pivoting and Reduced Storage Requirements", | ||
+ | Vol. 17, No. 4, 1974, pp. 377-378. | ||
+ | |||
+ | 2. Orden A., " | ||
+ | in Mathematical Methods for Digital Computers, Vol. 1, Edited by A. | ||
+ | Ralston and H. Wilf, John Wiley and Sons Inc., 1960. | ||
+ | |||
+ | 3. Dongarra, J. J., Moeler, C. B., Bunch, J. R., Stewart, G. W., | ||
+ | Linpack Users' Guide, SIAM Press, Philadelphia, | ||
+ | |||
+ | ============================================================================ | ||
+ | </ | ||
+ | ====== The Next Hack ====== | ||
+ | < | ||
+ | |||
+ | "But wait, there' | ||
+ | until next issue for it. Here's a little appetizer of what's ahead in | ||
+ | Commodore Hacking issue #12 | ||
+ | |||
+ | o All you cross-development folks, listen up! Issue #12 will enter the | ||
+ | realm of cross-compilers with Craig Bruce as he details the construction | ||
+ | of a high level language cross compiler. | ||
+ | | ||
+ | from BASIC, C, and Pascal. Concepts like declaration handling, expression | ||
+ | | ||
+ | | ||
+ | |||
+ | o Gearing up for the 65C816S. | ||
+ | | ||
+ | C64, accelerated or not, discuss pitfalls in code migration, and | ||
+ | | ||
+ | |||
+ | o SLIP, Sliding away.... | ||
+ | | ||
+ | | ||
+ | |||
+ | o Here Boy, here Boy! Good Dog. The " | ||
+ | | ||
+ | |||
+ | o The RumorMonger. | ||
+ | may vary... | ||
+ | |||
+ | o All that and C=Hacking' | ||
+ | |||
+ | So, set aside a place on that disk drive for the next issue now, because you | ||
+ | won't want to miss it... | ||
+ | |||
+ | ============================================================================ | ||
+ | </ |
magazines/chacking11.txt · Last modified: 2015-04-17 04:34 by 127.0.0.1