Compute! Publications, Inc.
Part of ABC Consumer Magazines, Inc.
One of the ABC Publishing Companies
Greensboro, North Carolina
“SpeedScript 3.0: All Machine Language Word Processor for Atari” was originally published in COMPUTE! magazine, May 1985, copyright 1985, COMPUTE! Publications, Inc.
Copyright 1985, COMPUTE! Publications, Inc. All rights reserved.
Reproduction or translation of any part of this work beyond that permitted by Sections 107 and 108 of the United States Copyright Act without the permission of the copyright owner is unlawful.
Printed in the United States of America
10 9 8 7 6 5 4 3 2 1
ISBN 0-87455-003-3
The author and publisher have made every effort in the preparation of this book to insure the accuracy of the programs and information. However, the information and programs in this book are sold without warranty, either express or implied. Neither the author nor COMPUTE! Publications, Inc. will be liable for any damages caused or alleged to be caused directly, indirectly, incidentally, or consequentially by the programs or information in this book.
The opinions expressed in this book are solely those of the author and are not necessarily those of COMPUTE! publications, Inc.
COMPUTE! Publications, Inc., Post Office Box 5406, Greensboro, NC 27403, (919) 275-9809, is one of the ABC Publishing Companies and is not associated with any manufacturer of personal computers. Atari 400, 800, 600XL, 800XL, 1200XL, and XE are trademarks of Atari, Inc.
SpeedScript is the most popular program ever published by COMPUTE! Publications. Ever since it first appeared in the January 1984 issue of COMPUTE!’s Gazette, the letters have been pouring in. People wanted to know more about the program and word processing, and they had countless suggestions about how to make SpeedScript better.
The result is SpeedScript 3.0, an even more powerful word processor for all eight-bit Ataris (including the 400/800, 600XL/800XL, 1200XL, and new XE series). Enhanced with additional commands and features, this all machine language word processor gives you all the things you expect from a commercial software package. You can write, edit, format, and print anything from memos to novels on your Atari. With a few keystrokes you can change the color of the screen and its text to whatever combination best suits you.
It’s easy to add or delete words, letters, even whole paragraphs. You can search through an entire document and find every occurrence of a particular word or phrase, then replace it with something new. Of course, when you finish writing, you can save your work to tape or disk.
The ability to quickly change the appearance of a printed document is one of the things that make word processing so efficient. SpeedScript lets you alter the margins, page length, spacing, page numbers, page width, as well as set up headers and footers at the top and bottom of the paper.
And once you’ve formatted your document, you’ll find enough print features to make even the most demanding writer happy. With SpeedScript, you can start printing at any page, force the printer to create a new page at any time, even make it wait while you put in another sheet of paper. Underlining and centering are simple. If you want to get fancy, you can use your printer’s codes to create graphics symbols or logos. And if you’re writing something really long—perhaps a novel or term paper—SpeedScript lets you link any number of files so that they print out as one continuous document.
In addition to the SpeedScript program for the Atari, you’ll find complete documentation and a keyboard map in this book. SpeedScript’s source code has also been included for your examination. By studying it, you’ll see exactly how the program is put together.
“The Machine Language Editor: MLX” makes typing in the program easier. MLX almost guarantees that you’ll have an error-free copy of the program the first time you type it in. If you prefer to purchase a copy of SpeedScript on disk rather than type it in, just use the convenient coupon in the back, or call toll-free 1-800-334-0868.
SpeedScript is an exceptionally easy-to-use and powerful word processor that will meet all your writing needs.
SpeedScript has become one of the most popular word processors for the Commodore 64, VIC-20, and Apple computers. And now SpeedScript has been translated to run on all eight-bit Ataris with at least 24K, with either disk or cassette (including the 400, 800, 600XL with memory expansion, 800XL, 1200XL, and new XE series). SpeedScript compares favorably with commercial word processors and has some features never seen before in an Atari word processor. It represents unique value in a type-in program.
SpeedScript 3.0, though compact in size (8K), has many features found on commercial word processors. SpeedScript is also very easy to learn and use. You type in everything first; preview and make corrections on the screen; insert and delete words, sentences, and paragraphs; then print out an error-free draft, letting SpeedScript take care of things like margins, centering, headers, and footers.
Atari SpeedScript is the longest machine language program we’ve ever published, but COMPUTE!’s “MLX” entry system helps you type it right the first time. MLX can detect most errors people make when entering numbers. (See the instructions for using MLX in chapter 2.) MLX also lets you type SpeedScript in more than one sitting. Although the program listing is lengthy, we guarantee the effort will be worthwhile.
After you run the Atari version of MLX, answer the first two questions like this:
Next, you’ll be asked “Tape or Disk.” SpeedScript can be saved as either a binary file on disk or as a boot tape. Press T for use with a tape drive. If you press D for disk, you’ll be asked “Boot Disk or Binary File.” Press F to select the Binary File option. Although you could save SpeedScript as an autobooting disk, it makes no sense, because such a disk cannot contain DOS, which is necessary for file-oriented disk access.
The screen will then show the first prompt, the number 7936 followed by a colon (:). Type in each three-digit number shown in the listing. You do not need to type the comma shown in the listing. MLX inserts the comma automatically.
The last number you enter in each line is a checksum. It represents the values of the other numbers in the line summed together. If you type the line correctly, the checksum calculated by MLX and displayed on the screen should match the checksum number in the listing. If it doesn’t match, you will have to retype the line. MLX is not foolproof, though. It’s possible to fool the checksum by exchanging the positions of the three-digit numbers. Also, an error in one number can be offset by an error in another. MLX will help catch your errors, but you must still be careful.
If you want to stop typing the listing at some point and pick up later, press CTRL-S and follow the screen prompts. (For disk, MLX will ask you to specify a filename; do not use AUTORUN.SYS until the entire listing is typed in.) Remember to note the line number of the last line you entered. When you are ready to continue typing, load MLX, answer the prompts as you did before, then press CTRL-L. For a boot tape, be sure the cassette is in the tape drive and rewound. For a binary disk file, MLX asks for the filename you gave to the partially typed listing. After the LOAD is complete, press CTRL-N and tell MLX the line number where you stopped. Now continue typing as before.
When you finish all typing, MLX automatically prompts you to save the program. For disks with Atari DOS 2.0 or 3.0, save the completed program with the filename AUTORUN.SYS. This will allow SpeedScript to load and run automatically when the disk is booted.
At this point, MLX has saved either a boot tape or binary disk file. To load your boot tape, remove all cartridges, rewind the tape, and hold down the START button while turning on the power. (On the 600XL, 800XL, and XE series, disable BASIC by holding down both START and OPTION while turning on the power.) When the computer turns on, you’ll hear a single beep tone. (On the XL and XE series, make sure the volume is turned up on your TV or monitor.) Press PLAY on the tape drive, then press any key on the keyboard to start the load. SpeedScript will automatically run once the boot is successfully completed.
To use SpeedScript with an Atari DOS disk, you must save or copy it on a disk which also contains DOS.SYS and DUP.SYS. Since you’ve saved SpeedScript as AUTORUN.SYS, it will automatically load and run when you turn on your computer with this disk in the drive. (On the 600XL, 800XL, and XE series, disable BASIC by holding down OPTION when switching on the computer.) SpeedScript must always be named AUTORUN.SYS in order to load properly with Atari DOS. If you want to prevent it from automatically running for some reason, you can save it with another name, then rename it AUTORUN.SYS later.
If you’re using Optimized System Software’s OS/A+ DOS or a compatible successor, you can give SpeedScript any filename you like. Just use the LOAD command from DOS, and SpeedScript will automatically run. Or you can give it a filename with the extension .COM, such as SPEED.COM. Then you can start up by just typing SPEED at the DOS prompt. You can also write a simple batch file to boot up SpeedScript automatically. Some enhanced DOS packages like Optimized System Software’s DOS XL may use so much memory that they conflict with SpeedScript. In this case, you’ll need either to use Atari DOS instead on your SpeedScript disks or to reassemble the source code at a higher address to avoid conflicts.
Note: The AUTORUN.SYS file on your DOS master disk is responsible for booting up the 850 Interface Module for RS-232 communications. There is no easy way to combine the 850 boot program with SpeedScript, so you can’t access the R: device. We’ll show you later how to transfer files over a modem or print to a serial printer.
If you prefer, Atari SpeedScript is available for purchase on disk. To order the disk, use the coupon in the back of this book or call COMPUTE! Publications toll-free at 800-334-0868.
When you run SpeedScript, the screen colors change to black on white. The first line on the screen is black with white letters. SpeedScript presents all messages on this command line. The remaining 18 lines of the screen are used to enter, edit, and display your document. SpeedScript makes use of a special, but little-used, Atari character mode that permits larger, more readable characters with true lowercase descenders. The screen still shows up to 40 columns; only five rows are sacrificed. We think you’ll agree that this is the most readable text you’ve ever seen on an Atari—perfect for word processing. (Technical note: SpeedScript starts at $1F00, and the ANTIC 3 character set is embedded at $2000.)
The cursor, a blinking square, shows where the next character you type will appear on the screen. SpeedScript lets you move the cursor anywhere within your document, making it easy to find and correct errors.
To begin using SpeedScript, just start typing. When the cursor reaches the right edge of the screen, it automatically jumps to the beginning of the next line, just as in BASIC. But unlike BASIC, SpeedScript never splits words at the right edge of the screen. If a word you’re typing won’t fit at the end of one line, it’s instantly moved to the next line. This feature, called word-wrap, or parsing, also helps to make your text more readable.
When you finish typing on the last screen line, SpeedScript automatically scrolls the text upward to make room for a new line at the bottom. Imagine the screen as an 18-line window on a long, continuous document. If you’ve unplugged all cartridges or disabled BASIC as described above, there’s room in memory for 3328 characters of text with 24K RAM and up to 27,904 characters on a 48K machine. (Unfortunately, SpeedScript 3.0 cannot make use of the extra memory available in the XL and XE series.) An additional 2K of text memory is available if SpeedScript is loaded from a boot tape. To check at any time how much unused space is left, press CTRL-U (hold down the CTRL key while pressing the U key). The number appearing in the command line indicates how much unused room remains for characters of text.
If you’re used to a typewriter, you’ll have to unlearn some habits if this is your first experience with word processing. Since the screen is only 40 columns wide, and most printers have 80-column carriages, it doesn’t make sense to press RETURN at the end of each line as you do on a typewriter. SpeedScript’s word-wrap takes care of this automatically. Press RETURN only when you want to force a carriage return to end a paragraph or limit the length of a line. A return-mark appears on the screen as a crooked left-pointing arrow.
Most features are accessed with control key commands—you hold down CTRL while pressing another key. In this book, control key commands are abbreviated CTRL-x (where x is the key you press in combination with CTRL). An example is the CTRL-U mentioned above to check on unused memory. CTRL-E means hold down CTRL and press E. Sometimes you must also hold down the OPTION button to select a special option of a command, such as OPTION-CTRL-H. Other keys are referenced by name or function, such as DELETE/BACK S for the backspace key, CTRL-CLEAR for the clear-screen key, and cursor left or CTRL-+ for the cursor-left key. (See the “Keyboard Map,” for a summary of the keyboard commands.)

Some keys let you move the cursor to different places in the document to make corrections or scroll text into view. You can move the cursor by character, word, sentence, or paragraph. Here’s how to control the cursor:
For special applications, if you ever need to type the actual character represented by a command or cursor key, press ESC before typing the CTRL key. Press ESC twice to get the ESCape character, CHR$(27).
Sometimes you’ll have to insert some characters to make a correction. Use CTRL-INSERT to open up a single space, just as in BASIC. Merely position the cursor at the point where you want to insert a space, and press CTRL-INSERT.
It can be tedious to use CTRL-INSERT to open up enough space for a whole sentence or paragraph. For convenience, SpeedScript has an insert mode that automatically inserts space for each character you type. In this mode, you can’t type over characters; everything is inserted at the cursor position. To enter insert mode, press CTRL-I. To cancel insert mode, press CTRL-I again. To let you know you’re in insert mode, the black command line at the top of the screen turns blue.
Insert mode is the easiest way to insert text, but it can become too slow when inserting near the top of a very long document because it must move all the text following the cursor position. So SpeedScript has even more ways to insert blocks of text.
One way is to use the TAB key. It is programmed in SpeedScript to act as a five-space margin indent. To end a paragraph and start another, press RETURN twice and press TAB. TAB always inserts; you don’t need to be in insert mode. You can also use TAB to open up more space than CTRL-INSERT. (You cannot set or clear tab stops in SpeedScript as you can with the normal screen editor.) No matter how much space you want to insert, each insertion takes the same amount of time. So the TAB key can insert five spaces five times faster than pressing CTRL-INSERT five times.
There’s an even better way, though. Press SHIFT-INSERT to insert 255 spaces (it does not insert a line; use RETURN for that). You can press it several times to open up as much space as you need. And SHIFT-INSERT is fast. It inserts 255 spaces as fast as CTRL-INSERT opens up one space. Now just type the text you want to insert over the blank space. (You don’t want to be in CTRL-I insert mode when you use this trick; that would defeat its purpose.)
Since the DELETE/BACK S key (backspace) is also slow when working with large documents (it, too, must move all text following the cursor), you may prefer to use the cursor-left key to backspace when using this method.
After you’ve finished inserting, there may be some inserted spaces left over that you didn’t use. Just press SHIFT-DELETE/BACK S. This instantly deletes all extra spaces between the cursor and the start of following text. It’s also useful whenever you need to delete a block of spaces for some reason.
Press DELETE/BACK S by itself to erase the character to the left of the cursor. All the following text is pulled back to fill the vacant space.
Press CTRL-DELETE/BACK S to delete the character on which the cursor is sitting. Again, all the following text is moved toward the cursor to fill the empty space.
These keys are fine for minor deletions, but it could take all day to delete a whole paragraph this way. So SpeedScript has two commands that can delete an entire word, sentence, or paragraph at a time. CTRL-E erases text after (to the right of) the cursor position, and CTRL-D deletes text behind (to the left of) the cursor.
To use the CTRL-E erase mode, first place the cursor at the beginning of the word, sentence, or paragraph you want to erase. Then press CTRL-E. The command line shows the message “Erase (S,W,P): RETURN to exit.” Press S to erase a sentence, W for a word, or P for a paragraph. Each time you press one of these letters, the text is quickly erased. You can keep pressing S, W, or P until you’ve erased all the text you wish. Then press RETURN to exit the erase mode.
The CTRL-D delete mode works similarly, but deletes only one word, sentence, or paragraph at a time. First, place the cursor after the word, sentence, or paragraph you want to delete. Then press CTRL-D. Next, press S, W or P for sentence, word, or paragraph. The text is immediately deleted and you return to editing. You don’t need to Press RETURN to exit the CTRL-D delete mode unless you pressed this key by mistake. (In general, you can escape from any command in SpeedScript by simply pressing RETURN.) CTRL-D is most convenient when the cursor is already past what you’ve been typing.
When you erase or delete with CTRL-E or CTRL-D, the text isn’t lost forever. SpeedScript remembers what you’ve removed by storing deletions in a separate area of memory called a buffer. The buffer is a fail-safe device. If you erase too much or change your mind, just Press CTRL-R to restore the deletion. However, be aware that SpeedScript remembers only the last erase or delete you performed.
Another, more powerful use of this buffer is to move or copy sections of text. To move some text from one location in your document to another, first erase or delete it with CTRL-E or CTRL-D. Then move the cursor to where you want the text to appear and press CTRL-R. CTRL-R instantly inserts the contents of the buffer at the cursor position. If you want to copy some text from one part of your document to another, just erase or delete it with CTRL-E or CTRL-D, restore it at the original position with CTRL-R, then move the cursor elsewhere and press CTRL-R to restore it again. You can retrieve the buffer with CTRL-R as many times as you like. If there is no room left in memory for inserting the buffer, you’ll see the message “Memory Full.”
Important: The CTRL-E erase mode lets you erase up to the maximum size of the buffer (2K for disk, about 6K for tape), and CTRL-E also removes the previous contents of the buffer. Keep this in mind if there’s something in the buffer you’d rather keep. If you don’t want the buffer to be erased, hold down the OPTION key while you press CTRL-E. This preserves the buffer contents and adds newly erased text to the buffer.
If you ever need to erase the contents of the buffer, press CTRL-K (kill buffer).
If you want to start a new document or simply obliterate all your text, hold down OPTION while you press SHIFT-CLEAR (that’s not a combination you’re likely to press accidentally). SpeedScript asks, “ERASE ALL TEXT: Are you sure? (Y/N).” This is your last chance. If you don’t want to erase the entire document, press N or any other key. Press Y to perform the irreversible deed. There is no way to recover text wiped out with Erase All.
SpeedScript has a Find command that searches through your document to find a selected word or phrase. A Change option lets you automatically change one word to another throughout the document.
OPTION-CTRL-F (find) activates the search feature, OPTION-CTRL-C (change) lets you selectively search and replace, and CTRL-G (global) is for automatically searching and replacing.
Searching is a two-step process. First, you need to tell SpeedScript what to search for, then you trigger the actual search. Hold down OPTION and press CTRL-F. The command line prompts “Find:”. Type in what you’d like to search for, the search phrase. If you press RETURN alone without typing anything, the Find command is canceled.
When you are ready to search, press CTRL-F. SpeedScript looks for the next occurrence of the search phrase starting from the current cursor position. If you want to hunt through the entire document, press START twice to move the cursor to the very top before beginning the search. Each time you press CTRL-F, SpeedScript looks for the next occurrence of the search phrase and places the cursor at the start of the phrase. If the search fails, you’ll see the message “Not Found.”
CTRL-C works together with CTRL-F. After you’ve specified the search phrase with OPTION-CTRL-F, press OPTION-CTRL-C to select the replace phrase. (You can press RETURN alone at the “Change to:” prompt to select a null replace phrase. When you hunt and replace, this deletes the located phrase.) To search and replace manually, start by pressing CTRL-F. After SpeedScript finds the search phrase, press CTRL-C if you want to replace the phrase. If you don’t want to replace the phrase, don’t press CTRL-C. You are not in a special search and replace mode. You’re free to continue writing at any time.
CTRL-G links CTRL-F and CTRL-C together. It first asks “Find:”, then “Change to:”, then automatically searches and replaces throughout the document, starting at the cursor position.
There are a few things to watch out for when using search and replace. First, realize that if you search for the, SpeedScript finds the embedded the in words like therefore and heathen. If you changed all occurrences of the to cow, these words would become cowrefore and heacown. If you want to find a single word, include a space as the first character of the word, since almost all words are preceded by a space. Naturally, if you are replacing, you need to include the space in the replace phrase, too.
SpeedScript also distinguishes between uppercase and lowercase. The word Meldids does not match with meldids. SpeedScript will not find a capitalized word unless you capitalize it in the search phrase. To cover all bases, you will sometimes need to make two passes at replacing a word. Keep these things in mind when using CTRL-G, since you don’t have a chance to stop a global search and replace.
Just press CTRL-S to store a document. You’ll see the prompt “Save: (Device:Filename)>”. Type C: for cassette or D: plus a legal Atari filename for disk. If you use the same name as a file already on disk, that file will be replaced by the new one. CTRL-S always saves the entire document. The cursor position within the document is not important.
When the SAVE is complete, SpeedScript reports “No errors” if all is well or gives a message like “Error #144” if not. Check your DOS or BASIC manual for a list of error numbers and their causes.
To recall a previously saved document, press CTRL-L. Answer the “Load: (Device:Filename)>” prompt with the filename. Again, remember to include the C: for cassette or D: for disk. SpeedScript loads the file and should display “No errors.” Otherwise, SpeedScript reports the error number.
The position of the cursor is important before loading a file. Documents start loading at the cursor position, so be sure to press START twice or OPTION-SHIFT-CLEAR (Erase All) to move the cursor to the start of text, unless you want to merge two documents. When you press CTRL-L to load, the command line turns green to warn you if the cursor is not at the top of the document.
To merge two or more files, simply load the first file, press CTRL-Z to move the cursor to the end of the document, and then load the file you want to merge. Do not place the cursor somewhere in the middle of your document before loading. A load does not insert the text from tape or disk, but overwrites all text after the cursor position. The last character loaded becomes the new end-of-text pointer, and you cannot access any text that appears ahead of this pointer.
Since SpeedScript stores files in ASCII (American Standard Code for Information Interchange), you can load any ASCII file with SpeedScript. You could write a BASIC program with SpeedScript, save it on disk, then use ENTER to read the file from BASIC. In BASIC, you can store a program in ASCII form with LIST "D:filename" for disk or LIST "C:" for tape, ready to load with SpeedScript. You can even load files produced by most other word processors, and most other Atari word processors can read SpeedScript files. You can make full use of SpeedScript’s editing features to prepare ASCII files for the Atari Assembler/Editor, MAC/65, and most other Atari assemblers. And SpeedScript files can be transferred via modem with your favorite telecommunications program that handles ASCII.
Sometimes you forget the name of a file, or need to delete or rename a file. SpeedScript provides a unique mini-DOS for your convenience. Just press CTRL-M (menu). SpeedScript reads the entire disk directory and puts it on the screen in three columns. A large cursor shows you which file is currently selected. Use the cursor keys to move the cursor to the file you want to select. A menu at the bottom of the screen shows you what keys you need to press. Press CTRL-D to delete the selected file, R to rename, L to lock, U to unlock, or F to format the disk. You can load the selected file by pressing CTRL-L. The position of the cursor within your document is not important when loading a file from the menu—SpeedScript always erases anything you previously had in memory.
Any changes you make to the directory will not show up until you call up the directory again. Press either 1, 2, 3, or 4 to update the directory from drives 1-4. This also sets the default disk drive, the drive accessed for further changes. When you’re ready to return to writing, press either ESC or the RETURN key.
SpeedScript has a few commands that don’t do much, but are nice to have. CTRL-X exchanges the character under the cursor with the character to the right of the cursor. Thus, you can fix transposition errors with a single keystroke. CTRL-A changes the character under the cursor from uppercase to lowercase or vice versa.
Press CTRL-B to change the background and border colors. Each time you press CTRL-B, one of 128 different background colors appears. Press CTRL-T (text) to cycle between one of eight text luminances. The colors are preserved until you change them or reboot SpeedScript.
If your TV suffers from overscanning, some characters on the left or right margin may be chopped off. Atari SpeedScript lets you widen and narrow the width of the screen. Press OPTION-CTRL-+ (the cursor-left key) to decrease the width of the screen. Each time you press it, the text is reformatted, and the left and right screen margins are adjusted by one character. You can decrease the width all the way down to two characters (although if your screen overscans that much, it’s time to buy a new TV). To increase the width, to a maximum of 40 (the default width), press OPTION-CTRL-* (the cursor-right key).
One disadvantage of word-wrapping is that it’s hard to tell exactly how many spaces are at the end of a screen line. When a word too long to fit on a line is wrapped to the next line, the hole it left is filled with “false” spaces. That is, the spaces are not actually part of your text and won’t appear on paper. If you want to distinguish between true spaces and false spaces, press CTRL-O (on/of). The false spaces become tiny dots. You can write and edit in this mode if you wish, or turn off the feature by pressing CTRL-O again.
Atari SpeedScript disables the BREAK and inverse-video keys when you’re entering or editing text. The inverse-video key was disabled because it is frequently pressed by accident on the 800 and 800XL models. If you want to enter inverse-video characters, hold down SELECT while typing the keys.
Atari 400 and 800 owners will notice that the action of the CAPS/LOWR key has been changed in SpeedScript. It works like the CAPS key on the XL and XE models. Press it once to switch to uppercase, and again to switch to lowercase. In other words, the CAPS/LOWR key toggles between uppercase and lowercase. You can still use SHIFT-CAPS/LOWR to force entry to all uppercase. CTRL-CAPS/LOWR has no effect.
Pressing SYSTEM RESET returns you to SpeedScript without erasing your text when using Atari DOS. With OS/A+ DOS, SYSTEM RESET returns you to the DOS command prompt. You can get back to SpeedScript without losing any text if you type RUN at the prompt.
If you already think SpeedScript has plenty of commands, wait until you see what the printing package offers. SpeedScript supports an array of powerful formatting features. It automatically fits your text between left and right margins which you can specify. You can center a line or block it against the right margin. SpeedScript skips over the perforation on continuous-form paper, or it can wait for you to insert single-sheet paper. A line of text can be printed at the top of each page (a header) and/or at the bottom of each page (a footer), and can include automatic page numbering, starting with whatever number you like. (See page 19 for a summary of the formatting commands.)
SpeedScript can print on different lengths and widths of paper, and single-, double-, triple-, or any-spacing is easy. You can print a document as big as can fit on a tape or disk by linking several files together during printing. You can print to the screen or to a file instead of to a printer. Other features let you send special codes to the printer to control features like underlining, boldfacing, and double-width type (depending on the printer).
But with all this power comes the need to learn additional commands. Fortunately, SpeedScript sets most of these variables to a default state. If you don’t change these settings, SpeedScript assumes a left margin of 5, a right margin position of 75, no header or footer, single-spacing, and continuous-paper page feeding. You can change these default settings if you want (see below). Before printing, be sure the paper in your printer is adjusted to top-of-form (move the paper perforation just above the printing element). One additional note: Some printers incorporate an automatic skip-over-perforation feature. The printer skips to the next page when it reaches the bottom of a page. Since SpeedScript already controls paper feeding, you need to turn off this automatic skip-over-perf feature before running SpeedScript, or paging won’t work properly.
To begin printing, simply press CTRL-P. SpeedScript prompts “Print: (Device:Filename)>”. You can print to almost any device, even disk or cassette. If you enter E (for Editor), SpeedScript prints to the screen, letting you preview where lines and pages break. Enter P to Print for most printers. If your printer is attached, powered on, and selected (online), SpeedScript begins printing immediately. To cancel printing, hold down the BREAK key until printing stops. You can use CTRL-1 to pause printing. Press CTRL-1 again to continue.
If you need to print to an RS-232 printer, just print to a disk file, then boot up your DOS master disk and use the copy selection to copy the print file to the R: device. You can also write BASIC programs to read and process a printed disk file. Remember, a Print to disk is not the same as a Save to disk.
The print formatting commands must be distinguished from normal text, so they appear onscreen in inverse video with the text and background colors switched. As mentioned above, the regular inverse-video key is not used for entering inverse-video text. Instead, hold down the SELECT key while typing the format key. All lettered printer commands should be entered in lowercase (unSHIFTed). During printing, SpeedScript treats these characters as printing commands.
There are two kinds of printing commands, which we’ll call Stage 1 and Stage 2. Stage 1 commands usually control variables such as left margin and right margin. Most are followed by a number, with no space between the command and the number. Stage 1 commands are executed before a line is printed.
Stage 2 commands, like centering and underlining, are executed while the line is being printed. Usually, Stage 1 commands must be on a line of their own, although you can group several Stage 1 commands together on a line. Stage 2 commands are by nature embedded within a line of text. Again, remember to hold down SELECT to enter the boldface characters shown here.
l Left margin. Follow with a number from 0 to 255. Use 0 for no margin. Defaults to 5.
r Right margin position, a number from 1 to 255. Defaults to 75. Be sure the right margin value is greater than the left margin value, or SpeedScript will go bonkers.
t Top margin. The position at which the first line of text is printed, relative to the top of the page. Defaults to 5. The header (if any) is always printed on the first line of the page, before the first line of text.
b Bottom margin. The line at which printing stops before continuing to the next page. Standard 8-1/2 X 11 inch paper has 66 lines. Bottom margin defaults to line 58. Don’t make the bottom margin greater than the page length.
p Page length. Defaults to 66. If your printer does not print six lines per inch, multiply lines-per-inch by 11 to get the page length. European paper is usually longer than American paper—11-5/8 or 12 inches. Try a page length of 69 or 72.
s Spacing. Defaults to single-spacing. Follow with a number from 1 to 255. Use 1 for single-spacing, 2 for double-spacing, 3 for triple-spacing.
@ Start numbering at page number given. Page numbering normally starts with 1.
? Disables printing until selected page number is reached. For example, a value of 3 would start printing the third page of your document. Normally, SpeedScript starts printing with the first page.
x Sets the page width, in columns (think across). Defaults to 80. You need to change this for the sake of the centering command if you are printing in double-width or condensed type, or if you are using a 40-column or wide-carriage printer.
n Forced paging. Normally, SpeedScript prints the footer and moves on to the next page only when it has finished a page, but you can force it to continue to the next page by issuing this command. It requires no numbers.
m Margin release. Disables the left margin for the next printed line. Remember that this executes before the line is printed. It’s used for outdenting.
w Page wait. This command should be placed at the beginning of your document before any text. With page wait turned on, SpeedScript prompts you to “Insert next sheet, press RETURN” when each page is finished printing. Insert the next sheet, line it up with the printhead, then press RETURN to continue. Page wait is ignored during disk or screen output.
j Select automatic linefeeds after carriage return. Like w, this command must be placed before any text. Don’t use this command to achieve double-spacing, but only if all text prints on the same line.
i Information. This works like REM in BASIC. You follow the command with a line of text, up to 255 characters, ending in a return-mark. This line will be ignored during printing and is handy for making such notes to yourself as the filename of the document.
h Header define and enable. The header must be a single line of text (up to 254 characters) ending in a return-mark. The header prints on the first line of each page. You can include Stage 2 commands such as centering and page numbering in a header. You can use a header by itself without a footer. The header and footer should be defined at the top of your document, before any text. If you want to prevent the header from printing on the first page, put a return-mark by itself at the top of your document before the header definition.
f Footer define and enable. The footer must be a single line of text (up to 254 characters) ending in a return-mark. The footer prints two lines prior to the last line of each page. As with the header, you can include Stage 2 printing commands, and you don’t need to set the header to use a footer.
g Go to (link) next file. Put this command as the last line in your document. Follow the command with the filename, including D: for disk. After the text in memory is printed, the link command loads the next file into memory. You can continue linking in successive files, but don’t include a link in the last file. Before you start printing a linked file, make sure the first of the linked files is in memory. When printing is finished, the last file linked to will be in memory.
These commands either precede a line of text or are embedded within one.
c Centering. Put this at the beginning of a line you want to center. This will center only one line ending in a return-mark. Repeat this command at the beginning of every line you want centered. Centering uses the page-width setting (see above) to center the line properly. To center a double-width line, either set the page width to 40 or pad out the rest of the line with an equal number of spaces. If you use double-width, remember that the spaces preceding the centered text will be double-wide spaces.
e Edge right. This works in the same manner as centering, but it blocks the line flush with the right margin.
# When SpeedScript encounters this command, it prints the current page number. You usually embed this within a header or footer.
u A simple form of underlining. It works only on printers that recognize CHR$(8) as a backspace and CHR$(95) as an underline character. Underlining works on spaces, too. Use the first u to start underlining and another one to turn off underlining.
| Command | Default | 
|---|---|
| b bottom margin | 58 | 
| c centering | |
| e edge right | |
| f define footer | |
| g goto linked file | |
| h define header | |
| i information | |
| j select linefeeds | |
| l left margin | 5 | 
| m margin release | |
| n next page | |
| p page length | 66 | 
| r right margin | 75 | 
| s spacing | 1 | 
| t top margin | 5 | 
| u underline toggle | |
| w page wait | off | 
| x columns across | 80 | 
| # page number | |
| @ starting page number | 1 | 
| ? print starting with # | 1 | 
Most dot-matrix printers are capable of more than just printing text at ten characters per inch. Some printers have several character sets, with italics and foreign language characters. Most can print in double-width (40 characters per line), condensed (132 characters per line), and in either pica or elite. Other features include programmable characters, programmable tab stops, and graphics modes. Many word processors customize themselves to a particular printer, but SpeedScript was purposely designed not to be printer-specific. Instead, SpeedScript lets you define your own Stage 2 printing commands.
You define a programmable printkey by choosing any character that is not already used for other printer commands. The entire uppercase alphabet is available for printkeys, and you can choose letters that are related to their function (like D for double-width). You enter these commands like printer commands, by holding down SELECT while you type them. The printkeys are like variables in BASIC.
To define a printkey, just hold down SELECT while you type the key you want to assign as the printkey, then an equal sign (=), and finally the ASCII value to be substituted for the printkey during printing. Now, whenever SpeedScript encounters the printkey embedded in text, it prints the character with the ASCII value you previously defined.
For example, to define the + key as the letter z, you first look up the ASCII value of z (in either your printer manual or in any Atari manual). The ASCII value of the letter z is 122, so the definition is
+=122
Gad+ooks! The +oo is +any!
Gadzooks! The zoo is zany!
More practically, here’s how you could program italics on an Epson MX-80-compatible printer. You switch on italics by sending an ESC (a character with an ASCII value of 27), then the character 4. You turn off italics by sending ESC 5. So define SHIFT-E as the escape code. Anywhere you want to print a word in italics, bracket it with printkey E, then 4, and printkey E, then 5:
The word E4italicE5 is in italics.
You can similarly define whatever codes your printer uses for features like double-width or emphasized mode. For your convenience, four of the printkeys are predefined, though you can change them. Keys 1-4 are defined as 27, 14, 15, and 18, common values for most printers. On most printers, CHR$(27) is the ESCape key, CHR$(14) starts double-width, CHR$(15) either stops double-width or starts condensed characters, and CHR$(18) usually cancels condensed characters.
SpeedScript actually lets you embed any character within text, so you may prefer to put in the actual printer codes as part of your text. To set italics, you could just press ESC twice, then 4. The ESC key appears in text as a mutant E. Double-width has a value of 14, the same value as CTRL-N. To start double-width, just embed a CTRL-N. Remember that you must press ESC before any CTRL key to get it to appear in text. CTRL keys appear as small “shadowed” capital letters. These characters, though, are counted as part of the length of a line, and excessive use within one line can result in a shorter than normal line. It can be more convenient to use the printkeys, since if you ever change printers, you have to change only the definitions of the keys.
Keep one thing in mind about printkeys: SpeedScript always assumes it is printing to a rather dumb, featureless printer, the least common denominator. SpeedScript doesn’t understand the intent of a printkey; it just sends out its value. So if you make one word within a line double-width, it may make the line overflow the specified right margin. There’s no way for SpeedScript to include built-in font and typestyle codes without being customized for a particular printer since no set of codes is universal to all printers.
It may take you awhile to fully master SpeedScript, but as you do, you’ll discover many ways to use the editing and formatting commands. For example, there is a simple way to simulate tab stops, say, for a columnar table. Just type a period at every tab stop position. Erase the line with CTRL-E, then restore it with CTRL-R multiple times. When you are filling in the table, just use word left/word right to jump quickly between the periods. Or you can use the programmable print-keys to embed your printer’s own commands for setting and jumping to tab stops.
You don’t have to change or define printer commands every time you write. Just save these definitions and load this file each time you write. You can create many custom definition files and have them ready to use on disk. You can create customized “fill-in-the-blank” letters. Just type the letter, and everywhere you’ll need to insert something, substitute a unique character, such as an * or a CTRL character. When you’re ready to customize the letter, use Find to locate each symbol and insert the specific information. Instead of typing an oft-used word or phrase, substitute a unique character, then use CTRL-G to globally change these characters into the actual word or phrase. You can even use SpeedScript as a simple filing program. Just type in all your data, flagging each field with a unique character. You can use Find to quickly locate any field.
Two program-entry aids written in BASIC are included here to make typing in SpeedScript as easy as possible. The first, “MLX,” is explained in this article. The second, “The Automatic Proofreader,” is a short program that will help you type in MLX without typing mistakes. Read the instructions for using the Automatic Proofreader later in this chapter before you type in the MLX program.
“MLX” is a new way to enter long machine language (ML) programs with a minimum of fuss. MLX lets you enter the numbers from a special list that looks similar to BASIC DATA statements. It checks your typing on a line-by-line basis. It won’t let you enter illegal characters when you should be typing numbers. It won’t let you enter numbers greater than 255 (forbidden in ML). And it won’t let you enter the wrong numbers on the wrong line. In addition, MLX creates a ready-to-use tape or disk file.
Type in and save MLX, Program 2-1 (you’ll want to use it in the future). When you’re ready to type in SpeedScript, run MLX. MLX asks you for three numbers: the starting address, the ending address, and the run/init address. These numbers for SpeedScript are
Next, you’ll be asked “Tape or Disk.” SpeedScript can be saved as either a binary file on disk or as a boot tape. Press T for use with a tape drive. If you press D for disk, you’ll be asked “Boot Disk or Binary File.” Press F to select the Binary File option. Although you could save SpeedScript as an auto-booting disk, it makes no sense, since such a disk cannot contain DOS, which is necessary for file-oriented disk access.
The screen will then show the first prompt, the number 7936 followed by a colon. Type in each three-digit number shown in the listing. You do not need to type the comma shown in the listing; MLX inserts the comma automatically. The prompt is the current line you are entering from the listing. It increases by six each time you enter a line. That’s because each line has seven numbers—six actual data numbers plus a checksum number. The checksum verifies that you typed the previous six numbers correctly. If you enter any of the six numbers wrong, or if you enter the checksum wrong, the computer rings a buzzer and prompts you to reenter the line. If you enter it correctly, a bell tone sounds and you continue to the next line.
MLX accepts only numbers as input. If you make a typing error, press the DELETE/BACK S key; the entire number is deleted. You can press it as many times as necessary back to the start of the line. If you enter three-digit numbers as listed, the computer automatically prints the comma and goes on to accept the next number. If you enter less than three digits, you can press the comma key, the space bar, or the RETURN key to advance to the next number. The checksum automatically appears in inverse video for emphasis.
When you finish typing an ML listing (assuming you type it all in one session), you can then save the completed program on tape or disk. Follow the screen instructions. If you get any errors while saving, you probably have a bad disk or the disk is full or you made a typo when entering the MLX program itself.
Fortunately, you don’t have to enter all of SpeedScript in one sitting. MLX lets you enter as much as you want, save it, and then reload the file from tape or disk later. MLX recognizes these commands:
To issue a command, hold down the CTRL key (CONTROL on the XL models) and press the indicated key. When you enter a command, MLX jumps out of the line you’ve been typing, so we recommend you do it at a new prompt. Use the Save command (CTRL-S) to save what you’ve been working on. It will save on tape or disk as if you’ve finished, but the tape or disk won’t work, of course, until you finish the typing. Remember to make a note of the address where you stop. The next time you run MLX, answer all the prompts as you did before—regardless of where you stopped typing—then insert the disk or tape. When you get to the line number prompt, press CTRL-L to reload the partly completed file into memory. Then use the New Address command to resume typing.
To use the New Address command, press CTRL-N and enter the address where you previously stopped. The prompt will change, and you can then continue typing. Always enter a New Address that matches up with one of the line numbers in the MLX-format listing, or the checksum won’t work. The Display command lets you display a section of your typing. After you press CTRL-D, enter two addresses within the line-number range of the listing. You can break out of the listing display and return to the prompt by pressing any key.
100 GRAPHICS 0:DL=PEEK(560)+256*PEEK(561)+4:POKE DL-1,71:POKE DL+2,6 110 POSITION 8,0:? "MLX":POSITION 23,0:? "failsafe entry":POKE 710,N:? 120 ? "Starting Address";:INPUT BEG:? " Ending Address";:INPUT FIN:? "Run/Init ADDRESS";:INPUT STARTADR 130 DIM A(6),BUFFER$(FIN-BEG+127),T$(20),F$(20),CIO$(7),SECTOR$(128),DSKINV$(6) 140 OPEN #1,4,0,"K:":? :? ,"Tape or Disk:"; 150 BUFFER$=CHR$(0):BUFFER$(FIN-BEG+30)=BUFFER$:BUFFER$(2)=BUFFER$:SECTOR$=BUFFER$ 160 ADDR=BEG:CIO$="hhh*LVd" 170 GET #1,MEDIA:IF MEDIA<>84 AND MEDIA<>68 THEN 170 180 ? CHR$(MEDIA):? :IF MEDIA<>ASC("T") THEN BUFFER$="":GOTO 250 190 BEG=BEG-24:BUFFER$=CHR$(0):BUFFER$(2)=CHR$(INT((FIN-BEG+127)/128)) 200 H=INT(BEG/256):L=BEG-H*256:BUFFER$(3)=CHR$(L):BUFFER$(4)=CHR$(H) 210 PINIT=BEG+8:H=INT(PINIT/256):L=PINIT-H*256:BUFFER$(5)=CHR$(L):BUFFER$(6)=CHR$(H) 220 FOR I=7 TO 24:READ A:BUFFER$(I)=CHR$(A):NEXT I:DATA 24,96,169,60,141,2,211,169,0,133,10,169,0,133,11,76,0,0 230 H=INT(STARTADR/256):L=STARTADR-H*256:BUFFER$(15)=CHR$(L):BUFFER$(19)=CHR$(H) 240 BUFFER$(23)=CHR$(L):BUFFER$(24)=CHR$(H) 250 IF MEDIA<>ASC("D") THEN 360 260 ? :? "Boot Disk or Binary File:"; 270 GET #1,DTYPE:IF DTYPE<>68 AND DTYPE<>70 THEN 270 280 ? CHR$(DTYPE):IF DTYPE=70 THEN 360 290 BEG=BEG-30:BUFFER$=CHR$(0):BUFFER$(2)=CHR$(INT((FIN-BEG+127)/128)) 300 H=INT(BEG/256):L=BEG-H*256:BUFFER$(3)=CHR$(L):BUFFER$(4)=CHR$(H) 310 PINIT=STARTADR:H=INT(PINIT/256):L=PINIT-H*256:BUFFER$(5)=CHR$(L):BUFFER$(6)=CHR$(H) 320 RESTORE 330:FOR I=7 TO 30:READ A:BUFFER$(I)=CHR$(A):NEXT I 330 DATA 169,0,141,231,2,133,14,169,0,141,232,2,133,15,169,0,133,10,169,0,133,11,24,96 340 H=INT(BEG/256):L=BEG-H*256:BUFFER$(8)=CHR$(L):BUFFER$(15)=CHR$(H) 350 H=INT(STARTADR/256):L=STARTADR-H*256:BUFFER$(22)=CHR$(L):BUFFER$(26)=CHR$(H) 360 GRAPHICS 0:POKE 712,10:POKE 710,10:POKE 709,2 370 ? ADDR;":";:FOR J=1 TO 6 380 GOSUB 570:IF N=-1 THEN J=J-1:GOTO 380 390 IF N=-19 THEN 720 400 IF N=-12 THEN LET READ=1:GOTO 720 410 TRAP 410:IF N=-14 THEN ? :? "New Address";:INPUT ADDR:? :GOTO 370 420 TRAP 32767:IF N<>-4 THEN 480 430 TRAP 430:? :? "Display:From";:INPUT F:? ,"To";:INPUT T:TRAP 32767 440 IF F<BEG OR F>FIN OR T<BEG OR T>FIN OR T<F THEN ? CHR$(253);"At least ";BEG;", Not More Than ";FIN:GOTO 430 450 FOR I=F TO T STEP 6:? :? I;":";:FOR K=0 TO 5:N=PEEK(ADR(BUFFER$)+I+K-BEG):T$="000":T$(4-LEN(STR$(N)))=STR$(N) 460 IF PEEK(764)<255 THEN GET #1,A:POP :POP :? :GOTO 370 470 ? T$;",";:NEXT K:? CHR$(126);:NEXT I:? :? :GOTO 370 480 IF N<0 THEN ? :GOTO 370 490 A(J)=N:NEXT J 500 CKSUM=ADDR-INT(ADDR/256)*256:FOR I=1 TO 6:CKSUM=CKSUM+A(I):CKSUM=CKSUM-256*(CKSUM>255):NEXT I 510 RF=128:SOUND 0,200,12,8:GOSUB 570:SOUND 0,0,0,0:RF=0:? CHR$(126) 520 IF N<>CKSUM THEN ? :? "Incorrect":GOTO 370 530 FOR W=15 TO 0 STEP -1:SOUND 0,50,10,W:NEXT W 540 FOR I=1 TO 6:POKE ADR(BUFFER$)+ADDR-BEG+I-1,A(I):NEXT I 550 ADDR=ADDR+6:IF ADDR<=FIN THEN 370 560 GOTO 710 570 N=0:Z=0 580 GET #1,A:IF A=155 OR A=44 OR A=32 THEN 670 590 IF A<32 THEN N=-A:RETURN 600 IF A<>126 THEN 630 610 GOSUB 690:IF I=1 AND T=44 THEN N=-1:? CHR$(126);:GOTO 690 620 GOTO 570 630 IF A<48 OR A>57 THEN 580 640 ? CHR$(A+RF);:N=N*10+A-48 650 IF N>255 THEN ? CHR$(253);:A=126:GOTO 600 660 Z=Z+1:IF Z<3 THEN 580 670 IF Z=0 THEN ? CHR$(253);:GOTO 570 680 ? ",";:RETURN 690 POKE 752,1:FOR I=1 TO 3:? CHR$(30);:GET #6,T:IF T<>44 AND T<>58 THEN ? CHR$(A);:NEXT I 700 POKE 752,0:? " ";CHR$(126);:RETURN 710 GRAPHICS 0:POKE 710,26:POKE 712,26:POKE 709,2 720 IF MEDIA=ASC("T") THEN 890 730 REM DISK 740 IF READ THEN ? :? "Load File":? 750 IF DTYPE<>70 THEN 1040 760 ? :? "Enter AUTORUN.SYS for automatic use":? :? "Enter filename":INPUT T$ 770 F$=T$:IF LEN(T$)>2 THEN IF T$(1,2)<>"D:" THEN F$="D:":F$(3)=T$ 780 TRAP 870:CLOSE #2:OPEN #2,8-4*READ,0,F$:? :? "Working..." 790 IF READ THEN FOR I=1 TO 6:GET #2,A:NEXT I:GOTO 820 800 PUT #2,255:PUT #2,255 810 H=INT(BEG/256):L=BEG-H*256:PUT #2,L:PUT #2,H:H=INT(FIN/256):L=FIN-H*256:PUT #2,L:PUT #2,H 820 GOSUB 970:IF PEEK(195)>1 THEN 870 830 IF STARTADR=0 OR READ THEN 850 840 PUT #2,224:PUT #2,2:PUT #2,225:PUT #2,2:H=INT(STARTADR/256):L=STARTADR-H*256:PUT #2,L:PUT #2,H 850 TRAP 32767:CLOSE #2:? "Finished.":IF READ THEN ? :? :LET READ=0:GOTO 360 860 END 870 ? "Error ";PEEK(195);" trying to access":? F$:CLOSE #2:? :GOTO 760 880 REM BOOT TAPE 890 IF READ THEN ? :? "Read Tape" 900 ? :? :? "Insert, Rewind Tape.":? "Press PLAY ";:IF NOT READ THEN ? "& RECORD" 910 ? :? "Press RETURN when ready:"; 920 TRAP 960:CLOSE #2:OPEN #2,8-4*READ,128,"C:":? :? "Working..." 930 GOSUB 970:IF PEEK(195)>1 THEN 960 940 CLOSE #2:TRAP 32767:? "Finished.":? :? :IF READ THEN LET READ=0:GOTO 360 950 END 960 ? :? "Error ";PEEK(195);" when reading/writing boot tape":? :CLOSE #2:GOTO 890 970 REM CIO Load/Save File#2 opened read=0 for write, read=1 for read 980 X=32:REM File#2,$20 990 ICCOM=834:ICBADR=836:ICBLEN=840:ICSTAT=835 1000 H=INT(ADR(BUFFER$)/256):L=ADR(BUFFER$)-H*256:POKE ICBADR+X,L:POKE ICBADR+X+1,H 1010 L=FIN-BEG+1:H=INT(L/256):L=L-H*256:POKE ICBLEN+X,L:POKE ICBLEN+X+1,H 1020 POKE ICCOM+X,11-4*READ:A=USR(ADR(CIO$),X) 1030 POKE 195,PEEK(ICSTAT):RETURN 1040 REM SECTOR I/O 1050 IF READ THEN 1100 1060 ? :? "Format Disk In Drive 1? (Y/N):"; 1070 GET #1,A:IF A<>78 AND A<>89 THEN 1070 1080 ? CHR$(A):IF A=78 THEN 1100 1090 ? :? "Formatting...":XIO 254,#2,0,0,"D:":? "Format Complete":? 1100 NR=INT((FIN-BEG+127)/128):BUFFER$(FIN-BEG+2)=CHR$(0):IF READ THEN ? "Reading...":GOTO 1120 1110 ? "Writing..." 1120 FOR I=1 TO NR:S=I 1130 IF READ THEN GOSUB 1220:BUFFER$(I*128-127)=SECTOR$:GOTO 1160 1140 SECTOR$=BUFFER$(I*128-127) 1150 GOSUB 1220 1160 IF PEEK(DSTATS)<>1 THEN 1200 1170 NEXT I 1180 IF NOT READ THEN END 1190 ? :? :LET READ=0:GOTO 360 1200 ? "Error on disk access.":? "May need formatting.":GOTO 1040 1210 REM 1220 REM SECTOR ACCESS SUBROUTINE 1230 REM Drive ONE 1240 REM Pass buffer in SECTOR$ 1250 REM sector #in variable S 1260 REM READ=1 for read, 1270 REM READ=0 for write 1280 BASE=3*256 1290 DUNIT=BASE+1:DCOMND=BASE+2:DSTATS=BASE+3 1300 DBUFLO=BASE+4:DBUFHI=BASE+5 1310 DBYTLO=BASE+8:DBYTHI=BASE+9 1320 DAUX1=BASE+10:DAUX2=BASE+11 1330 REM DIM DSKINV$(4) 1340 DSKINV$="hLS":DSKINV$(4)=CHR$(228) 1350 POKE DUNIT,1:A=ADR(SECTOR$):H=INT(A/256):L=A-256*H 1360 POKE DBUFHI,H 1370 POKE DBUFLO,L 1380 POKE DCOMND,87-5*READ 1390 POKE DAUX2,INT(S/256):POKE DAUX1,S-PEEK(DAUX2)*256 1400 A=USR(ADR(DSKINV$)) 1410 RETURN
At last there’s a way for your computer to help you check your typing. “The Automatic Proofreader” will make entering programs faster, easier, and more accurate.
The strong point of computers is that they excel at tedious, exacting tasks. So why not get your computer to check your typing for you?
“The Automatic Proofreader” will help you type in “MLX” program listings without typing mistakes. It is a short error-checking program that hides itself in memory. When activated, it lets you know immediately after typing a line from a program listing if you have made a mistake. Please read these instructions carefully before typing the MLX program.
The MLX program listing has a checksum found immediately to the left of each line number. Don’t enter the checksum when typing in a program. It is just for your information.
When you type in a line from the program listing and press RETURN, the Proofreader displays the checksum letters at the top of your screen. These checksum letters must match the checksum letters in the printed listing. If they don’t match, it means you typed the line differently from the way it is listed. Immediately recheck your typing. You can correct any mistakes you find.
The Proofreader is not picky with spaces. It will not notice extra spaces or missing ones. This is for your convenience since spacing is generally not important. But occasionally proper spacing is important, so be extra careful with spaces. The Proofreader will catch practically everything else that can go wrong. Characters in inverse video will appear like this:
INVERSE VIDEO
Due to the nature of a checksum, the Proofreader will not catch all errors. The Proofreader will not catch errors of transposition. In fact, you could type in a line in any order, and the Proofreader wouldn’t notice.
There’s another thing to watch out for: If you enter a line by using abbreviations for commands, the checksum will not match up. But there is a way to make the Proofreader check the line. After entering the line, LIST it. This eliminates the abbreviations. Then move the cursor up to the line and press RETURN. It should now match the checksum. You can check whole groups of lines this way. The only abbreviation that cannot be handled this way is when a question mark (?) is used instead of PRINT; they are not the same to the Proofreader.
100 GRAPHICS 0 110 FOR I=1536 TO 1700:READ A:POKE I,A:CK=CK+A:NEXT I 120 IF CK<>19072 THEN ? "ERROR IN DATA STATEMENTS. CHECK TYPING.":END 130 A=USR(1536) 140 ? :? "AUTOMATIC PROOFREADER NOW ACTIVATED." 150 END 1536 DATA 104,160,0,185,26,3 1542 DATA 201,69,240,7,200,200 1548 DATA 192,34,208,243,96,200 1554 DATA 169,74,153,26,3,200 1560 DATA 169,6,153,26,3,162 1566 DATA 0,189,0,228,157,74 1572 DATA 6,232,224,16,208,245 1578 DATA 169,93,141,78,6,169 1584 DATA 6,141,79,6,24,173 1590 DATA 4,228,105,1,141,95 1596 DATA 6,173,5,228,105,0 1602 DATA 141,96,6,169,0,133 1608 DATA 203,96,247,238,125,241 1614 DATA 93,6,244,241,115,241 1620 DATA 124,241,76,205,238,0 1626 DATA 0,0,0,0,32,62 1632 DATA 246,8,201,155,240,13 1638 DATA 201,32,240,7,72,24 1644 DATA 101,203,133,203,104,40 1650 DATA 96,72,152,72,138,72 1656 DATA 160,0,169,128,145,88 1662 DATA 200,192,40,208,249,165 1668 DATA 203,74,74,74,74,24 1674 DATA 105,161,160,3,145,88 1680 DATA 165,203,41,15,24,105 1686 DATA 161,200,145,88,169,0 1692 DATA 133,203,104,170,104,168 1698 DATA 104,40,96
Before you begin typing SpeedScript, you must load and run the “MLX” program. Answer the MLX prompts as follows:
7936:173,198,002,141,197,002,201 7942:032,137,037,169,203,205,021 7948:179,066,141,179,066,240,115 7954:033,032,031,037,032,080,007 7960:042,165,012,141,118,037,027 7966:165,013,141,119,037,169,162 7972:117,133,012,169,037,133,125 7978:013,169,000,141,068,002,179 7984:169,001,133,009,032,234,114 7990:037,076,072,038,000,000,021 7996:000,000,000,000,000,000,060 8002:000,000,000,000,000,000,066 8008:000,000,000,000,000,000,072 8014:000,000,000,000,000,000,078 8020:000,000,000,000,000,000,084 8026:000,000,000,000,000,000,090 8032:000,000,000,000,000,000,096 8038:000,000,000,000,000,000,102 8044:000,000,000,000,000,000,108 8050:000,000,000,000,000,000,114 8056:000,000,000,000,000,000,120 8062:000,000,000,000,000,000,126 8068:000,000,000,000,000,000,132 8074:000,000,000,000,000,000,138 8080:000,000,000,000,000,000,144 8086:000,000,000,000,000,000,150 8092:000,000,000,000,000,000,156 8098:000,000,000,000,000,000,162 8104:000,000,000,000,000,000,168 8110:000,000,000,000,000,000,174 8116:000,000,000,000,000,000,180 8122:000,000,000,000,000,000,186 8128:000,000,000,000,000,000,192 8134:000,000,000,000,000,000,198 8140:000,000,000,000,000,000,204 8146:000,000,000,000,000,000,210 8152:000,000,000,000,000,000,216 8158:000,000,000,000,000,000,222 8164:000,000,000,000,000,000,228 8170:000,000,000,000,000,000,234 8176:000,000,000,000,000,000,240 8182:000,000,000,000,000,000,246 8188:036,037,045,017,000,000,131 8194:000,000,000,000,000,000,002 8200:000,024,024,024,024,024,128 8206:000,024,000,102,102,102,088 8212:000,000,000,000,000,102,122 8218:255,102,102,255,102,000,074 8224:024,062,096,060,006,124,148 8230:024,000,000,204,216,048,018 8236:096,204,140,000,000,056,028 8242:108,056,112,222,204,118,102 8248:000,024,024,048,000,000,152 8254:000,000,000,024,048,096,230 8260:096,096,048,024,000,048,124 8266:024,012,012,012,024,048,206 8272:000,000,102,060,255,060,045 8278:102,000,000,000,024,024,236 8284:126,024,024,000,000,000,010 8290:000,000,000,048,048,096,034 8296:000,000,000,000,126,000,230 8302:000,000,000,000,000,000,110 8308:000,000,048,048,000,000,212 8314:006,012,024,048,096,192,244 8320:000,124,206,222,246,230,132 8326:198,124,000,024,056,024,048 8332:024,024,024,126,000,124,206 8338:198,012,024,048,096,254,010 8344:000,254,012,024,056,012,254 8350:198,124,000,028,060,108,164 8356:204,254,012,012,000,254,132 8362:192,252,006,006,198,124,180 8368:000,124,192,252,198,198,116 8374:198,124,000,126,006,012,136 8380:024,048,096,096,000,124,064 8386:198,198,124,198,198,124,210 8392:000,124,198,198,126,012,090 8398:024,048,000,000,048,048,118 8404:000,048,048,000,000,000,052 8410:048,048,000,048,048,096,250 8416:000,012,024,048,096,048,196 8422:024,012,000,000,000,126,136 8428:000,000,126,000,000,048,154 8434:024,012,006,012,024,048,112 8440:000,060,102,006,012,024,196 8446:000,024,000,124,198,222,054 8452:214,220,224,060,000,124,078 8458:198,198,198,254,198,198,230 8464:000,252,198,198,252,198,090 8470:198,252,000,124,198,192,218 8476:192,192,198,124,000,248,214 8482:204,198,198,198,204,248,004 8488:000,254,192,192,252,192,098 8494:192,254,000,254,192,192,106 8500:252,192,192,192,000,124,236 8506:198,192,222,198,198,124,166 8512:000,198,198,198,254,198,086 8518:198,198,000,126,024,024,128 8524:024,024,024,126,000,062,080 8530:012,012,012,012,204,120,198 8536:000,198,204,216,240,216,138 8542:204,198,000,192,192,192,048 8548:192,192,192,254,000,198,104 8554:238,254,214,198,198,198,126 8560:000,198,230,246,254,222,238 8566:206,198,000,124,198,198,018 8572:198,198,198,124,000,252,070 8578:198,198,198,252,192,192,080 8584:000,124,198,198,198,222,052 8590:124,014,000,252,198,198,160 8596:252,216,204,198,000,124,118 8602:198,192,124,006,198,124,228 8608:000,126,024,024,024,024,126 8614:024,024,000,198,198,198,040 8620:198,198,198,124,000,198,064 8626:198,198,198,198,108,056,110 8632:000,198,198,198,214,254,222 8638:238,198,000,198,198,108,106 8644:056,108,198,198,000,102,090 8650:102,102,060,024,024,024,026 8656:000,254,012,024,048,096,130 8662:192,254,000,030,024,024,226 8668:024,024,024,030,000,064,130 8674:096,048,024,012,006,000,156 8680:000,240,048,048,048,048,152 8686:048,240,000,008,028,054,104 8692:099,000,000,000,000,000,087 8698:000,000,000,000,000,255,249 8704:000,000,000,000,000,000,000 8710:000,000,124,194,153,153,118 8716:129,153,153,230,252,130,035 8722:153,130,153,153,131,252,222 8728:124,194,153,158,158,153,196 8734:194,124,252,130,153,153,012 8740:153,153,130,252,254,130,084 8746:158,132,156,158,130,254,006 8752:126,193,206,194,206,204,153 8758:204,120,124,194,153,158,239 8764:145,153,194,124,246,153,051 8770:153,129,153,153,153,246,029 8776:127,097,115,050,050,115,114 8782:097,127,062,050,050,050,002 8788:050,114,198,124,230,153,185 8794:146,132,146,153,153,230,026 8800:120,076,076,076,076,078,086 8806:066,124,230,153,129,129,165 8812:137,153,153,230,230,153,140 8818:137,129,145,153,153,230,037 8824:124,194,153,153,153,153,026 8830:194,124,254,195,201,201,015 8836:195,206,200,240,124,194,011 8842:153,153,153,146,201,118,038 8848:124,194,201,201,194,201,235 8854:201,247,126,195,158,194,247 8860:249,153,195,126,254,194,047 8866:102,100,100,100,100,124,020 8872:246,153,153,153,153,153,155 8878:194,124,230,153,153,153,157 8884:153,194,100,056,246,153,058 8890:153,153,137,129,153,246,133 8896:230,153,153,194,153,153,204 8902:153,230,230,153,153,195,032 8908:230,100,100,124,254,193,181 8914:249,050,228,206,193,254,110 8920:120,096,120,096,126,024,030 8926:030,000,000,024,060,126,206 8932:024,024,024,000,000,024,068 8938:024,024,126,060,024,000,236 8944:000,000,000,012,012,088,096 8950:112,120,000,024,012,126,128 8956:012,024,000,000,000,000,032 8962:024,060,126,126,060,024,166 8968:000,000,000,124,006,126,008 8974:198,126,000,000,192,252,014 8980:198,198,198,252,000,000,098 8986:000,124,198,192,198,124,094 8992:000,000,006,126,198,198,048 8998:198,126,000,000,000,124,230 9004:198,254,192,124,000,000,044 9010:062,096,252,096,096,096,236 9016:006,252,000,126,198,198,068 9022:198,126,000,000,192,192,002 9028:252,198,198,198,000,000,146 9034:024,000,056,024,024,060,006 9040:024,240,024,000,024,024,160 9046:024,024,000,000,192,204,018 9052:216,248,204,198,000,000,190 9058:056,024,024,024,024,060,054 9064:000,000,000,204,254,254,048 9070:214,198,000,000,000,252,006 9076:198,198,198,198,000,000,140 9082:000,124,198,198,198,124,196 9088:192,192,000,252,198,198,136 9094:198,252,006,006,000,126,210 9100:198,198,198,126,000,000,092 9106:000,252,198,192,192,192,148 9112:000,000,000,126,192,124,082 9118:006,252,000,000,048,254,206 9124:048,048,048,030,000,000,082 9130:000,198,198,198,198,126,064 9136:000,000,000,198,198,198,002 9142:108,056,000,000,000,198,032 9148:214,254,124,108,000,000,120 9154:000,198,108,056,108,198,094 9160:006,252,000,198,198,198,028 9166:198,126,000,000,000,254,016 9172:012,056,096,254,014,000,132 9178:014,024,024,056,024,024,128 9184:024,024,024,024,024,024,112 9190:024,024,112,000,112,024,014 9196:024,028,024,024,000,000,080 9202:000,008,024,056,024,008,106 9208:000,000,000,016,016,024,048 9214:028,024,000,000,000,000,050 9220:000,000,000,000,000,000,004 9226:000,000,000,000,000,000,010 9232:165,128,141,048,036,165,187 9238:129,141,049,036,165,130,160 9244:141,051,036,165,131,141,181 9250:052,036,166,133,240,032,181 9256:169,000,141,115,063,160,176 9262:000,185,255,255,153,255,125 9268:255,200,204,115,063,208,073 9274:244,238,049,036,238,052,147 9280:036,224,000,240,007,202,005 9286:208,224,165,132,208,222,205 9292:096,165,133,170,005,132,009 9298:208,001,096,024,138,101,138 9304:129,141,120,036,165,128,039 9310:141,119,036,024,138,101,141 9316:131,141,123,036,165,130,058 9322:141,122,036,232,164,132,165 9328:208,004,240,013,160,255,224 9334:185,255,255,153,255,255,196 9340:136,192,255,208,245,206,086 9346:120,036,206,123,036,202,085 9352:208,234,096,169,040,200,059 9358:024,109,108,068,024,101,064 9364:088,133,136,165,089,105,096 9370:000,133,137,024,173,111,220 9376:063,133,138,173,112,063,074 9382:133,139,162,001,173,114,120 9388:063,133,145,160,000,177,082 9394:138,153,123,063,200,041,128 9400:127,201,094,240,022,204,048 9406:107,068,208,239,136,177,101 9412:138,041,127,201,000,240,175 9418:007,136,208,245,172,107,053 9424:068,136,200,132,140,160,020 9430:000,185,123,063,145,136,098 9436:200,196,140,208,246,024,210 9442:152,101,138,133,138,165,029 9448:139,105,000,133,139,224,204 9454:001,208,003,140,110,063,251 9460:204,107,068,240,008,169,016 9466:064,145,136,200,076,244,091 9472:036,024,165,136,105,040,250 9478:133,136,144,002,230,137,020 9484:232,224,019,240,003,076,038 9490:175,036,165,138,141,121,026 9496:063,165,139,141,122,063,205 9502:096,173,102,063,133,138,223 9508:141,111,063,141,117,063,160 9514:133,134,173,103,063,133,013 9520:139,141,112,063,141,118,250 9526:063,133,135,056,173,105,207 9532:063,237,103,063,170,169,097 9538:000,160,255,198,139,145,195 9544:138,200,230,139,145,138,038 9550:200,208,251,230,139,202,028 9556:208,246,145,138,096,133,026 9562:140,132,141,169,001,141,046 9568:240,002,160,000,177,140,047 9574:240,006,032,127,047,200,242 9580:208,246,096,032,204,047,173 9586:240,251,096,032,064,021,050 9592:173,106,068,240,006,160,105 9598:000,165,144,145,134,032,234 9604:234,037,076,072,038,169,246 9610:125,032,127,047,169,000,126 9616:141,114,063,141,102,063,000 9622:141,104,063,141,106,063,000 9628:141,108,063,141,245,063,149 9634:141,020,064,141,182,067,009 9640:141,190,002,141,108,068,050 9646:169,040,141,107,068,169,100 9652:068,024,105,001,141,103,110 9658:063,173,049,002,056,233,250 9664:001,141,109,063,056,233,027 9670:008,141,107,063,056,233,038 9676:001,141,105,063,169,255,170 9682:141,243,063,165,075,240,113 9688:016,173,109,063,141,105,055 9694:063,169,007,141,107,063,004 9700:169,030,141,109,063,096,068 9706:032,173,045,173,102,063,054 9712:133,134,173,103,063,133,211 9718:135,032,139,036,032,010,118 9724:038,169,152,160,061,032,096 9730:089,037,238,113,063,076,106 9736:207,039,032,026,038,169,007 9742:136,160,061,032,089,037,017 9748:169,000,141,113,063,096,090 9754:160,039,169,000,145,088,115 9760:136,016,251,169,000,133,225 9766:082,133,085,133,084,096,139 9772:072,041,128,133,140,104,150 9778:041,127,201,096,176,013,192 9784:201,032,176,006,024,105,088 9790:064,076,069,038,056,233,086 9796:032,005,140,096,160,000,245 9802:140,106,068,177,134,133,064 9808:144,160,000,140,184,067,007 9814:177,134,073,128,145,134,109 9820:173,106,068,073,001,141,142 9826:106,068,032,139,036,032,255 9832:204,047,208,040,169,008,012 9838:141,031,208,173,031,208,134 9844:201,006,208,015,160,000,194 9850:140,106,068,165,144,145,122 9856:134,032,161,043,076,072,134 9862:038,165,020,041,016,240,142 9868:218,169,000,133,020,076,244 9874:081,038,170,169,008,141,241 9880:031,208,173,031,208,201,236 9886:005,208,005,169,128,141,046 9892:184,067,160,000,165,144,116 9898:145,134,173,113,063,240,014 9904:007,138,072,032,010,038,217 9910:104,170,138,201,155,208,134 9916:005,162,030,076,226,038,213 9922:138,044,182,067,048,026,187 9928:201,156,176,102,041,127,235 9934:201,032,144,096,201,123,235 9940:176,092,201,092,240,088,077 9946:201,094,240,084,201,095,109 9952:240,080,138,072,160,000,146 9958:140,182,067,177,134,201,107 9964:094,240,005,173,114,063,157 9970:240,003,032,124,044,104,021 9976:032,044,038,041,127,013,031 9982:184,067,160,000,145,134,176 9988:032,139,036,056,165,134,054 9994:237,117,063,133,140,165,097 10000:135,237,118,063,005,140,202 10006:144,014,165,134,105,000,072 10012:141,117,063,165,135,105,242 10018:000,141,118,063,230,134,208 10024:208,002,230,135,032,207,086 10030:039,076,072,038,174,083,016 10036:039,221,083,039,240,006,168 10042:202,208,248,076,072,038,134 10048:202,138,010,170,169,038,023 10054:072,169,071,072,189,120,251 10060:039,072,189,119,039,072,094 10066:096,035,031,030,092,094,204 10072:002,020,028,029,126,255,036 10078:004,009,125,124,095,005,200 10084:012,019,013,018,024,026,212 10090:016,254,001,011,006,021,159 10096:127,157,003,007,156,027,077 10102:015,132,040,183,040,236,252 10108:040,034,041,130,041,138,036 10114:041,154,041,000,042,049,201 10120:043,123,044,091,043,225,193 10126:044,001,045,048,045,081,150 10132:045,050,046,056,053,092,234 10138:052,186,049,124,054,016,123 10144:055,102,041,189,055,076,166 10150:043,032,055,079,042,132,037 10156:059,109,061,083,044,075,091 10162:044,047,060,099,059,216,191 10168:043,188,039,197,039,173,095 10174:182,067,073,128,141,182,195 10180:067,096,173,004,034,073,131 10186:016,141,004,034,096,032,013 10192:045,040,056,165,134,237,117 10198:111,063,165,135,237,112,013 10204:063,176,032,056,173,111,063 10210:063,237,102,063,133,140,196 10216:173,112,063,237,103,063,215 10222:005,140,240,013,165,134,167 10228:141,111,063,165,135,141,232 10234:112,063,032,139,036,056,176 10240:173,121,063,229,134,133,085 10246:138,173,122,063,229,135,098 10252:133,139,005,138,240,002,157 10258:176,024,024,173,111,063,077 10264:109,110,063,141,111,063,109 10270:173,112,063,105,000,141,112 10276:112,063,032,139,036,076,238 10282:255,039,096,056,173,117,010 10288:063,237,104,063,133,140,020 10294:173,118,063,237,105,063,045 10300:005,140,144,012,173,104,126 10306:063,141,117,063,173,105,216 10312:063,141,118,063,056,165,166 10318:134,237,102,063,133,140,119 10324:165,135,237,103,063,005,024 10330:140,176,011,173,102,063,243 10336:133,134,173,103,063,133,067 10342:135,096,056,165,134,237,157 10348:117,063,133,140,165,135,093 10354:237,118,063,005,140,176,085 10360:001,096,173,117,063,133,191 10366:134,173,118,063,133,135,114 10372:096,169,008,141,031,208,017 10378:173,031,208,201,003,208,194 10384:030,173,107,068,201,040,251 10390:240,020,238,107,068,238,037 10396:107,068,206,108,068,032,233 10402:139,036,032,207,039,169,016 10408:125,032,127,047,076,010,073 10414:038,230,134,208,002,230,248 10420:135,076,207,039,169,008,046 10426:141,031,208,173,031,208,210 10432:201,003,208,030,173,107,146 10438:068,201,002,240,020,206,167 10444:107,068,206,107,068,238,230 10450:108,068,032,139,036,032,113 10456:207,039,169,125,032,127,147 10462:047,076,010,038,165,134,180 10468:208,002,198,135,198,134,079 10474:076,207,039,165,134,133,220 10480:138,165,135,133,139,198,124 10486:139,160,255,177,138,201,036 10492:000,240,004,201,094,208,231 10498:003,136,208,243,177,138,139 10504:201,000,240,008,201,094,240 10510:240,004,136,208,243,096,173 10516:056,152,101,138,133,134,222 10522:165,139,105,000,133,135,191 10528:076,207,039,160,000,177,179 10534:134,201,000,240,008,201,054 10540:094,240,004,200,208,243,009 10546:096,200,208,011,230,135,162 10552:165,135,205,118,063,144,118 10558:002,208,025,177,134,201,041 10564:000,240,236,201,094,240,055 10570:232,024,152,101,134,133,082 10576:134,165,135,105,000,133,240 10582:135,076,207,039,173,117,065 10588:063,133,134,173,118,063,008 10594:133,135,076,207,039,169,089 10600:000,141,111,063,173,118,198 10606:063,056,233,004,205,103,006 10612:063,176,003,173,103,063,185 10618:141,112,063,032,139,036,133 10624:076,090,041,238,138,041,240 10630:238,138,041,096,008,238,125 10636:154,041,238,154,041,173,173 10642:154,041,041,015,141,154,180 10648:041,096,002,165,134,133,211 10654:138,165,135,133,139,198,042 10660:139,160,255,177,138,201,210 10666:014,240,012,201,001,240,110 10672:008,201,031,240,004,201,093 10678:094,208,004,136,208,235,043 10684:096,177,138,201,014,240,030 10690:027,201,001,240,023,201,119 10696:031,240,019,201,094,240,001 10702:015,136,208,235,198,139,113 10708:165,139,205,102,063,176,038 10714:226,076,244,041,132,140,053 10720:198,140,200,240,010,177,165 10726:138,201,000,240,247,136,168 10732:076,020,041,164,140,076,241 10738:189,041,173,102,063,133,175 10744:134,173,103,063,133,135,221 10750:076,207,039,160,000,177,145 10756:134,201,014,240,029,201,055 10762:001,240,025,201,031,240,236 10768:021,201,094,240,017,200,021 10774:208,235,230,135,165,135,106 10780:205,118,063,240,226,144,000 10786:224,076,090,041,200,208,105 10792:014,230,135,165,135,205,156 10798:118,063,144,005,240,003,107 10804:076,090,041,177,134,201,003 10810:000,240,233,201,014,240,218 10816:229,201,001,240,225,201,137 10822:031,240,221,201,094,240,073 10828:217,076,075,041,173,106,252 10834:063,141,209,063,173,107,070 10840:063,141,210,063,032,026,111 10846:038,169,172,160,061,032,214 10852:089,037,169,001,141,113,138 10858:063,096,056,165,134,237,089 10864:102,063,133,140,165,135,082 10870:237,103,063,005,140,208,106 10876:003,104,104,096,165,134,218 10882:133,128,165,135,133,129,185 10888:096,056,165,134,133,130,082 10894:073,255,101,128,141,213,029 10900:063,165,135,133,131,073,080 10906:255,101,129,141,214,063,033 10912:165,128,141,215,063,165,013 10918:129,141,216,063,165,130,242 10924:141,217,063,133,128,165,251 10930:131,141,218,063,133,129,225 10936:056,173,214,063,109,210,241 10942:063,205,109,063,144,016,022 10948:032,026,038,169,187,160,040 10954:061,032,089,037,169,001,079 10960:141,113,063,096,173,209,235 10966:063,133,130,173,210,063,218 10972:133,131,173,213,063,133,042 10978:132,024,109,209,063,141,136 10984:209,063,173,214,063,133,063 10990:133,109,210,063,141,210,080 10996:063,032,016,036,173,215,011 11002:063,133,128,173,216,063,002 11008:133,129,173,217,063,133,080 11014:130,173,218,063,133,131,086 11020:056,173,117,063,229,130,012 11026:133,132,173,118,063,229,098 11032:131,133,133,032,016,036,249 11038:056,173,117,063,237,213,121 11044:063,141,117,063,173,118,199 11050:063,237,214,063,141,118,110 11056:063,096,032,108,042,032,165 11062:184,040,032,137,042,056,033 11068:173,209,063,233,001,141,112 11074:209,063,173,210,063,233,249 11080:000,141,210,063,096,032,102 11086:133,040,032,108,042,032,209 11092:184,040,032,137,042,076,083 11098:059,043,032,080,042,169,003 11104:050,133,145,032,026,038,008 11110:169,199,160,061,032,089,044 11116:037,032,111,037,072,032,173 11122:010,038,104,041,095,009,155 11128:064,201,087,208,009,032,209 11134:108,042,032,237,040,076,149 11140:137,042,201,083,208,009,044 11146:032,108,042,032,155,041,036 11152:076,137,042,201,080,208,120 11158:009,032,108,042,032,082,199 11164:045,076,137,042,096,056,096 11170:165,134,237,111,063,133,237 11176:140,165,135,237,112,063,252 11182:005,140,240,026,173,111,101 11188:063,133,134,173,112,063,090 11194:133,135,169,000,133,020,008 11200:141,031,208,165,020,201,190 11206:030,208,250,076,207,039,240 11212:173,102,063,133,134,173,214 11218:103,063,133,135,076,188,140 11224:043,165,134,133,138,133,194 11230:130,165,135,133,139,133,033 11236:131,160,000,177,138,201,011 11242:000,208,030,200,208,247,103 11248:165,139,205,118,063,144,050 11254:015,173,117,063,133,138,117 11260:173,118,063,133,139,160,014 11266:000,076,011,044,230,139,246 11272:076,231,043,024,152,101,123 11278:138,133,128,169,000,101,171 11284:139,133,129,056,173,117,255 11290:063,229,130,133,132,173,118 11296:118,063,229,131,133,133,071 11302:056,165,128,229,130,141,119 11308:213,063,165,129,229,131,206 11314:141,214,063,032,016,036,040 11320:056,173,117,063,237,213,147 11326:063,141,117,063,173,118,225 11332:063,237,214,063,141,118,136 11338:063,096,169,255,141,238,012 11344:063,076,102,044,169,005,027 11350:141,238,063,032,102,044,194 11356:177,134,201,000,208,001,045 11362:200,076,075,041,169,000,147 11368:141,239,063,032,146,044,001 11374:169,000,174,238,063,160,146 11380:000,145,134,200,202,208,237 11386:250,096,169,001,141,238,249 11392:063,169,000,141,239,063,035 11398:032,146,044,169,000,160,173 11404:000,145,134,076,207,039,229 11410:024,173,117,063,109,238,102 11416:063,173,118,063,109,239,149 11422:063,205,105,063,144,005,231 11428:104,104,076,225,044,024,229 11434:165,134,133,128,109,238,053 11440:063,133,130,165,135,133,167 11446:129,109,239,063,133,131,218 11452:056,173,117,063,229,128,186 11458:133,132,173,118,063,229,018 11464:129,133,133,032,077,036,228 11470:024,173,117,063,109,238,162 11476:063,141,117,063,173,118,119 11482:063,109,239,063,141,118,183 11488:063,096,173,114,063,073,038 11494:116,141,114,063,096,169,161 11500:214,160,061,032,089,037,061 11506:032,204,047,041,127,240,165 11512:249,201,125,240,245,041,069 11518:223,201,089,096,169,008,016 11524:141,031,208,173,031,208,028 11530:201,003,240,001,096,169,208 11536:050,133,145,032,026,038,184 11542:169,237,160,061,032,089,002 11548:037,032,235,044,240,003,107 11554:076,010,038,162,250,154,212 11560:032,031,037,032,234,037,187 11566:076,072,038,160,000,177,057 11572:134,201,094,240,017,200,170 11578:208,247,230,135,165,135,154 11584:205,118,063,144,238,240,048 11590:236,076,090,041,200,208,153 11596:002,230,135,076,075,041,123 11602:165,134,133,138,165,135,184 11608:133,139,198,139,160,255,088 11614:177,138,201,094,240,017,193 11620:136,192,255,208,245,198,054 11626:139,165,139,205,103,063,152 11632:176,236,076,244,041,056,173 11638:152,101,138,133,138,169,181 11644:000,101,139,133,139,056,180 11650:165,138,229,134,133,140,045 11656:165,139,229,135,005,140,181 11662:208,018,132,140,024,165,061 11668:138,229,140,133,138,165,067 11674:139,233,000,133,139,076,106 11680:100,045,165,138,133,134,107 11686:165,139,133,135,076,207,253 11692:039,169,064,141,014,212,043 11698:169,010,141,000,002,169,157 11704:046,141,001,002,173,048,083 11710:002,133,140,173,049,002,177 11716:133,141,160,000,185,238,029 11722:045,145,140,200,192,028,184 11728:208,246,160,004,165,088,055 11734:145,140,165,089,200,145,074 11740:140,160,026,165,140,145,228 11746:140,165,141,200,145,140,133 11752:169,192,141,014,212,096,032 11758:112,112,112,195,000,000,001 11764:003,003,003,003,003,003,006 11770:003,003,003,003,003,003,012 11776:003,003,003,003,003,003,018 11782:016,065,000,000,072,173,076 11788:138,041,141,010,212,141,183 11794:024,208,141,200,002,173,254 11800:154,041,141,023,208,165,244 11806:145,141,198,002,169,010,183 11812:141,197,002,169,032,141,206 11818:244,002,169,000,141,182,012 11824:002,104,064,169,008,141,024 11830:031,208,173,031,208,201,138 11836:003,240,003,032,080,042,204 11842:032,026,038,169,252,160,231 11848:061,032,089,037,160,000,195 11854:177,134,073,128,145,134,101 11860:032,139,036,160,000,177,116 11866:134,073,128,145,134,169,105 11872:050,133,145,032,111,037,092 11878:041,095,009,064,201,087,087 11884:208,009,032,151,046,032,074 11890:035,041,076,166,046,201,167 11896:083,208,009,032,151,046,137 11902:032,001,042,076,166,046,233 11908:201,080,208,009,032,151,045 11914:046,032,049,045,076,166,040 11920:046,032,207,039,076,010,042 11926:038,165,134,133,130,141,123 11932:203,063,165,135,133,131,218 11938:141,204,063,096,056,165,119 11944:134,133,128,237,203,063,042 11950:141,213,063,165,135,133,000 11956:129,237,204,063,141,214,144 11962:063,032,160,042,173,203,091 11968:063,133,134,173,204,063,194 11974:133,135,032,139,036,076,237 11980:076,046,169,039,229,085,080 11986:141,119,063,160,000,140,065 11992:120,063,140,240,002,169,182 11998:032,032,127,047,169,126,243 12004:032,127,047,140,120,063,245 12010:032,111,037,172,120,063,001 12016:044,182,067,048,057,201,071 12022:027,208,011,169,128,141,162 12028:182,067,141,162,002,076,114 12034:231,046,201,155,240,069,176 12040:201,126,208,015,136,016,198 12046:004,200,076,231,046,169,228 12052:126,032,127,047,076,231,147 12058:046,133,140,041,127,201,202 12064:032,144,196,201,125,176,138 12070:192,204,119,063,240,187,019 12076:165,140,041,127,162,008,175 12082:142,031,208,174,031,208,076 12088:224,005,208,002,009,128,120 12094:153,163,063,032,127,047,135 12100:169,000,141,182,067,200,059 12106:076,231,046,162,001,142,220 12112:240,002,169,000,153,163,039 12118:063,152,096,162,000,169,216 12124:012,141,066,003,032,086,176 12130:228,162,000,169,153,141,183 12136:068,003,169,047,141,069,089 12142:003,169,002,141,072,003,244 12148:142,073,003,169,003,157,151 12154:066,003,076,086,228,140,209 12160:203,047,162,000,142,072,242 12166:003,142,073,003,142,255,240 12172:002,160,011,140,066,003,010 12178:032,086,228,172,203,047,146 12184:096,069,058,160,128,076,227 12190:162,047,160,000,140,104,003 12196:068,134,212,133,213,032,188 12202:170,217,032,230,216,160,171 12208:000,177,243,072,041,127,068 12214:044,104,068,048,006,032,228 12220:127,047,076,196,047,032,201 12226:098,055,104,048,003,200,190 12232:208,231,096,018,173,252,154 12238:002,201,255,208,003,169,020 12244:000,096,173,252,002,201,168 12250:255,240,249,141,109,068,000 12256:169,255,141,252,002,133,152 12262:017,032,041,048,173,109,138 12268:068,201,192,176,016,041,162 12274:063,201,060,208,024,173,203 12280:109,068,041,064,240,006,008 12286:141,190,002,169,000,096,084 12292:173,190,002,073,064,141,135 12298:190,002,169,000,096,174,129 12304:109,068,189,064,048,044,026 12310:190,002,080,010,201,097,090 12316:144,006,201,123,176,002,168 12322:041,223,201,128,240,217,060 12328:096,072,169,050,141,000,056 12334:210,162,175,142,001,210,178 12340:160,128,136,208,253,202,115 12346:224,159,208,243,104,096,068 12352:108,106,059,128,128,107,188 12358:043,042,111,128,112,117,111 12364:155,105,045,061,118,128,176 12370:099,128,128,098,120,122,009 12376:052,128,051,054,027,053,197 12382:050,049,044,032,046,110,169 12388:128,109,047,128,114,128,242 12394:101,121,127,116,119,113,035 12400:057,128,048,055,126,056,070 12406:060,062,102,104,100,128,162 12412:130,103,115,097,076,074,207 12418:058,128,128,075,092,094,193 12424:079,128,080,085,155,073,224 12430:095,124,086,128,067,128,002 12436:128,066,088,090,036,128,172 12442:035,038,027,037,034,033,102 12448:091,032,093,078,128,077,147 12454:063,128,082,128,069,089,213 12460:159,084,087,081,040,128,239 12466:041,039,156,064,125,157,248 12472:070,072,068,128,131,071,212 12478:083,065,012,010,123,128,099 12484:128,011,030,031,015,128,027 12490:016,021,155,009,028,029,204 12496:022,128,003,128,128,002,107 12502:024,026,128,128,133,128,013 12508:027,128,253,128,000,032,020 12514:096,014,128,013,128,128,221 12520:018,128,005,025,158,020,074 12526:023,017,128,128,128,128,022 12532:254,128,125,255,006,008,252 12538:004,128,132,007,019,001,029 12544:032,132,049,162,112,169,144 12550:122,157,068,003,169,062,075 12556:157,069,003,169,005,157,060 12562:072,003,169,000,157,073,236 12568:003,169,006,157,074,003,180 12574:169,003,157,066,003,032,204 12580:086,228,048,092,169,000,147 12586:141,103,068,174,103,068,187 12592:165,100,157,229,067,165,163 12598:101,157,230,067,238,103,182 12604:068,238,103,068,032,169,226 12610:049,048,063,201,043,176,134 12616:075,032,127,047,032,169,042 12622:049,048,051,169,000,141,024 12628:105,068,032,169,049,048,043 12634:041,032,127,047,238,105,168 12640:068,173,105,068,201,008,207 12646:208,008,169,046,032,127,180 12652:047,076,086,049,201,011,066 12658:208,226,169,005,133,140,227 12664:032,169,049,198,140,165,105 12670:140,208,247,076,045,049,123 12676:162,112,169,012,157,066,042 12682:003,032,086,228,162,112,249 12688:188,067,003,096,072,169,227 12694:155,032,127,047,104,032,135 12700:127,047,032,169,049,048,116 12706:225,032,127,047,076,158,059 12712:049,162,112,169,000,157,049 12718:072,003,157,073,003,169,139 12724:007,157,066,003,076,086,063 12730:228,032,255,053,032,089,107 12736:047,032,255,053,169,001,237 12742:141,240,002,133,082,169,197 12748:125,032,127,047,032,000,055 12754:049,032,239,051,173,229,215 12760:067,133,136,173,230,067,254 12766:133,137,169,000,141,228,006 12772:067,206,103,068,206,103,213 12778:068,032,227,051,032,111,243 12784:037,162,001,142,240,002,056 12790:174,025,050,201,097,144,169 12796:002,041,095,133,140,221,116 12802:025,050,240,006,202,208,221 12808:248,076,242,050,202,138,196 12814:010,170,189,042,050,072,035 12820:189,041,050,072,096,015,227 12826:030,031,028,029,004,082,230 12832:076,085,070,049,050,051,157 12838:052,027,012,070,050,083,076 12844:050,112,050,129,050,228,151 12850:050,007,051,247,050,255,198 12856:050,084,051,110,051,110,000 12862:051,110,051,110,051,152,075 12868:051,118,051,032,227,051,086 12874:174,228,067,240,031,202,248 12880:202,076,097,050,032,227,252 12886:051,174,228,067,232,232,046 12892:236,103,068,176,013,142,062 12898:228,067,189,229,067,133,243 12904:136,189,230,067,133,137,228 12910:076,235,049,032,227,051,012 12916:173,228,067,201,006,144,167 12922:243,056,233,006,170,076,138 12928:097,050,032,227,051,173,246 12934:228,067,024,105,006,205,001 12940:103,068,176,222,170,076,187 12946:097,050,162,000,189,122,254 12952:062,157,187,067,232,224,057 12958:003,208,245,160,001,177,184 12964:136,041,127,032,056,055,099 12970:201,032,240,004,157,187,223 12976:067,232,200,192,013,208,064 12982:236,189,186,067,201,046,083 12988:208,001,202,142,227,067,011 12994:169,000,157,187,067,096,102 13000:162,112,157,066,003,173,105 13006:227,067,157,072,003,169,133 13012:000,157,073,003,169,187,033 13018:157,068,003,169,067,157,071 13024:069,003,076,086,228,032,206 13030:148,050,169,033,032,200,094 13036:050,016,003,076,182,051,102 13042:032,227,051,076,235,049,144 13048:032,148,050,169,035,076,246 13054:234,050,032,148,050,169,169 13060:036,076,234,050,032,170,090 13066:051,169,079,160,063,032,052 13072:089,037,169,064,141,190,194 13078:002,032,206,046,169,000,221 13084:141,190,002,173,120,063,205 13090:240,043,032,148,050,162,197 13096:000,172,227,067,169,044,207 13102:153,187,067,200,189,163,237 13108:063,153,187,067,200,232,186 13114:236,120,063,208,243,140,044 13120:227,067,169,000,153,187,099 13126:067,032,239,051,169,032,148 13132:076,234,050,032,239,051,246 13138:076,242,050,032,170,051,191 13144:169,090,160,063,032,089,179 13150:037,032,235,044,208,235,117 13156:032,239,051,032,148,050,140 13162:169,254,076,234,050,165,030 13168:140,141,123,062,076,187,073 13174:049,162,112,142,185,067,067 13180:169,004,157,074,003,169,188 13186:000,133,142,133,143,032,201 13192:148,050,169,003,032,200,226 13198:050,048,037,032,031,037,121 13204:032,126,053,048,029,162,086 13210:250,154,169,125,032,127,243 13216:047,032,173,045,032,010,243 13222:038,076,072,038,169,022,069 13228:133,084,169,157,032,127,106 13234:047,076,127,047,140,236,083 13240:063,032,132,049,032,170,150 13246:051,169,050,160,062,032,202 13252:089,037,174,236,063,169,196 13258:000,032,160,047,169,253,095 13264:032,127,047,169,108,160,083 13270:062,032,089,037,032,111,065 13276:037,032,239,051,076,242,129 13282:050,160,012,177,136,073,066 13288:128,145,136,136,016,247,016 13294:096,032,170,051,169,000,244 13300:160,063,032,089,037,173,030 13306:123,062,076,127,047,169,086 13312:000,141,183,067,076,012,223 13318:052,169,128,141,183,067,234 13324:173,102,063,133,138,173,026 13330:103,063,133,139,076,038,058 13336:052,169,000,141,183,067,124 13342:165,134,133,138,165,135,132 13348:133,139,056,173,118,063,206 13354:229,139,170,232,160,000,204 13360:177,138,044,183,067,048,193 13366:015,201,155,208,005,169,039 13372:094,076,082,052,032,044,184 13378:038,076,082,052,201,094,097 13384:208,005,169,155,076,082,255 13390:052,032,056,055,145,138,044 13396:200,208,217,230,139,202,000 13402:208,212,096,032,026,038,190 13408:169,026,160,062,032,089,122 13414:037,169,008,032,235,052,123 13420:048,064,032,007,052,162,217 13426:112,173,102,063,157,068,021 13432:003,173,103,063,157,069,176 13438:003,056,173,117,063,237,007 13444:102,063,157,072,003,173,190 13450:118,063,237,103,063,157,111 13456:073,003,169,011,157,066,111 13462:003,032,086,228,048,011,046 13468:032,255,051,032,132,049,195 13474:048,010,076,232,053,152,221 13480:072,032,255,051,104,168,082 13486:192,128,240,033,152,072,223 13492:169,125,032,127,047,169,081 13498:050,160,062,032,089,037,104 13504:104,170,169,000,032,160,059 13510:047,032,224,052,032,173,246 13516:045,169,001,141,113,063,224 13522:096,032,026,038,169,058,117 13528:160,062,032,089,037,076,160 13534:199,052,174,185,067,169,044 13540:012,157,066,003,076,086,116 13546:228,162,112,142,185,067,106 13552:141,186,067,173,190,002,231 13558:072,169,064,141,190,002,116 13564:032,206,046,104,141,190,203 13570:002,173,120,063,208,008,064 13576:032,010,038,104,104,076,116 13582:173,045,032,224,052,174,202 13588:185,067,169,163,157,068,061 13594:003,169,063,157,069,003,234 13600:173,120,063,157,072,003,108 13606:169,000,157,073,003,173,101 13612:186,067,157,074,003,169,188 13618:003,157,066,003,076,086,185 13624:228,056,165,134,237,102,210 13630:063,133,138,133,142,165,068 13636:135,237,103,063,133,139,110 13642:133,143,005,138,240,004,225 13648:169,196,133,145,032,026,013 13654:038,169,084,160,062,032,119 13660:089,037,169,004,032,235,146 13666:052,016,003,076,174,052,215 13672:165,145,201,196,240,003,030 13678:032,031,037,032,126,053,165 13684:192,128,144,003,076,174,065 13690:052,076,232,053,174,185,126 13696:067,165,134,157,068,003,210 13702:165,135,157,069,003,056,207 13708:173,104,063,229,134,157,232 13714:072,003,173,105,063,229,023 13720:135,157,073,003,169,007,184 13726:157,066,003,032,086,228,218 13732:016,005,192,136,240,001,242 13738:096,174,185,067,024,189,137 13744:072,003,109,102,063,141,154 13750:117,063,189,073,003,109,224 13756:103,063,141,118,063,024,188 13762:173,117,063,101,142,141,163 13768:117,063,173,118,063,101,067 13774:143,141,118,063,032,025,216 13780:052,173,117,063,133,138,120 13786:173,118,063,133,139,169,245 13792:000,168,145,138,200,208,059 13798:251,096,032,224,052,016,133 13804:003,076,174,052,169,125,067 13810:032,127,047,169,074,160,083 13816:062,032,089,037,076,199,231 13822:052,169,064,141,014,212,138 13828:173,138,041,141,198,002,185 13834:141,200,002,173,154,041,209 13840:141,197,002,096,162,000,102 13846:142,205,063,142,206,063,075 13852:142,207,063,142,208,063,085 13858:056,177,138,233,016,144,030 13864:042,201,010,176,038,014,009 13870:205,063,046,206,063,014,131 13876:205,063,046,206,063,014,137 13882:205,063,046,206,063,014,143 13888:205,063,046,206,063,013,148 13894:205,063,141,205,063,200,179 13900:208,212,230,139,076,034,207 13906:054,248,173,205,063,013,070 13912:206,063,240,028,056,173,086 13918:205,063,233,001,141,205,174 13924:063,173,206,063,233,000,070 13930:141,206,063,238,207,063,000 13936:208,003,238,208,063,076,140 13942:084,054,173,207,063,216,147 13948:096,056,173,209,063,237,190 13954:106,063,141,211,063,173,119 13960:210,063,237,107,063,141,189 13966:212,063,013,211,063,208,144 13972:016,032,026,038,169,140,057 13978:160,062,032,089,037,169,191 13984:001,141,113,063,096,024,086 13990:165,134,133,128,109,211,022 13996:063,133,130,165,135,133,163 14002:129,109,212,063,133,131,187 14008:056,173,117,063,229,128,182 14014:133,132,173,118,063,229,014 14020:129,133,133,024,101,131,079 14026:205,105,063,144,016,032,255 14032:026,038,169,128,160,062,023 14038:032,089,037,169,001,141,171 14044:113,063,096,032,077,036,125 14050:024,173,211,063,133,132,194 14056:109,117,063,141,117,063,074 14062:173,212,063,133,133,109,037 14068:118,063,141,118,063,165,144 14074:134,133,130,165,135,133,056 14080:131,173,106,063,133,128,222 14086:173,107,063,133,129,032,131 14092:016,036,076,207,039,160,034 14098:000,177,134,170,200,177,108 14104:134,136,145,134,200,138,143 14110:145,134,096,160,000,177,230 14116:134,041,063,201,033,144,140 14122:010,201,059,176,006,177,159 14128:134,073,064,145,134,076,162 14134:133,040,072,041,128,133,089 14140:140,104,041,127,201,096,001 14146:176,011,201,064,144,005,155 14152:233,064,076,079,055,105,172 14158:032,005,140,096,005,075,175 14164:066,005,058,001,001,001,216 14170:000,001,000,080,027,014,212 14176:015,018,141,244,063,138,203 14182:072,152,072,056,173,228,087 14188:063,237,230,063,173,229,079 14194:063,237,231,063,144,049,133 14200:169,001,141,254,002,162,081 14206:112,169,000,157,072,003,127 14212:157,073,003,169,011,157,190 14218:066,003,173,244,063,032,207 14224:086,228,008,169,000,141,008 14230:254,002,040,016,009,032,247 14236:174,052,162,250,154,076,000 14242:072,038,173,255,002,208,142 14248:251,104,168,104,170,173,114 14254:244,063,096,032,026,038,161 14260:169,183,160,062,076,089,151 14266:037,076,215,056,032,026,116 14272:038,169,158,160,062,032,043 14278:089,037,032,255,053,169,065 14284:008,032,235,052,016,003,038 14290:076,215,056,032,255,053,129 14296:032,177,055,162,000,142,016 14302:220,063,142,219,063,142,047 14308:240,063,142,241,063,142,095 14314:181,067,189,082,055,157,197 14320:221,063,232,224,012,208,176 14326:245,169,255,141,235,063,074 14332:141,233,063,162,004,189,020 14338:093,055,157,067,064,202,128 14344:208,247,173,102,063,133,166 14350:138,173,103,063,133,139,251 14356:160,000,140,234,063,204,053 14362:233,063,240,006,173,221,194 14368:063,141,234,063,177,138,080 14374:016,003,076,166,057,201,045 14380:094,240,041,153,179,064,047 14386:200,238,234,063,173,234,168 14392:063,205,222,063,144,230,215 14398:140,116,063,177,138,201,129 14404:000,240,017,206,234,063,060 14410:136,208,244,172,116,063,245 14416:200,177,138,201,000,240,012 14422:001,136,140,116,063,152,182 14428:056,101,138,133,138,165,055 14434:139,105,000,133,139,160,006 14440:000,173,235,063,201,255,007 14446:208,003,032,077,057,173,148 14452:233,063,240,003,032,117,036 14458:057,056,046,233,063,173,238 14464:116,063,141,115,063,169,027 14470:179,133,142,169,064,133,186 14476:143,032,220,060,032,134,249 14482:057,173,235,063,205,225,080 14488:063,144,003,032,238,056,176 14494:056,165,138,237,117,063,166 14500:133,140,165,139,237,118,072 14506:063,005,140,240,060,144,054 14512:058,173,220,063,240,011,173 14518:169,000,141,219,063,141,147 14524:224,063,032,238,056,173,206 14530:163,063,201,069,208,015,145 14536:169,155,032,127,047,169,131 14542:108,160,062,032,089,037,182 14548:032,111,037,032,132,049,093 14554:162,250,154,032,173,045,010 14560:169,125,032,127,047,032,244 14566:010,038,076,072,038,076,028 14572:020,056,056,173,223,063,059 14578:237,235,063,168,136,136,193 14584:240,008,048,006,032,152,222 14590:057,136,208,250,173,220,018 14596:063,240,017,141,115,063,131 14602:169,180,133,142,169,066,101 14608:133,143,032,117,057,032,018 14614:220,060,032,152,057,032,063 14620:152,057,032,152,057,238,204 14626:228,063,208,003,238,229,235 14632:063,173,227,063,208,031,037 14638:056,173,228,063,237,230,009 14644:063,173,229,063,237,231,024 14650:063,144,016,032,026,038,121 14656:169,197,160,062,032,089,005 14662:037,032,111,037,032,177,240 14668:055,173,219,063,240,017,075 14674:141,115,063,169,179,133,114 14680:142,169,065,133,143,032,004 14686:117,057,032,220,060,172,240 14692:224,063,140,235,063,136,193 14698:240,008,048,006,032,152,080 14704:057,136,208,250,096,169,004 14710:032,172,221,063,140,234,212 14716:063,240,006,032,098,055,106 14722:136,208,250,096,172,226,194 14728:063,024,152,109,235,063,014 14734:141,235,063,032,152,057,054 14740:136,208,250,096,169,155,138 14746:032,098,055,173,181,067,248 14752:240,003,032,098,055,096,172 14758:141,237,063,041,127,032,039 14764:056,055,174,241,057,221,208 14770:241,057,240,009,202,208,111 14776:248,206,234,063,076,246,233 14782:058,202,138,010,170,140,140 14788:236,063,169,057,072,169,194 14794:212,072,189,004,058,072,041 14800:189,003,058,072,096,056,170 14806:173,236,063,101,138,133,034 14812:138,165,139,105,000,133,132 14818:139,076,020,056,177,138,064 14824:201,094,240,001,136,140,020 14830:236,063,096,017,119,108,109 14836:114,116,098,115,110,104,133 14842:102,064,112,063,120,109,052 14848:105,103,106,097,058,115,072 14854:058,125,058,135,058,145,073 14860:058,155,058,165,058,180,174 14866:058,214,058,071,058,087,052 14872:058,055,058,045,058,036,078 14878:058,239,058,024,059,106,062 14884:058,200,169,000,141,233,069 14890:063,076,230,057,200,032,188 14896:020,054,141,232,063,076,122 14902:230,057,200,032,020,054,135 14908:141,230,063,173,208,063,170 14914:141,231,063,076,230,057,096 14920:200,032,020,054,141,228,235 14926:063,173,208,063,141,229,187 14932:063,076,230,057,200,032,230 14938:020,054,141,223,063,076,155 14944:230,057,169,000,141,227,152 14950:063,200,076,230,057,169,129 14956:010,141,181,067,200,076,015 14962:230,057,200,032,020,054,195 14968:141,221,063,076,230,057,140 14974:200,032,020,054,141,222,027 14980:063,076,230,057,200,032,022 14986:020,054,141,224,063,076,204 14992:230,057,200,032,020,054,225 14998:141,225,063,076,230,057,174 15004:200,032,020,054,141,226,061 15010:063,076,230,057,172,236,228 15016:063,200,152,072,032,238,157 15022:056,104,168,140,236,063,173 15028:096,032,207,058,136,140,081 15034:219,063,160,001,177,138,176 15040:153,178,065,200,204,219,187 15046:063,144,245,240,243,200,053 15052:076,230,057,200,177,138,058 15058:201,094,208,249,096,032,066 15064:207,058,136,140,220,063,016 15070:160,001,177,138,153,179,006 15076:066,200,204,220,063,144,101 15082:245,240,243,076,230,057,045 15088:032,207,058,076,230,057,132 15094:200,177,138,201,029,240,207 15100:007,136,173,237,063,076,176 15106:047,056,200,032,020,054,155 15112:072,173,237,063,041,127,209 15118:170,104,157,051,064,032,080 15124:230,057,076,213,057,160,045 15130:001,162,000,177,138,201,193 15136:094,240,012,032,056,055,009 15142:157,163,063,200,232,224,053 15148:014,208,238,142,120,063,061 15154:169,000,157,163,063,162,252 15160:096,142,185,067,169,004,207 15166:141,186,067,032,016,053,045 15172:016,003,076,155,055,169,030 15178:000,133,142,133,143,032,145 15184:031,037,032,126,053,016,119 15190:003,076,155,055,104,104,071 15196:162,112,141,185,067,076,067 15202:010,056,032,145,059,173,061 15208:245,063,240,022,032,060,254 15214:060,032,183,059,173,243,092 15220:063,201,255,240,009,032,148 15226:095,060,032,139,036,076,048 15232:111,059,076,010,038,169,079 15238:008,141,031,208,173,031,214 15244:208,201,003,208,038,032,062 15250:026,038,169,229,160,062,062 15256:032,089,037,032,206,046,082 15262:141,245,063,208,003,076,126 15268:010,038,160,000,185,163,208 15274:063,153,246,063,200,204,075 15280:120,063,208,244,076,010,129 15286:038,165,134,133,138,165,187 15292:135,133,139,169,255,141,136 15298:243,063,160,001,162,000,055 15304:173,245,063,240,083,189,169 15310:246,063,032,044,038,209,070 15316:138,240,005,224,000,208,003 15322:235,202,200,208,011,230,024 15328:139,165,139,205,118,063,029 15334:240,002,176,054,232,236,146 15340:245,063,208,221,024,152,125 15346:101,138,133,140,165,139,034 15352:105,000,133,141,173,117,149 15358:063,197,140,173,118,063,240 15364:229,141,144,024,056,165,251 15370:140,237,245,063,133,134,194 15376:141,242,063,165,141,233,233 15382:000,133,135,141,243,063,225 15388:032,207,039,096,032,026,204 15394:038,169,235,160,062,032,218 15400:089,037,169,001,141,113,078 15406:063,096,169,008,141,031,042 15412:208,173,031,208,201,003,108 15418:208,035,032,026,038,169,054 15424:245,160,062,032,089,037,177 15430:032,206,046,141,020,064,067 15436:240,014,160,000,185,163,070 15442:063,153,021,064,200,204,019 15448:120,063,208,244,076,010,041 15454:038,056,165,134,133,130,238 15460:237,242,063,133,140,165,056 15466:135,133,131,237,243,063,024 15472:005,140,208,101,169,255,222 15478:141,243,063,024,173,245,239 15484:063,101,134,133,128,169,084 15490:000,101,135,133,129,056,172 15496:173,117,063,229,130,133,213 15502:132,173,118,063,229,131,220 15508:133,133,032,016,036,056,042 15514:173,117,063,237,245,063,028 15520:141,117,063,173,118,063,067 15526:233,000,141,118,063,173,126 15532:020,064,240,041,141,238,148 15538:063,169,000,141,239,063,085 15544:032,146,044,160,000,185,239 15550:021,064,032,044,038,145,022 15556:134,200,204,020,064,208,002 15562:242,024,165,134,109,020,128 15568:064,133,134,165,135,105,176 15574:000,133,135,076,207,039,036 15580:160,000,204,115,063,240,234 15586:029,177,142,048,026,032,168 15592:056,055,032,098,055,173,189 15598:241,063,240,010,169,008,201 15604:032,098,055,169,095,032,213 15610:098,055,200,076,222,060,193 15616:096,140,236,063,041,127,191 15622:141,237,063,032,056,055,078 15628:201,099,208,027,056,173,008 15634:232,063,237,115,063,074,034 15640:056,237,221,063,168,169,170 15646:032,032,098,055,136,208,079 15652:250,172,236,063,076,252,061 15658:060,201,101,208,017,056,173 15664:173,222,063,237,115,063,153 15670:056,237,221,063,168,169,200 15676:032,076,031,061,201,117,066 15682:208,008,173,241,063,073,064 15688:001,141,241,063,201,035,242 15694:208,018,140,236,063,174,149 15700:228,063,173,229,063,032,104 15706:155,047,172,236,063,076,071 15712:252,060,174,237,063,189,047 15718:051,064,032,098,055,076,222 15724:252,060,032,026,038,056,060 15730:173,104,063,237,117,063,103 15736:170,173,105,063,237,118,218 15742:063,032,160,047,169,001,086 15748:141,113,063,096,083,112,228 15754:101,101,100,083,099,114,224 15760:105,112,116,032,051,046,094 15766:048,000,032,098,121,032,225 15772:067,104,097,114,108,101,235 15778:115,032,066,114,097,110,184 15784:110,111,110,000,066,117,170 15790:102,102,101,114,032,067,180 15796:108,101,097,114,101,100,033 15802:000,066,117,102,102,101,162 15808:114,032,070,117,108,108,229 15814:000,068,101,108,101,116,180 15820:101,032,040,083,044,087,079 15826:044,080,041,000,058,032,209 15832:065,114,101,032,121,111,248 15838:117,032,115,117,114,101,050 15844:063,032,040,089,047,078,065 15850:041,058,000,069,082,065,037 15856:083,069,032,065,076,076,129 15862:032,084,069,088,084,000,091 15868:069,114,097,115,101,032,012 15874:040,083,044,087,044,080,124 15880:041,058,032,210,197,212,246 15886:213,210,206,032,116,111,134 15892:032,101,120,105,116,000,238 15898:083,097,118,101,032,040,241 15904:068,101,118,105,099,101,112 15910:058,070,105,108,101,110,078 15916:097,109,101,041,062,000,198 15922:069,114,114,111,114,032,092 15928:035,000,066,082,069,065,117 15934:075,032,075,101,121,032,242 15940:065,098,111,114,116,000,060 15946:078,111,032,069,114,114,080 15952:111,114,115,000,076,111,095 15958:097,100,032,040,068,101,012 15964:118,105,099,101,058,070,131 15970:105,108,101,110,097,109,216 15976:101,041,062,000,032,080,164 15982:114,101,115,115,032,210,029 15988:197,212,213,210,206,000,130 15994:068,049,058,042,046,042,171 16000:077,101,109,111,114,121,249 16006:032,070,117,108,108,000,057 16012:078,111,032,116,101,120,186 16018:116,032,105,110,032,098,127 16024:117,102,102,101,114,000,176 16030:080,114,105,110,116,032,203 16036:040,068,101,118,105,099,183 16042:101,058,070,105,108,101,201 16048:110,097,109,101,041,062,184 16054:000,080,114,105,110,116,195 16060:105,110,103,046,046,046,132 16066:155,155,000,073,110,115,034 16072:101,114,116,032,110,101,006 16078:120,116,032,115,104,101,026 16084:101,116,044,032,112,114,219 16090:101,115,115,032,210,197,220 16096:212,213,210,206,000,070,111 16102:105,110,100,058,000,078,169 16108:111,116,032,102,111,117,057 16114:110,100,000,067,104,097,208 16120:110,103,101,032,116,111,053 16126:058,000,027,028,027,029,167 16132:027,030,027,031,032,195,090 16138:212,210,204,045,196,101,210 16144:108,101,116,101,032,204,166 16150:111,099,107,032,213,110,182 16156:108,111,099,107,032,210,183 16162:101,110,097,109,101,032,072 16168:197,211,195,198,111,114,042 16174:109,097,116,032,195,212,039 16180:210,204,045,204,111,097,155 16186:100,032,032,068,114,105,253 16192:118,101,032,091,177,032,103 16198:178,032,179,032,180,093,252 16204:058,032,000,082,101,110,203 16210:097,109,101,032,116,111,136 16216:058,000,070,111,114,109,038 16222:097,116,032,100,105,115,147 16228:107,000,000,000,000,000,207
The source code for SpeedScript was originally developed using the MAC/65 assembler (from Optimized Systems Software, Inc.). The MAC/65 assembler uses the standard MOS source code format, so this source code can be assembled on a variety of Atari assemblers, including EASMD from OSS and the Atari Assembler/Editor cartridge. The source code was originally broken up into a number of modules, each SAVE#’d to disk. The .INCLUDE pseudo-op was used to link all the modules together. All files must be merged together to be assembled with the Atari Assembler/Editor cartridge. Line numbers are omitted.
Most pseudo-ops are in standard MOS 6502 notation: *= updates the program counter (some assemblers use .ORG instead); .BYTE assembles a list of numbers or an ATASCII character string; .WOR, or .WORD, assembles a list of addresses into low byte/high byte format; < extracts the low byte of a 16-bit expression; > extracts the high byte of a 16-bit expression (some assemblers reverse the use of < and > others, such as EASMD and the Assembler/Editor cartridge, use a suffix of &255 and /256 to achieve the same effect); and = is used to assign an expression to a label (some assemblers use .EQU).
Beginners should make sure they understand Indirect-Y addressing, as in LDA ($FB),Y or LDA (CURR),Y. This mode is used extensively in SpeedScript.
The Atari version of SpeedScript was developed by sending the Commodore 64 source code to the Atari via modem. References to Commodore 64 Kernal ROM routines were replaced with Atari CIO routines. Some routines built into the Commodore 64’s ROM had to be programmed into Atari SpeedScript, with resulting code expansion. References to location 1 (which maps banks of ROM in and out in the 64) were omitted. The REFRESH routine, TOPCLR, and a few other routines were changed to compensate for Atari’s floating screen memory. The raster interrupt used to highlight the command line in the 64 version became a display-list interrupt. A custom character set was added to take advantage of the Atari’s special nine-line character mode. The DOS package was written to support disk functions. But much of the source code did not need to be changed at all, since SpeedScript’s machine-specific code is segregated into distinct modules. These modules were rewritten. Approximately one week was required to get a primitive version running, followed by two months of testing, debugging, and refining to complete Atari SpeedScript. Because of the new character set, the DOS package, smoother input/output programming (such as Atari’s device-independent I/O), and more logical keyboard layout, the Atari version may be the best version of SpeedScript yet.
SpeedScript is written in small modules. Some people think that subroutines are useful only when a routine is called more than once. I strongly believe in breaking up a problem into a number of discrete tasks. These tasks can be written as subroutines, then tested individually. Once all the modules are working, just link them together with JSRs and you have a working program.
I’ve also tried to use meaningful labels, but sometimes one just runs out of imagination. Comments are added below as signposts to guide you through the source code (you needn’t type them in—if you do, precede each comment with a semicolon for the sake of your assembler). Modules are also set apart with blank lines. Notice that some modules are used in rather creative ways. For example, word left/word right is used both for moving the cursor and in delimiting a word to be erased in the erase mode. Also, note that memory locations are sometimes used instead of meaningful labels. In order to fit the complete source code into memory at once, I sometimes had to compromise readability for the sake of brevity.
Crucial to the understanding of SpeedScript is the REFRESH routine. Study it carefully. REFRESH is the only routine in SpeedScript that writes directly to the screen (CIO is used to print on the command line). It automatically takes care of word-wrap and carriage returns, and provides useful pointers so that the CHECK routine can easily scroll the screen. This frees the rest of SpeedScript to just move and modify contiguous memory. Carriage returns are not padded out in memory with spaces to fill the rest of a line; the REFRESH routine takes care of this transparently.
Filename: SPEED.0
Location $1F00 is safely above DOS 2.0S, DOS 3, and OS/A+ DOS. Some DOS’s may use more memory, so you may need to reassemble SpeedScript at a higher address, usually the address of LOMEM plus 256 bytes to be safe.
          *=  $1F00
Locations used by high-speed memory move routines.
FROML = $80 FROMH = $81 DESTL = $82 DESTH = $83 LLEN = $84 HLEN = $85
CURR: Position of cursor within text memory. SCR: used by the REFRESH routine.
CURR = $86 SCR = $88
TEX: An alternate location used in tandem with CURR. COLR is used by REFRESH. TEMP is used throughout as a scratehpad pointer. INDIR is also a reusable indirect pointer. UNDERCURS stores the value of the character highlighted by the cursor.
TEX = $8A TEMP = $8C INDIR = $8E UNDERCURS = $90
WTNDCOLOR: Color of command line window supported by HIGHLIGHT. RETCHAR is the screen-code value of the return-mark (a left-pointing arrow). SPACE is the screen-code value of the space character, RED and BLUE are used as command-line colors
WINDCOLR = $91 RETCHAR = 94 SPACE = 0 RED = $32 BLUE = $74
Input/Output Control System definitions for input/output control blocks (IOCBs). CIO is the entry point for all file-oriented input/output. SHFLOK is the SHiFtLOcK flag.
ICCOM = $0342 ICBADR = $0344 ICBLEN = $0348 ICAUX1 = $034A ICAUX2 = $034B ICSTAT = $0343 SHFLOK = $02BE CIO = $E456
Called only when run from DOS. It is assumed that the author’s initials (that conveniently work out in hex) are not normally present in memory. If they are, we know that SpeedScript has been run before, so we avoid the ERASE routine to preserve the text in memory.
BEGIN     LDA 710
          STA 709
          JSR INIT
          LDA #$CB
          CMP FIRSTRUN
          STA FIRSTRUN
          BEQ SKIPERAS
          JSR ERASE
          JSR KILLBUFF
We save the DOS reset vector and change this vector to point to SpeedScript’s SYSTEM RESET routine. Since this routine is called at power-up, right after DOS.SYS runs, we need to disable the cold-start flag (location 580) and set location $09 to signify a successful disk boot.
          LDA $0C
          STA JDOS+1
          LDA $0D
          STA JDOS+2
          LDA # <JDOS
          STA $0C
          LDA # >JDOS
          STA $0D
          LDA #0
          STA 580
          LDA #1
          STA $09
SKIPERAS  JSR INIT2
          JMP MAIN
The character set for the ANTIC 3 nine-line character mode must be on an even 512-Syte boundary, so we force the assembler’s program counter to address $2000 and merge in the character set. We then link in each successive module of SpeedScript. Again, if your assembler cannot handle .INCLUDE, you’ll have to merge all these files together in the order indicated.
          *=        $2000
          .INCLUDE  #D:CHSET.SRC
          .INCLUDE  #D:SPEED.1
          .INCLUDE  #D:SUPPORT
          .INCLUDE  #D:DOSPAK
          .INCLUDE  #D:SPEED.2
          .INCLUDE  #D:DATA
          .END
Filename: CHSET.SRC
The character set here is stored as eight bytes per line, so each line defines one character. Sheldon Leemon’s INSTEDIT character editor was used to create the character set, and I wrote a special program to convert the character set into .BYTE statements. In ANTIC mode 3, each character takes up ten scan lines of vertical screen space. The characters in the lowercase portion of the character set are displayed with a blank line at the top line, then the character data from bytes 1-7 of the character set. Byte 0 of the character’s definition is displayed at the ninth line of the character. The tenth line is always blank. This lets you define characters with true descenders. The forced blank line lets you use more of the character matrix for defining a character, so these characters are larger than normal Atari characters.
          .BYTE 0,0,0,0,0,0,0,0
          .BYTE 0,24,24,24,24,24,0,24
          .BYTE 0,102,102,102,0,0,0,0
          .BYTE 0,102,255,102,102,255,102,0
          .BYTE 24,62,96,60,6,124,24,0
          .BYTE 0,204,216,48,96,204,140,0
          .BYTE 0,56,108,56,112,222,204,118
          .BYTE 0,24,24,48,0,0,0,0
          .BYTE 0,24,48,96,96,96,48,24
          .BYTE 0,48,24,12,12,12,24,48
          .BYTE 0,0,102,60,255,60,102,0
          .BYTE 0,0,24,24,126,24,24,0
          .BYTE 0,0,0,0,0,48,48,96
          .BYTE 0,0,0,0,126,0,0,0
          .BYTE 0,0,0,0,0,0,48,48
          .BYTE 0,0,6,12,24,48,96,192
          .BYTE 0,124,206,222,246,230,198,124
          .BYTE 0,24,56,24,24,24,24,126
          .BYTE 0,124,198,12,24,48,96,254
          .BYTE 0,254,12,24,56,12,198,124
          .BYTE 0,28,60,108,204,254,12,12
          .BYTE 0,254,192,252,6,6,198,124
          .BYTE 0,124,192,252,198,198,198,124
          .BYTE 0,126,6,12,24,48,96,96
          .BYTE 0,124,198,198,124,198,198,124
          .BYTE 0,124,198,198,126,12,24,48
          .BYTE 0,0,48,48,0,48,48,0
          .BYTE 0,0,48,48,0,48,48,96
          .BYTE 0,12,24,48,96,48,24,12
          .BYTE 0,0,0,126,0,0,126,0
          .BYTE 0,48,24,12,6,12,24,48
          .BYTE 0,60,102,6,12,24,0,24
          .BYTE 0,124,198,222,214,220,224,60
          .BYTE 0,124,198,198,198,254,198,198
          .BYTE 0,252,198,198,252,198,198,252
          .BYTE 0,124,198,192,192,192,198,124
          .BYTE 0,248,204,198,198,198,204,248
          .BYTE 0,254,192,192,252,192,192,254
          .BYTE 0,254,192,192,252,192,192,192
          .BYTE 0,124,198,192,222,198,198,124
          .BYTE 0,198,198,198,254,198,198,198
          .BYTE 0,126,24,24,24,24,24,126
          .BYTE 0,62,12,12,12,12,204,120
          .BYTE 0,198,204,216,240,216,204,198
          .BYTE 0,192,192,192,192,192,192,254
          .BYTE 0,198,238,254,214,198,198,198
          .BYTE 0,198,230,246,254,222,206,198
          .BYTE 0,124,198,198,198,198,198,124
          .BYTE 0,252,198,198,198,252,192,192
          .BYTE 0,124,198,198,198,222,124,14
          .BYTE 0,252,198,198,252,216,204,198
          .BYTE 0,124,198,192,124,6,198,124
          .BYTE 0,126,24,24,24,24,24,24
          .BYTE 0,198,198,198,198,198,198,124
          .BYTE 0,198,198,198,198,198,108,56
          .BYTE 0,198,198,198,214,254,238,198
          .BYTE 0,198,198,108,56,108,198,198
          .BYTE 0,102,102,102,60,24,24,24
          .BYTE 0,254,12,24,48,96,192,254
          .BYTE 0,30,24,24,24,24,24,30
          .BYTE 0,64,96,48,24,12,6,0
          .BYTE 0,240,48,48,48,48,48,240
          .BYTE 0,8,28,54,99,0,0,0
          .BYTE 0,0,0,0,0,0,0,255
          .BYTE 0,0,0,0,0,0,0,0
          .BYTE 124,194,153,153,129,153,153,230
          .BYTE 252,130,153,130,153,153,131,252
          .BYTE 124,194,153,158,158,153,194,124
          .BYTE 252,130,153,153,153,153,130,252
          .BYTE 254,130,158,132,156,158,130,254
          .BYTE 126,193,206,194,206,204,204,120
          .BYTE 124,194,153,158,145,153,194,124
          .BYTE 246,153,153,129,153,153,153,246
          .BYTE 127,97,115,50,50,115,97,127
          .BYTE 62,50,50,50,50,114,198,124
          .BYTE 230,153,146,132,146,153,153,230
          .BYTE 120,76,76,76,76,78,66,124
          .BYTE 230,153,129,129,137,153,153,230
          .BYTE 230,153,137,129,145,153,153,230
          .BYTE 124,194,153,153,153,153,194,124
          .BYTE 254,195,201,201,195,206,200,240
          .BYTE 124,194,153,153,153,146,201,118
          .BYTE 124,194,201,201,194,201,201,247
          .BYTE 126,195,158,194,249,153,195,126
          .BYTE 254,194,102,100,100,100,100,124
          .BYTE 246,153,153,153,153,153,194,124
          .BYTE 230,153,153,153,153,194,100,56
          .BYTE 246,153,153,153,137,129,153,246
          .BYTE 230,153,153,194,153,153,153,230
          .BYTE 230,153,153,195,230,100,100,124
          .BYTE 254,193,249,50,228,206,193,254
          .BYTE 120,96,120,96,126,24,30,0
          .BYTE 0,24,60,126,24,24,24,0
          .BYTE 0,24,24,24,126,60,24,0
          .BYTE 0,0,0,12,12,88,112,120
          .BYTE 0,24,12,126,12,24,0,0
          .BYTE 0,0,24,60,126,126,60,24
          .BYTE 0,0,0,124,6,126,198,126
          .BYTE 0,0,192,252,198,198,198,252
          .BYTE 0,0,0,124,198,192,198,124
          .BYTE 0,0,6,126,198,198,198,126
          .BYTE 0,0,0,124,198,254,192,124
          .BYTE 0,0,62,96,252,96,96,96
          .BYTE 6,252,0,126,198,198,198,126
          .BYTE 0,0,192,192,252,198,198,198
          .BYTE 0,0,24,0,56,24,24,60
          .BYTE 24,240,24,0,24,24,24,24
          .BYTE 0,0,192,204,216,248,204,198
          .BYTE 0,0,56,24,24,24,24,60
          .BYTE 0,0,0,204,254,254,214,198
          .BYTE 0,0,0,252,198,198,198,198
          .BYTE 0,0,0,124,198,198,198,124
          .BYTE 192,192,0,252,198,198,198,252
          .BYTE 6,6,0,126,198,198,198,126
          .BYTE 0,0,0,252,198,192,192,192
          .BYTE 0,0,0,126,192,124,6,252
          .BYTE 0,0,48,254,48,48,48,30
          .BYTE 0,0,0,198,198,198,198,126
          .BYTE 0,0,0,198,198,198,108,56
          .BYTE 0,0,0,198,214,254,124,108
          .BYTE 0,0,0,198,108,56,108,198
          .BYTE 6,252,0,198,198,198,198,126
          .BYTE 0,0,0,254,12,56,96,254
          .BYTE 14,0,14,24,24,56,24,24
          .BYTE 24,24,24,24,24,24,24,24
          .BYTE 112,0,112,24,24,28,24,24
          .BYTE 0,0,0,8,24,56,24,8
          .BYTE 0,0,0,16,16,24,28,24
          *=    *+16
          .END
Filename: SPEED.1
This module is chiefly concerned with the word processor editing functions. It contains many common subroutines, such as TOPCLR and PRMSG to clear the command line and print messages. It contains the initialization routines and takes care of memory moves (inserts and deletes). A second module, SPEED.2, is responsible for most input/output, including the printer routines. SPEED.1 is the largest file in the linked chain. UMOVE is a high-speed memory move routine. It gets its speed from self-modifying code (the $FFFFs at MOVLOOP are replaced by actual addresses when UMOVE is called). UMOVE is used to move an overlapping range of memory upward (toward location 0), so it is used to delete. Set FROML/FROMH to point to the source area of memory, DESTL/DESTH to point to the destination, and LLEN/HLEN to hold the length of the area being moved.
UMOVE     LDA FROML
          STA MOVLOOP+1
          LDA FROMH
          STA MOVLOOP+2
          LDA DESTL
          STA MOVLOOP+4
          LDA DESTH
          STA MOVLOOP+5
          LDX HLEN
          BEQ SKIPMOV
MOV1      LDA #0
MOV2      STA ENDPOS
          LDY #0
MOVLOOP   LDA $FFFF,Y
          STA $FFFF,Y
          INY
          CPY ENDPOS
          BNE MOVLOOP
          INC MOVLOOP+2
          INC MOVLOOP+5
          CPX #0
          BEQ OUT
          DEX
          BNE MOV1
SKIPMOV   LDA LLEN
          BNE MOV2
OUT       RTS
DMOVE uses the same variables as UMOVE, but it is used to move an overlapping block of memory downward (toward location $FFFF), so it is used to insert. If the block of memory to be moved does not overlap the destination area, then either routine can be used.
DMOVE     LDA HLEN
          TAX
          ORA LLEN
          BNE NOTNULL
          RTS
NOTNULL   CLC
          TXA
          ADC FROMH
          STA DMOVLOOP+2
          LDA FROML
          STA DMOVLOOP+1
          CLC
          TXA
          ADC DESTH
          STA DMOVLOOP+5
          LDA DESTL
          STA DMOVLOOP+4
          INX
          LDY LLEN
          BNE DMOVLOOP
          BEQ SKIPDMOV
DMOV1     LDY #255
DMOVLOOP  LDA $FFFF,Y
          STA $FFFF,Y
          DEY
          CPY #255
          BNE DMOVLOOP
SKIPDMOV  DEC DMOVLOOP+2
          DEC DMOVLOOP+5
          DEX
          BNE DMOV1
          RTS
REFRESH copies a screenful of text from the area of memory pointed to by TOPLIN. It works like a printer routine, fitting a line of text between the screen margins, wrapping words, and restarts at the left margin after printing a carriage return. SpeedScript constantly calls this routine while the cursor is blinking, so it has to be very fast. To eliminate flicker, it clears out the end of each line instead of first clearing the screen. It stores the length of the first screen line for the sake of the CHECK routine (which scrolls up by adding that length to TOPLIN) and the last text location referenced (so CHECK can see if the cursor has moved off the visible screen). REFRESH can automatically handle different screen widths.
REFRESH   LDA #40
          INY
          CLC
RLM: Left margin. Location $58/$59 points to the address of screen memory.
          ADC RLM
          CLC
          ADC $58
          STA SCR
          LDA $59
          ADC #0
          STA SCR+1
TOPLIN points to the first character within text to be printed at the top-left comer of the screen.
          CLC
          LDA TOPLIN
          STA TEX
          LDA TOPLIN+1
          STA TEX+1
          LDX #1
          LDA INSMODE
          STA WINDCOLR
PPAGE     LDY #0
PLINE     LDA (TEX),Y
          STA LBUFF,Y
          INY
          AND #127
          CMP #RETCHAR
          BEQ BREAK
          CPY LINELEN
          BNE PLINE
          DEY
SLOOP     LDA (TEX),Y
          AND #127
NXCUR     CMP #SPACE
          BEQ SBRK
          DEY
          BNE SLOOP
          LDY LINELEN
          DEY
SBRK      INY
BREAK     STY TEMP
          LDY #0
COPY      LDA LBUFF,Y
          STA (SCR),Y
          INY
          CPY TEMP
          BNE COPY
          CLC
          TYA
          ADC TEX
          STA TEX
          LDA TEX+1
          ADC #0
          STA TEX+1
          CPX #1
          BNE CLRLN
          STY LENTABLE
CLRLN     CPY LINELEN
          BEQ CLEARED
Character #64 (ATASCII value of O) fills the gap when a line is broken. It can be redefined to show or not show these false spaces.
          LDA #64
          STA (SCR),Y
          INY
          JMP CLRLN
CLEARED   CLC
          LDA SCR
          ADC #40
          STA SCR
          BCC INCNOT
          INC SCR+1
INCNOT    INX
          CPX #19
          BEQ PDONE
          JMP PPAGE
PDONE     LDA TEX
          STA BOTSCR
          LDA TEX+1
          STA BOTSCR+1
          RTS
The following routine fills the entire text area with space characters (screen code 0), effectively erasing all text. It is called when the program is first run and when an Erase All is performed. It also initializes the cursor position (CURR) and the end-of-text pointer (LASTLINE).
ERASE     LDA TEXSTART
          STA TEX
          STA TOPLIN
          STA LASTLINE
          STA CURR
          LDA TEXSTART+1
          STA TEX+1
          STA TOPLIN+1
          STA LASTLINE+1
          STA CURR+1
          SEC
          LDA TEXEND+1
          SBC TEXSTART+1
          TAX
          LDA #SPACE
CLRLOOP   LDY #255
          DEC TEX+1
          STA (TEX),Y
          INY
          INC TEX+1
CLR2      STA (TEX),Y
          INY
          BNE CLR2
          INC TEX+1
          DEX
          BNE CLR2
          STA (TEX),Y
          RTS
PRMSG is used anytime we need to print something at the top of the screen (the command line). Pass it the address of the message to be printed by storing the low byte of the address in the accumulator and the high byte in the Y register. The message in memory must end with a zero byte. The routine does not add a carriage return. CHROUT (character out) prints the character in the accumulator to the screen. CHROUT is a subroutine in the SUPPORT package.
PRMSG     STA TEMP
          STY TEMP+1
          LDA #1
          STA 752
          LDY #0
PRLOOP    LDA (TEMP),Y
          BEQ PREXIT
          JSR CHROUT
          INY
          BNE PRLOOP
PREXIT    RTS
GETAKEY   JSR GETIN
          BEQ GETAKEY
          RTS
JDOS      JSR PREXIT
          LDA BLINK
          BEQ NOBLINK
          LDY #0
          LDA UNDERCURS
          STA (CURR),Y
NOBLINK   JSR INIT2
          JMP MAIN
The initialization routine sets up the memory map, clears out certain flags, and enables the display-list interrupt.
INIT      LDA #125
          JSR CHROUT
          LDA #0
          STA INSMODE
          STA TEXSTART
          STA TEXEND
          STA TEXBUF
          STA BUFEND
          STA HUNTLEN
          STA REPLEN
          STA ESCFLAG
          STA SHFLOK
          STA RLM
          LDA #40
          STA LINELEN
Label END is at the end of the source code, so it points to the last address used by the object code. We use it to calculate the start-of-text memory.
          LDA # >END
          CLC
          ADC #1
          STA TEXSTART+1
Location 561 points to the display list, which holds screen information at the top of memory. We use it as the last address available for storing text or buffer text.
          LDA 561
          SEC
          SBC #1
          STA BUFEND+1
          SEC
          SBC #8
          STA TEXBUF+1
          SEC
          SBC #1
          STA TEXEND+1
          LDA #$FF
          STA FPOS+1
If location $4B is 0, then SpeedScript is booted from disk. if we booted from cassette, we free up the DOS area ($0700-$1E00) for use as the text buffer, and free up the text memory used by disk-based SpeedScript as the text buffer.
          LDA $4B
          BEQ DISKBOOT
          LDA BUFEND+1
          STA TEXEND+1
          LDA #$07
          STA TEXBUF+1
          LDA #$1E
          STA BUFEND+1
DISKBOOT  RTS
The second initialization routine turns on the display-list interrupt (HIGHLIGHT), homes the cursor, and prints the credit line.
INIT2     JSR HIGHLIGHT
          LDA TEXSTART
          STA CURR
          LDA TEXSTART+1
          STA CURR+1
          JSR REFRESH
          JSR SYSMSG
          LDA # <MSG2
          LDY # >MSG2
          JSR PRMSG
          INC MSGFLG
          JMP CHECK
SYSMSG displays “SpeedScript 3.0.” The message flag (MSGFLG) is set when a message is to be left on the screen only until the next keystroke. After that keystroke, SYSMSG is called. The INIT2 routine prints the credit line with the MSGFLG set so that you won’t have to stare at the author’s name while you’re writing—a modesty feature.
SYSMSG    JSR TOPCLR
          LDA # <MSG1
          LDY # >MSG1
          JSR PRMSG
          LDA #0
          STA MSGFLG
          RTS
TOPCLR keeps the command line clean. It is called before most messages. It’s like a one-line clear-screen. It also forces the left margin (82) to 0, and homes the cursor to the beginning of the command line by zeroing out the X and Y cursor positions (84 and 85).
TOPCLR    LDY #39
          LDA #SPACE
TOPLOOP   STA ($58),Y
          DEY
          BPL TOPLOOP
          LDA #0
          STA 82
          STA 85
          STA 84
          RTS
Convert ATASCII to screen codes
ASTOIN    PHA
          AND #128
          STA TEMP
          PLA
          AND #127
          CMP #96
          BCS LOWR
          CMP #32
          BCS NOTCTRL
          CLC
          ADC #64
          JMP LOWR
NOTCTRL   SEC
          SBC #32
LOWR      ORA TEMP
          RTS
The MAIN loop blinks the cursor, checks for keystrokes, converts them from ATASCII to screen codes, puts them in text at the CURRent position, and increments the CURRent position and LASTLINE. It also checks for special cases like the RETURN key and passes control characters to the CONTROL routine. The INSMODE flag is checked to see if we should insert a space before a character.
MAIN      LDY #0
          STY BLINK
          LDA (CURR),Y
          STA UNDERCURS
MAIN2     LDY #0
          STY SELFLAG
          LDA (CURR),Y
          EOR #$80
          STA (CURR),Y
          LDA BLINK
          EOR #1
          STA BLINK
          JSR REFRESH
WAIT      JSR GETIN
          BNE KEYPRESS
We check for the START key, and if pressed, go to the HOME cursor routine.
          LDA #8
          STA 53279
          LDA 53279
          CMP #6
          BNE FLIPIT
          LDY #0
          STY BLINK
          LDA UNDERCURS
          STA (CURR),Y
          JSR HOME
          JMP MAIN
The realtime clock (location 20), which counts in 1/60 seconds, is checked for 16/60 seconds (about 1/5 second) to see if it’s time to blink the cursor.
FLIPIT    LDA 20
          AND #16
          BEQ WAIT
          LDA #0
          STA 20
          JMP MAIN2
A key has been pressed. We check the SELECT key to see if the keystroke should be inverted.
KEYPRESS  TAX
          LDA #8
          STA 53279
          LDA 53279
          CMP #5
          BNE NOTSEL
          LDA #128
          STA SELFLAG
NOTSEL    LDY #0
          LDA UNDERCURS
          STA (CURR),Y
NOTBKS    LDA MSGFLG
          BEQ NOMSG
          TXA
          PHA
          JSR SYSMSG
          PLA
          TAX
NOMSG     TXA
          CMP #155
          BNE NOTCR
Change a carriage return into a back arrow.
          LDX #30
          JMP OVERCTRL
NOTCR     TXA
          BIT ESCFLAG
          BMI OVERCTRL
          CMP #156
          BCS CONTROL
          AND #127
          CMP #32
          BCC CONTROL
          CMP #123
          BCS CONTROL
          CMP #92
          BEQ CONTROL
          CMP #94
          BEQ CONTROL
          CMP #95
          BEQ CONTROL
OVERCTRL  TXA
          PHA
          LDY #0
          STY ESCFLAG
          LDA (CURR),Y
          CMP #RETCHAR
          BEQ DOINS
          LDA INSMODE
          BEQ NOINST
DOINS     JSR INSCHAR
NOINST    PLA
          JSR ASTOIN
          AND #127
          ORA SELFLAG
          LDY #0
Put the character into memory.
          STA (CURR),Y
          JSR REFRESH
          SEC
          LDA CURR
          SBC LASTLINE
          STA TEMP
          LDA CURR+1
          SBC LASTLINE+1
          ORA TEMP
          BCC INKURR
          LDA CURR
          ADC #0
          STA LASTLINE
          LDA CURR+1
          ADC #0
          STA LASTLINE+1
Move the cursor forward.
INKURR    INC CURR
          BNE NOINC2
          INC CURR+1
NOINC2    JSR CHECK
          JMP MAIN
CONTROL looks up a keyboard command in the list of control codes at CTBL. The first byte of CTBL is the actual number of commands. Once the position is found, this position is doubled as an index to the two-byte address table at VECT. The address of MAIN-1 is put on the stack, simulating the return address; then the address of the command routine taken from VECT is pushed. We then perform an RTS. RTS pulls the bytes off the stack as if they were put there by a JSR. This powerful technique is used to simulate ON-GOTO in machine language.
CONTROL   LDX CTBL
SRCH      CMP CTBL,X
          BEQ FOUND
          DEX
          BNE SRCH
          JMP MAIN
FOUND     DEX
          TXA
          ASL A
          TAX
          LDA # >MAIN-1
          PHA
          LDA # <MAIN-1
          PHA
          LDA VECT+1,X
          PHA
          LDA VECT,X
          PHA
          RTS
CTBL      .BYTE 35
          .BYTE 31,30,92,94,2,20,28,29
          .BYTE 126,255,4
          .BYTE 9,125,124,95,5,12,19
          .BYTE 13,18,24,26,16
          .BYTE 254,1,11,6,21,127,157
          .BYTE 3,7,156,27,15
VECT      .WORD RIGHT-1,LEFT-1,WLEFT-1,WRIGHT-1,BORDER-1,LETTERS-1
          .WORD SLEFT-1,SRIGHT-1,DELCHAR-1,INSCHAR-1,DELETE-1
          .WORD INSTGL-1,CLEAR-1,PARIGHT-1,PARLEFT-1
          .WORD ERAS-1,TLOAD-1,TSAVE-1
          .WORD DOS-1,INSBUFFER-1,SWITCH-1
          .WORD ENDTEX-1,PRINT-1
          .WORD DELIN-1,ALPHA-1,KILLBUFF-1,HUNT-1,FREEMEM-1,TAB-1
          .WORD LOTTASPACE-1,REPSTART-1,SANDR-1,EATSPACE-1,ESC-1,ONOFF-1
Toggle ESCape mode.
ESC       LDA ESCFLAG
          EOR #128
          STA ESCFLAG
          RTS
Change the character definition of the character used to fill in the end of a line. It alternates between being a blank space, and being a blank space with a tiny dot visible. This lets you see which spaces are actually part of your text and which are just used to parse the screen. Beware of the address $2204 if you reassemble at a different address (sorry, I didn’t use a label).
ONOFF     LDA $2204
          EOR #16
          STA $2204
          RTS
The CHECK routine first prevents the cursor from disappearing past the beginning or end-of-text memory and prevents us from cursoring past the end-of-text pointer. It also checks to see if the cursor has left the visible screen, scrolling with REFRESH to make the cursor visible. The double-byte SBCs are used as a 16-bit CMP macro, setting the Z and C flags just like CMP does.
CHECK     JSR CHECK2
          SEC
          LDA CURR
          SBC TOPLIN
          LDA CURR+1
          SBC TOPLIN+1
          BCS OK1
          SEC
          LDA TOPLIN
          SBC TEXSTART
          STA TEMP
          LDA TOPLIN+1
          SBC TEXSTART+1
          ORA TEMP
          BEQ OK1
          LDA CURR
          STA TOPLIN
          LDA CURR+1
          STA TOPLIN+1
          JSR REFRESH
OK1       SEC
          LDA BOTSCR
          SBC CURR
          STA TEX
          LDA BOTSCR+1
          SBC CURR+1
          STA TEX+1
          ORA TEX
          BEQ EQA
          BCS OK2
EQA       CLC
          LDA TOPLIN
          ADC LENTABLE
          STA TOPLIN
          LDA TOPLIN+1
          ADC #0
          STA TOPLIN+1
REF       JSR REFRESH
          JMP OK1
OK2       RTS
CHECK2    SEC
          LDA LASTLINE
          SBC TEXEND
          STA TEMP
          LDA LASTLINE+1
          SBC TEXEND+1
          ORA TEMP
          BCC CK3
          LDA TEXEND
          STA LASTLINE
          LDA TEXEND+1
          STA LASTLINE+1
CK3       SEC
          LDA CURR
          SBC TEXSTART
          STA TEMP
          LDA CURR+1
          SBC TEXSTART+1
          ORA TEMP
          BCS INRANGE
          LDA TEXSTART
          STA CURR
          LDA TEXSTART+1
          STA CURR+1
          RTS
INRANGE   SEC
          LDA CURR
          SBC LASTLINE
          STA TEMP
          LDA CURR+1
          SBC LASTLINE+1
          ORA TEMP
          BCS OUTRANGE
          RTS
OUTRANGE  LDA LASTLINE
          STA CURR
          LDA LASTLINE+1
          STA CURR+1
          RTS
Move cursor right. If the OPTION key is held down, we instead increase the line length.
RIGHT     LDA #8
          STA 53279
          LDA 53279
          CMP #3
          BNE CRIGHT
          LDA LINELEN
          CMP #40
          BEQ NOBIGGER
          INC LINELEN
          INC LINELEN
          DEC RLM
          JSR REFRESH
          JSR CHECK
          LDA #125
          JSR CHROUT
NOBIGGER  JMP SYSMSG
CRIGHT    INC CURR
          BNE NOINCR
          INC CURR+1
NOINCR    JMP CHECK
Move cursor left. If the OPTION key is held down, we instead decrease the line length.
LEFT      LDA #8
          STA 53279
          LDA 53279
          CMP #3
          BNE CLEFT
          LDA LINELEN
          CMP #2
          BEQ TOOSMALL
          DEC LINELEN
          DEC LINELEN
          INC RLM
          JSR REFRESH
          JSR CHECK
          LDA #125
          JSR CHROUT
TOOSMALL  JMP SYSMSG
CLEFT     LDA CURR
          BNE NODEC
          DEC CURR+1
NODEC     DEC CURR
          JMP CHECK
Word left. We look backward for a space.
WLEFT     LDA CURR
          STA TEX
          LDA CURR+1
          STA TEX+1
          DEC TEX+1
          LDY #$FF
STRIP     LDA (TEX),Y
          CMP #SPACE
          BEQ STRLOOP
          CMP #RETCHAR
          BNE WLOOP
STRLOOP   DEY
          BNE STRIP
WLOOP     LDA (TEX),Y
          CMP #SPACE
          BEQ WROUT
          CMP #RETCHAR
          BEQ WROUT
          DEY
          BNE WLOOP
          RTS
WROUT     SEC
          TYA
          ADC TEX
          STA CURR
          LDA TEX+1
          ADC #0
          STA CURR+1
          JMP CHECK
Word right. We scan forward for a space. OIDS is not a meaningful label.
WRIGHT    LDY #0
RLOOP     LDA (CURR),Y
          CMP #SPACE
          BEQ ROUT
          CMP #RETCHAR
          BEQ ROUT
          INY
          BNE RLOOP
          RTS
ROUT      INY
          BNE OIDS
          INC CURR+1
          LDA CURR+1
          CMP LASTLINE+1
          BCC OIDS
          BNE LASTWORD
OIDS      LDA (CURR),Y
          CMP #SPACE
          BEQ ROUT
          CMP #RETCHAR
          BEQ ROUT
Add the Y register to the CURRent cursor position to move the cursor. CHECK prevents illegal cursor movement. LASTWORD is called if the end of the word cannot be found before we reach the end-of-text.
ADYCURR   CLC
          TYA
          ADC CURR
          STA CURR
          LDA CURR+1
          ADC #0
          STA CURR+1
WRTN      JMP CHECK
LASTWORD  LDA LASTLINE
          STA CURR
          LDA LASTLINE+1
          STA CURR+1
          JMP CHECK
ENDTEX is tricky. If the end-of-text pointer would point to an area already visible on the screen, we just move the cursor there and call REFRESH. Otherwise, we step back 1K from the end-of-text and then scroll to the end. This is necessary since in the worst case only 18 characters of return-marks would fill the screen.
ENDTEX    LDA #0
          STA TOPLIN
          LDA LASTLINE+1
          SEC
          SBC #4
          CMP TEXSTART+1
          BCS SAFE
          LDA TEXSTART+1
SAFE      STA TOPLIN+1
          JSR REFRESH
          JMP LASTWORD
Change the border color. The display list interrupt automatically places SCRCOL into the hardware background color register #2.
BORDER    INC SCRCOL
          INC SCRCOL
          RTS
SCRCOL    .BYTE 8
Change text luminance. TEXCOLR is stored into hardware color register #1 during the display-list interrupt.
LETTERS   INC TEXCOLR
          INC TEXCOLR
          LDA TEXCOLR
          AND #15
          STA TEXCOLR
          RTS
TEXCOLR   .BYTE 2
Sentence left. We look backward for ending punctuation or a return-mark, then go forward until we run out of spaces.
SLEFT     LDA CURR
          STA TEX
          LDA CURR+1
          STA TEX+1
          DEC TEX+1
          LDY #$FF
PMANY     LDA (TEX),Y
          CMP #'.-32
          BEQ PSRCH
          CMP #'!-32
          BEQ PSRCH
          CMP #'?-32
          BEQ PSRCH
          CMP #RETCHAR
          BNE PSLOOP
PSRCH     DEY
          BNE PMANY
          RTS
PSLOOP    LDA (TEX),Y
          CMP #'.-32
          BEQ PUNCT
          CMP #'!-32
          BEQ PUNCT
          CMP #'?-32
          BEQ PUNCT
          CMP #RETCHAR
          BEQ PUNCT
          DEY
          BNE PSLOOP
          DEC TEX+1
          LDA TEX+1
          CMP TEXSTART
          BCS PSLOOP
          JMP FIRSTWORD
PUNCT     STY TEMP
          DEC TEMP
SKIPSPC   INY
          BEQ REPEAT
          LDA (TEX),Y
          CMP #SPACE
          BEQ SKIPSPC
          DEY
          JMP WROUT
REPEAT    LDY TEMP
          JMP PSLOOP
FIRSTWORD LDA TEXSTART
          STA CURR
          LDA TEXSTART+1
          STA CURR+1
          JMP CHECK
Sentence right. We look forward for ending punctuation, then skip forward until we run out of spaces.
SRIGHT    LDY #0
SRLP      LDA (CURR),Y
          CMP #'.-32
          BEQ PUNCT2
          CMP #'!-32
          BEQ PUNCT2
          CMP #'?-32
          BEQ PUNCT2
          CMP #RETCHAR
          BEQ PUNCT2
          INY
          BNE SRLP
          INC CURR+1
          LDA CURR+1
          CMP LASTLINE+1
          BEQ SRLP
          BCC SRLP
SREXIT    JMP LASTWORD
PUNCT2    INY
          BNE NOFIXCURR
          INC CURR+1
          LDA CURR+1
          CMP LASTLINE+1
          BCC NOFIXCURR
          BEQ NOFIXCURR
          JMP LASTWORD
NOFIXCURR LDA (CURR),Y
          CMP #SPACE
          BEQ PUNCT2
          CMP #'.-32
          BEQ PUNCT2
          CMP #'!-32
          BEQ PUNCT2
          CMP #'?-32
          BEQ PUNCT2
          CMP #RETCHAR
          BEQ PUNCT2
          JMP ADYCURR
The text buffer starts at a fixed location, but the end of the buffer is changed as text is added to it. To clear the buffer, we just set the end of the buffer to the value of the start of the buffer. No text is actually erased.
KILLBUFF  LDA TEXBUF
          STA TPTR
          LDA TEXBUF+1
          STA TPTR+1
          JSR TOPCLR
          LDA # <KILLMSG
          LDY # >KILLMSG
          JSR PRMSG
          LDA #1
          STA MSGFLG
          RTS
This is the second level of the general-purpose delete routines. UMOVE is the primitive core of deleting. For CTRL-D, the CURRent cursor position is the source; then a cursor command is called to update the cursor pointer. This becomes the destination. For CTRL-E, the CURRent cursor position is the destination; a cursor movement routine is called, and this becomes the source. UMOVE is then called. We actually move more than the length from the source to the end-of-text. Some extra text is moved from past the end-of-text. Since everything past the end-of-text is spaces, this neatly erases everything past the new end-of-text position. Naturally, the end-of-text pointer is updated. Before the actual delete is performed, the text to be deleted is stored in the buffer so that it can be recalled in case of error. The buffer doubles as a fail-safe device, and for moving and copying text. Checks are made to make sure that the buffer does not overflow.
DEL1      SEC
          LDA CURR
          SBC TEXSTART
          STA TEMP
          LDA CURR+1
          SBC TEXSTART+1
          ORA TEMP
          BNE DEL1A
DELABORT  PLA
          PLA
          RTS
DEL1A     LDA CURR
          STA FROML
          LDA CURR+1
          STA FROMH
          RTS
DEL2      SEC
          LDA CURR
          STA DESTL
          EOR #$FF
          ADC FROML
          STA GOBLEN
          LDA CURR+1
          STA DESTH
          EOR #$FF
          ADC FROMH
          STA GOBLEN+1
DELC      LDA FROML
          STA FROMSAV
          LDA FROMH
          STA FROMSAV+1
          LDA DESTL
          STA DESTSAV
          STA FROML
          LDA DESTH
          STA DESTSAV+1
          STA FROMH
          SEC
          LDA GOBLEN+1
          ADC TPTR+1
          CMP BUFEND+1
          BCC GOSAV
          JSR TOPCLR
          LDA # <BUFERR
          LDY # >BUFERR
          JSR PRMSG
          LDA #1
          STA MSGFLG
          RTS
GOSAV     LDA TPTR
          STA DESTL
          LDA TPTR+1
          STA DESTH
          LDA GOBLEN
          STA LLEN
          CLC
          ADC TPTR
          STA TPTR
          LDA GOBLEN+1
          STA HLEN
          ADC TPTR+1
          STA TPTR+1
          JSR UMOVE
          LDA FROMSAV
          STA FROML
          LDA FROMSAV+1
          STA FROMH
          LDA DESTSAV
          STA DESTL
          LDA DESTSAV+1
          STA DESTH
          SEC
          LDA LASTLINE
          SBC DESTL
          STA LLEN
          LDA LASTLINE+1
          SBC DESTH
          STA HLEN
          JSR UMOVE
          SEC
          LDA LASTLINE
          SBC GOBLEN
          STA LASTLINE
          LDA LASTLINE+1
          SBC GOBLEN+1
          STA LASTLINE+1
          RTS
Most delete commands end up calling the above routines. The single-character deletes must subtract 1 from the buffer pointer so that single characters are not added to the buffer. But note how short these routines are.
Delete character (BACK S)
DELCHAR   JSR DEL1
          JSR LEFT
          JSR DEL2
FIXTP     SEC
          LDA TPTR
          SBC #1
          STA TPTR
          LDA TPTR+1
          SBC #0
          STA TPTR+1
          RTS
CTRL-BACK S
DELIN     JSR RIGHT
          JSR DEL1
          JSR LEFT
          JSR DEL2
          JMP FIXTP
Called by CTRL-D. As mentioned, it stores CURR into FROML/FROMH, moves the cursor either by sentence, word, or paragraph, then stores the new position of CURR into DESTL and DESTH. The above routines perform the actual delete. CTRL-D always discards the previous contents of the buffer, for deleting text backward creates a buffer of out-of-order text. Notice how we change the color of the command window to red to warn the user of the impending deletion.
DELETE    JSR KILLBUFF
          LDA #RED
          STA WINDCOLR
          JSR TOPCLR
          LDA # <DELMSG
          LDY # >DELMSG
          JSR PRMSG
          JSR GETAKEY
          PHA
          JSR SYSMSG
          PLA
          AND #95
          ORA #64
          CMP #'W
          BNE NOTWORD
DELWORD   JSR DEL1
          JSR WLEFT
          JMP DEL2
NOTWORD   CMP #'S
          BNE NOTSENT
DELSENT   JSR DEL1
          JSR SLEFT
          JMP DEL2
NOTSENT   CMP #'P
          BNE NOTPAR
          JSR DEL1
          JSR PARLEFT
          JMP DEL2
NOTPAR    RTS
Home the cursor. This is called by the START key. We check to see if START is held down for at least 1/2 second. If it is, we move the cursor to the top of text.
HOME      SEC
          LDA CURR
          SBC TOPLIN
          STA TEMP
          LDA CURR+1
          SBC TOPLIN+1
          ORA TEMP
          BEQ TOPHOME
          LDA TOPLIN
          STA CURR
          LDA TOPLIN+1
          STA CURR+1
WAITST    LDA #0
          STA 20
          STA 53279
HOMEPAUSE LDA 20
          CMP #30
          BNE HOMEPAUSE
OUTHOME   JMP CHECK
TOPHOME   LDA TEXSTART
          STA CURR
          LDA TEXSTART+1
          STA CURR+1
          JMP WAITST
This deletes all spaces between the cursor and following nonspace text. Sometimes inventing labels can be fun.
EATSPACE  LDA CURR
          STA TEX
          STA DESTL
          LDA CURR+1
          STA TEX+1
          STA DESTH
          LDY #0
SPCSRCH   LDA (TEX),Y
          CMP #SPACE
          BNE OUTSPACE
          INY
          BNE SPCSRCH
          LDA TEX+1
          CMP LASTLINE+1
          BCC GOINC
          LDA LASTLINE
          STA TEX
          LDA LASTLINE+1
          STA TEX+1
          LDY #0
          JMP OUTSPACE
GOINC     INC TEX+1
          JMP SPCSRCH
OUTSPACE  CLC
          TYA
          ADC TEX
          STA FROML
          LDA #0
          ADC TEX+1
          STA FROMH
          SEC
          LDA LASTLINE
          SBC DESTL
          STA LLEN
          LDA LASTLINE+1
          SBC DESTH
          STA HLEN
          SEC
          LDA FROML
          SBC DESTL
          STA GOBLEN
          LDA FROMH
          SBC DESTH
          STA GOBLEN+1
          JSR UMOVE
          SEC
          LDA LASTLINE
          SBC GOBLEN
          STA LASTLINE
          LDA LASTLINE+1
          SBC GOBLEN+1
          STA LASTLINE+1
          RTS
Insert 255 spaces. Notice how it and other insert routines use TAB2.
LOTTASPACE LDA #255
          STA INSLEN
          JMP TAB2
TAB       LDA #5
          STA INSLEN
          JSR TAB2
          LDA (CURR),Y
          CMP #SPACE
          BNE NOINCY
          INY
NOINCY    JMP ADYCURR
TAB2      LDA #0
          STA INSLEN+1
          JSR INSBLOCK
          LDA #SPACE
          LDX INSLEN
          LDY #0
FILLSP    STA (CURR),Y
          INY
          DEX
          BNE FILLSP
          RTS
Insert a single space.
INSCHAR   LDA #1
          STA INSLEN
          LDA #0
          STA INSLEN+1
          JSR INSBLOCK
          LDA #SPACE
          LDY #0
          STA (CURR),Y
          JMP CHECK
A general routine to insert as many spaces as are specified by INSLEN.
INSBLOCK  CLC
          LDA LASTLINE
          ADC INSLEN
          LDA LASTLINE+1
          ADC INSLEN+1
          CMP TEXEND+1
          BCC OKINS
          PLA
          PLA
          JMP INOUT
OKINS     CLC
          LDA CURR
          STA FROML
          ADC INSLEN
          STA DESTL
          LDA CURR+1
          STA FROMH
          ADC INSLEN+1
          STA DESTH
          SEC
          LDA LASTLINE
          SBC FROML
          STA LLEN
          LDA LASTLINE+1
          SBC FROMH
          STA HLEN
          JSR DMOVE
          CLC
          LDA LASTLINE
          ADC INSLEN
          STA LASTLINE
          LDA LASTLINE+1
          ADC INSLEN+1
          STA LASTLINE+1
INOUT     RTS
Toggle insert mode. The INSMODE nag doubles as the color of the command line.
INSTGL    LDA INSMODE
          EOR #BLUE
          STA INSMODE
          RTS
Another example of modular code. This is called anytime a yes/no response is called for. It prints “Are you sure? (Y/N),” then returns with the zero flag set to true if Y was pressed, ready for the calling routine to use BEQ or BNE as a branch for yes or no. We trap out the clear-screen key in case this routine is called by Erase All, since otherwise repeating keys may instantly cancel the command. The AND #223 zaps out the distinction between uppercase and lowercase Y.
YORN      LDA # <YMSG
          LDY # >YMSG
          JSR PRMSG
YORNKEY   JSR GETIN
          AND #127
          BEQ YORNKEY
          CMP #125
          BEQ YORNKEY
          AND #223
          CMP #'Y
          RTS
Erase all text. Allowed only if the OPTION key is held down with SHIFT-CLEAR. It calls YORN to affirm the deadly deed, then calls ERASE to erase all text, INIT2 to reset some flags, then jumps back to the MAIN loop. LDX #$FA / TXS is used to clean up the stack.
CLEAR     LDA #8
          STA 53279
          LDA 53279
          CMP #3
          BEQ OKCLEAR
          RTS
OKCLEAR   LDA #RED
          STA WINDCOLR
          JSR TOPCLR
          LDA # <CLRMSG
          LDY # >CLRMSG
          JSR PRMSG
          JSR YORN
          BEQ DOIT
          JMP SYSMSG
DOIT      LDX #$FA
          TXS
          JSR ERASE
          JSR INIT2
          JMP MAIN
Paragraph right.
PARIGHT   LDY #0
PARLP     LDA (CURR),Y
          CMP #RETCHAR
          BEQ RETFOUND
          INY
          BNE PARLP
          INC CURR+1
          LDA CURR+1
          CMP LASTLINE+1
          BCC PARLP
          BEQ PARLP
          JMP LASTWORD
RETFOUND  INY
          BNE GOADY
          INC CURR+1
GOADY     JMP ADYCURR
Paragraph left. Notice the trick of decrementing the high byte of the pointer, then starting the index at 255 in order to search backward.
PARLEFT   LDA CURR
          STA TEX
          LDA CURR+1
          STA TEX+1
          DEC TEX+1
          LDY #$FF
PARLOOP   LDA (TEX),Y
          CMP #RETCHAR
          BEQ RETF2
PARCONT   DEY
          CPY #255
          BNE PARLOOP
          DEC TEX+1
          LDA TEX+1
          CMP TEXSTART+1
          BCS PARLOOP
          JMP FIRSTWORD
RETF2     SEC
          TYA
          ADC TEX
          STA TEX
          LDA #0
          ADC TEX+1
          STA TEX+1
          SEC
          LDA TEX
          SBC CURR
          STA TEMP
          LDA TEX+1
          SBC CURR+1
          ORA TEMP
          BNE TEXTOCURR
          STY TEMP
          CLC
          LDA TEX
          SBC TEMP
          STA TEX
          LDA TEX+1
          SBC #0
          STA TEX+1
          JMP PARCONT
TEXTOCURR LDA TEX
          STA CURR
          LDA TEX+1
          STA CURR+1
          JMP CHECK
This enables the display-list interrupt (DLI). The DLI allows separate background colors for the command line and the rest of the screen. It lets us change the color of the top line to flag insert mode or to warn the user with a red color that he/she should be careful. Since it is an interrupt, it is always running in the background. Interrupt routines must always be careful not to corrupt the main program.
HIGHLIGHT turns off any DLIs (by storing #64 into $D40E), sets the NMI pointer ($200/$201), creates a custom display list of IRG mode 3 (lowercase descenders, GRAPHICS 0 1/2) With DLI set in one line, then enables DLIs ($C0 into $D40E) and returns. The routine DLI is now running constantly in the background, changing the screen color of all text below the DLI.
HIGHLIGHT LDA #64
          STA $D40E
          LDA # <DLI
          STA $0200
          LDA # >DLI
          STA $0201
          LDA 560
          STA TEMP
          LDA 561
          STA TEMP+1
          LDY #0
DLOOP     LDA DLIST,Y
          STA (TEMP),Y
          INY
          CPY #28
          BNE DLOOP
          LDY #4
          LDA $58
          STA (TEMP),Y
          LDA $59
          INY
          STA (TEMP),Y
          LDY #26
          LDA TEMP
          STA (TEMP),Y
          LDA TEMP+1
          INY
          STA (TEMP),Y
          LDA #$C0
          STA $D40E
          RTS
The custom display list.
DLIST     .BYTE 112,112,112,3+64+128,0,0
          .BYTE 3,3,3,3,3,3,3,3,3,3,3,3,3
          .BYTE 3,3,3,3,3,16,65,0,0
The display-list interrupt routine stores the SCReen COLor and TEXt COLoR into the appropriate hardware registers, then stores the WINDow COLoR into 710, and #10 into 709 to set the color of the top line of the screen. This line is automatically set by the normal vertical-blank interrupt. We also force the character-set pointer to keep our character set in place whenever we’re on the editing screen.
DLI       PHA
          LDA SCRCOL
          STA $D40A
          STA $D018
          STA 712
          LDA TEXCOLR
          STA $D017
          LDA WINDCOLR
          STA 710
          LDA #10
          STA 709
          LDA #$20
          STA 756
          LDA #0
          STA $02B6
          PLA
          RTI
ERAS is called by CTRL-E. It works much like CTRL-D. Notice that the ORA #64 allows users to press either S, W, P, or CTRL-S, CTRL-W, CTRL-P, in case they have a habit of leaving the control key held down. It must call REFRESH after each move and adjust the new position of the cursor. If OPTION is held down with CTRL-E, we don’t erase the previous contents of the buffer, letting the user chain non-contiguous sections into the buffer for later recall.
ERAS      LDA #8
          STA 53279
          LDA 53279
          CMP #3
          BEQ ERAS1
          JSR KILLBUFF
ERAS1     JSR TOPCLR
          LDA # <ERASMSG
          LDY # >ERASMSG
          JSR PRMSG
ERASAGAIN LDY #0
          LDA (CURR),Y
          EOR #$80
          STA (CURR),Y
          JSR REFRESH
          LDY #0
          LDA (CURR),Y
          EOR #$80
          STA (CURR),Y
          LDA #RED
          STA WINDCOLR
          JSR GETAKEY
          AND #95
          ORA #64
          CMP #'W
          BNE NOWORD
ERASWORD  JSR ERA1
          JSR WRIGHT
          JMP ERA2
NOWORD    CMP #'S
          BNE UNSENT
ERASENT   JSR ERA1
          JSR SRIGHT
          JMP ERA2
UNSENT    CMP #'P
          BNE NOPAR
          JSR ERA1
          JSR PARIGHT
          JMP ERA2
NOPAR     JSR CHECK
          JMP SYSMSG
ERA1      LDA CURR
          STA DESTL
          STA SAVCURR
          LDA CURR+1
          STA DESTH
          STA SAVCURR+1
          RTS
ERA2      SEC
          LDA CURR
          STA FROML
          SBC SAVCURR
          STA GOBLEN
          LDA CURR+1
          STA FROMH
          SBC SAVCURR+1
          STA GOBLEN+1
          JSR DELC
          LDA SAVCURR
          STA CURR
          LDA SAVCURR+1
          STA CURR+1
          JSR REFRESH
          JMP ERASAGAIN
The INPUT routine is used to get responses from the command line. It returns the complete line in INBUFF. INLEN is the length of the input. A zero byte is stored at INBUFF+INLEN after the user presses RETURN. This routine is foolproof (I know...), since no control keys other than BACK S are allowed, unless preceded by ESCape. The SELECT key can be held down to enter inverse-video characters. The system cursor is turned on for this routine (by putting #0 into 752), then turned off when we exit (by putting #1 into 752). This routine also prevents the user from typing past the end of the command line. If the limit of typing length must be set arbitrarily, LIMIT is preset and INPUT is called at INP1. CURSIN is the MAIN loop.
INPUT     LDA #39
          SBC 85
          STA LIMIT
INP1      LDY #0
          STY INLEN
          STY 752
          LDA #32
          JSR CHROUT
          LDA #126
          JSR CHROUT
CURSIN    STY INLEN
          JSR GETAKEY
          LDY INLEN
          BIT ESCFLAG
          BMI ESCKEY
          CMP #27
          BNE NOESC
          LDA #128
          STA ESCFLAG
          STA $02A2
          JMP CURSIN
NOESC     CMP #155
          BEQ INEXIT
          CMP #126
          BNE NOBACK
          DEY
          BPL NOTZERO
          INY
          JMP CURSIN
NOTZERO   LDA #126
          JSR CHROUT
          JMP CURSIN
NOBACK    STA TEMP
          AND #127
          CMP #32
          BCC CURSIN
          CMP #125
          BCS CURSIN
          CPY LIMIT
          BEQ CURSIN
          LDA TEMP
ESCKEY    AND #127
          LDX #8
          STX 53279
          LDX 53279
          CPX #5
          BNE SKIPSEL
          ORA #128
SKIPSEL   STA INBUFF,Y
          JSR CHROUT
          LDA #0
          STA ESCFLAG
          INY
          JMP CURSIN
INEXIT    LDX #1
          STX 752
          LDA #0
          STA INBUFF,Y
          TYA
          RTS
          .END
Filename: SUPPORT
This module supports most primitive input/output functions, including a routine to clear the screen and reset the screen editor (OPENEDITOR), print a character (CHROUT), and get a key from the keyboard (GETAKEY).
OPENEDITOR LDX #0
          LDA #12
          STA ICCOM
          JSR CIO
          LDX #0
          LDA # <ENAME
          STA ICBADR
          LDA # >ENAME
          STA ICBADR+1
          LDA #2
          STA ICBLEN
          STX ICBLEN+1
          LDA #3
          STA ICCOM,X
          JMP CIO
Put the ATASCII value of the character into the accumulator and call CHROUT to print a character. The Y register is preserved. We call CIO with a buffer length of zero.
CHROUT    STY CHRYSAVE
          LDX #0
          STX ICBLEN
          STX ICBLEN+1
          STX $02FF
          LDY #11
          STY ICCOM
          JSR CIO
          LDY CHRYSAVE
          RTS
The filename of the Editor device.
ENAME .BYTE "E:"
OUTNUM and PROUTNUM print decimal numbers to the display or printer. The integer to be printed is passed with the low byte in the X register and the high byte in the accumulator. The integer to floating-point routine ($D9AA) is called first, followed by floating-point to ATASCII routine, which creates a string of ATASCII digits. The last digit of the number has bit 7 set, which we use to terminate printing.
PROUTNUM  LDY #128
          JMP OVERZAP
OUTNUM    LDY #0
OVERZAP   STY WHICHFLAG
          STX $D4
          STA $D5
          JSR $D9AA
          JSR $D8E6
          LDY #0
ONUMLOOP  LDA ($F3),Y
          PHA
          AND #$7F
          BIT WHICHFLAG
          BMI GOPCHR
          JSR CHROUT
          JMP OVERPCHR
GOPCHR    JSR PCHROUT
OVERPCHR  PLA
          BMI ONUMEXIT
          INY
          BNE ONUMLOOP
ONUMEXIT  RTS
CHRYSAVE  .BYTE 0
The system keyboard fetch routine interferes with the display-list interrupt, since the blip of each key is timed with WSYNC, which freezes the ANTIC chip for one line. This causes annoying flicker. This routine uses POKEY sound decaying from volume 15 to 0 for the keyboard feedback tone. It’s not hard to create any sound effect you want for the keyboard blip. This routine mimics the system routine fairly closely. It’s easy to expand it to allow many more keyboard functions and full processing of new keystrokes just by changing some of this code and the keyboard table.
GETIN     LDA 764
          CMP #$FF
          BNE GETCHAR
          LDA #0
          RTS
GETCHAR   LDA 764
          CMP #$FF
          BEQ GETCHAR
          STA KEYVAL
          LDA #$FF
          STA 764
Clear break flag.
          STA $11
          JSR BLIP
          LDA KEYVAL
Check for SHIFT+CTRL.
          CMP #$C0
          BCS GXIT
          AND #63
          CMP #60
          BNE NOTCAPS
          LDA KEYVAL
          AND #64
          BEQ NOTSET
          STA SHFLOK
GXIT      LDA #0
          RTS
The CAPS/LOWR key toggles the SHiFtLOcK flag to allow either only uppercase, or both uppercase and lowercase.
NOTSET    LDA SHFLOK
          EOR #64
          STA SHFLOK
          LDA #0
          RTS
NOTCAPS   LDX KEYVAL
          LDA KEYBOARD,X
          BIT SHFLOK
          BVC NOTLOCKED
          CMP #'a
          BCC NOTLOCKED
          CMP #'z+1
          BCS NOTLOCKED
          AND #223
NOTLOCKED CMP #$80
          BEQ GXIT
          RTS
The sound effect for the keyboard “blip.”
BLIP      PHA
          LDA #50
          STA $D200
          LDX #$AF
SNDLOOP   STX $D201
          LDY #128
SLOW      DEY
          BNE SLOW
          DEX
          CPX #$9F
          BNE SNDLOOP
          PLA
          RTS
KEYBOARD  .BYTE 108,106,59,128,128,107
          .BYTE 43,42,111,128,112,117
          .BYTE 155,105,45,61,118,128
          .BYTE 99,128,128,98,120,122
          .BYTE 52,128,51,54,27,53
          .BYTE 50,49,44,32,46,110
          .BYTE 128,109,47,$80,114,128
          .BYTE 101,121,127,116,119,113
          .BYTE 57,128,48,55,126,56
          .BYTE 60,62,102,104,100,128
          .BYTE 130,103,115,97,76,74
          .BYTE 58,128,128,75,92,94
          .BYTE 79,128,80,85,155,73
          .BYTE 95,124,86,128,67,128
          .BYTE 128,66,88,90,36,128
          .BYTE 35,38,27,37,34,33
          .BYTE 91,32,93,78,128,77
          .BYTE 63,$80,82,128,69,89
          .BYTE 159,84,87,81,40,128
          .BYTE 41,39,156,64,125,157
          .BYTE 70,72,68,128,131,71
          .BYTE 83,65,12,10,123,128
          .BYTE 128,11,30,31,15,128
          .BYTE 16,21,155,9,28,29
          .BYTE 22,128,3,128,128,2
          .BYTE 24,26,128,128,133,128
          .BYTE 27,128,253,128,0,32
          .BYTE 96,14,128,13,128,$80
          .BYTE 18,128,5,25,158,20
          .BYTE 23,17,128,128,128,128
          .BYTE 254,128,125,255,6,8
          .BYTE 4,128,132,7,19,1
          .END
Filename: DOSPAK
DOSPAK is a self-contained substitute for the DOS menu, although it uses several routines built into SpeedScript. The concept of DOSPAK is that all directory entries should fit on one screen. A large cursor is used to move from filename to filename. At any time, you can delete, rename, lock, unlock, or load the selected filename, just by pressing one key, or a CTRL key combination. Except for Rename, you don’t have to type the filename. You can also format the entire disk or redisplay the directory.
CATALOG fits the entire disk directory onto the screen by skipping over the sector counts, trimming up spacing, and placing three items per line. The cursor position of each filename is saved into a slot in memory so that the cursor routine can quickly and easily skip about.
CATALOG   JSR CLOSE7
          LDX #$70
          LDA # <DIRNAME
          STA ICBADR,X
          LDA # >DIRNAME
          STA ICBADR+1,X
          LDA #5
          STA ICBLEN,X
          LDA #0
          STA ICBLEN+1,X
          LDA #6
          STA ICAUX1,X
          LDA #3
          STA ICCOM,X
          JSR CIO
          BMI CLOSE7
          LDA #0
          STA XPTR
REDIR     LDX XPTR
          LDA $64
          STA SLOT,X
          LDA $65
          STA SLOT+1,X
          INC XPTR
          INC XPTR
          JSR GET7
          BMI CLOSE7
          CMP #'*+1
          BCS ENDIR
          JSR CHROUT
          JSR GET7
          BMI CLOSE7
          LDA #0
          STA DIRCOUNT
DIRLOOP   JSR GET7
          BMI CLOSE7
DNOTCR    JSR CHROUT
          INC DIRCOUNT
          LDA DIRCOUNT
          CMP #8
          BNE DNOT8
          LDA #'.
          JSR CHROUT
          JMP DIRLOOP
DNOT8     CMP #11
          BNE DIRLOOP
          LDA #5
          STA TEMP
THROW5    JSR GET7
          DEC TEMP
          LDA TEMP
          BNE THROW5
          JMP REDIR
CLOSE7    LDX #$70
          LDA #12
          STA ICCOM,X
          JSR CIO
          LDX #$70
          LDY ICSTAT,X
          RTS
ENDIR     PHA
          LDA #155
          JSR CHROUT
          PLA
          JSR CHROUT
ENDLP     JSR GET7
          BMI CLOSE7
          JSR CHROUT
          JMP ENDLP
GET7      LDX #$70
          LDA #0
          STA ICBLEN,X
          STA ICBLEN+1,X
          LDA #7
          STA ICCOM,X
          JMP CIO
The main DOS routine calls the CATALOG routine to fill the screen with filenames, then puts the cursor on the current filename, waiting for a keypress.
DOS       JSR DELITE
          JSR OPENEDITOR
          JSR DELITE
          LDA #1
          STA 752
          STA 82
          LDA #125
          JSR CHROUT
          JSR CATALOG
          JSR DOSMSG
GETNAME   LDA SLOT
          STA SCR
          LDA SLOT+1
          STA SCR+1
          LDA #0
          STA XSLOT
          DEC XPTR
          DEC XPTR
NAMELP    JSR INVNAME
          JSR GETAKEY
          LDX #1
          STX 752
Now that we’ve got a keypress, we look it up in the keypress table, then vector to the appropriate routine. This is the same ML ON-GOTO routine that we’ve used in several places in SpeedScript, including the CONTROL routine.
          LDX DOSTABLE
          CMP #97
          BCC NOPROB
          AND #95
NOPROB    STA TEMP
FINDIT    CMP DOSTABLE,X
          BEQ FOUNDIT
          DEX
          BNE FINDIT
          JMP JNAME
FOUNDIT   DEX
          TXA
          ASL A
          TAX
          LDA DOSADR+1,X
          PHA
          LDA DOSADR,X
          PHA
          RTS
The braces surround control characters, some entered with the ESCape key: cursor-left, cursor-right, cursor-up, cursor-down, CTRL-D, ESCape, and CTRL-L.
DOSTABLE  .BYTE 15
          .BYTE "{LEFT}{RIGHT}{UP}{DOWN}{D}RLUF1234{ESC}{L}"
DOSADR    .WORD DLEFT-1,DRIGHT-1,DUP-1,DDOWN-1,DELFILE-1,RENAME-1
          .WORD LOCK-1,UNLOCK-1,FORMAT-1,DRIVE-1,DRIVE-1,DRIVE-1
          .WORD DRIVE-1,ESCDOS-1,LOADIT-1
Move bar cursor left by decrementing slot pointer.
DLEFT     JSR INVNAME
          LDX XSLOT
          BEQ NRANGE
          DEX
          DEX
          JMP RESLOT
Move bar cursor right by incrementing slot pointer.
DRIGHT    JSR INVNAME
          LDX XSLOT
          INX
          INX
          CPX XPTR
          BCS NRANGE
Store new slot index.
RESLOT    STX XSLOT
          LDA SLOT,X
          STA SCR
          LDA SLOT+1,X
          STA SCR+1
NRANGE    JMP NAMELP
Move bar cursor up by subtracting 6 from the slot pointer (each slot is two bytes).
DUP       JSR INVNAME
          LDA XSLOT
          CMP #6
          BCC NRANGE
          SEC
          SBC #6
          TAX
          JMP RESLOT
Move bar cursor down by adding 6 to the slot pointer.
DDOWN     JSR INVNAME
          LDA XSLOT
          CLC
          ADC #6
          CMP XPTR
          BCS NRANGE
          TAX
          JMP RESLOT
This routine turns a filename pointed to by the bar cursor into a legal CIO filename, complete with Dx: and legal extension.
NAMER     LDX #0
COPYD     LDA DIRNAME,X
          STA FNBUFF,X
          INX
          CPX #3
          BNE COPYD
          LDY #1
COPYNAME  LDA (SCR),Y
          AND #127
          JSR INTOAS
          CMP #32
          BEQ NOSTOR
          STA FNBUFF,X
          INX
NOSTOR    INY
          CPY #13
          BNE COPYNAME
          LDA FNBUFF-1,X
          CMP #'.
          BNE NOTDOT
          DEX
NOTDOT    STX FNLEN
          LDA #0
          STA FNBUFF,X
          RTS
This routine passes any CIO command along with a formed filename.
XIO       LDX #$70
          STA ICCOM,X
          LDA FNLEN
          STA ICBLEN,X
          LDA #0
          STA ICBLEN+1,X
          LDA # <FNBUFF
          STA ICBADR,X
          LDA # >FNBUFF
          STA ICBADR+1,X
          JMP CIO
The DOS functions are quite short. NAMER builds the name; then we simply pass the number of the DOS CIO function unto XIO. If there’s no error, we return to waiting for the next keystroke; otherwise, print the DOS error message and wait for a keystroke.
DELFILE   JSR NAMER
          LDA #33
Jump to the XIO routine.
GOXIO     JSR XIO
          BPL JNAME
          JMP DOSERR
JNAME     JSR INVNAME
          JMP NAMELP
Lock a file.
LOCK      JSR NAMER
          LDA #35
          JMP GOXIO
Unlock a file.
UNLOCK    JSR NAMER
          LDA #36
          JMP GOXIO
We ask for the new name of the file, build the rename string, then jump to the XIO routine.
RENAME    JSR BOTCLR
          LDA # <RENMSG
          LDY # >RENMSG
          JSR PRMSG
          LDA #64
          STA $02BE
          JSR INPUT
          LDA #0
          STA $02BE
          LDA INLEN
          BEQ NONAME
          JSR NAMER
          LDX #0
          LDY FNLEN
          LDA #',
          STA FNBUFF,Y
          INY
COPYR     LDA INBUFF,X
          STA FNBUFF,Y
          INY
          INX
          CPX INLEN
          BNE COPYR
          STY FNLEN
          LDA #0
          STA FNBUFF,Y
          JSR DOSMSG
          LDA #32
          JMP GOXIO
NONAME    JSR DOSMSG
          JMP JNAME
Format routine. We use YORN to af firm this operation, which erases an entire disk. BOTCLR clears the bottom line of the screen.
FORMAT    JSR BOTCLR
          LDA # <FORMSG
          LDY # >FORMSG
          JSR PRMSG
          JSR YORN
          BNE NONAME
          JSR DOSMSG
          JSR NAMER
          LDA #254
          JMP GOXIO
Select new drive number and redisplay directory.
DRIVE     LDA TEMP
          STA DIRNAME+1
          JMP DOS
The Load-from-directory routine opens the file, then jumps into the SpeedScript Load routine.
LOADIT    LDX #$70
          STX IOCB
          LDA #4
          STA ICAUX1,X
          LDA #0
          STA INDIR
          STA INDIR+1
          JSR NAMER
Command 3 is for OPEN file.
          LDA #3
          JSR XIO
          BMI DOSERR
          JSR ERASE
          JSR LOADLINK
If the load ended with an error, we display the error; otherwise, we exit the DOSPAK at ESCDOS.
          BMI DOSERR
The ESCape DOS routine clears the stack, clears the screen, reenables the display-list interrupt, prints the “SpeedScript” message, then jumps back to the editing loop.
ESCDOS    LDX #$FA
          TXS
          LDA #125
          JSR CHROUT
          JSR HIGHLIGHT
          JSR SYSMSG
          JMP MAIN
BOTCLR erases the bottom two lines of the screen by positioning the cursor on the next-to-the-last line, then printing two INSERT LINE characters that push any text on these lines off the bottom of the screen. Nifty, eh?
BOTCLR    LDA #22
          STA 84
          LDA #157
          JSR CHROUT
          JMP CHROUT
This is the error routine for the DOSPAK. We print “ERROR #”, then print the error number with OUTNUM, a bell character (actually sounds like an annoying buzzer, appropriate Pavlovian treatment), then “Press RETURN.” We wait for a keystroke, then return to getting keys for the DOSPAK commands.
DOSERR    STY YSAVE
          JSR CLOSE7
          JSR BOTCLR
          LDA # <ERRMSG
          LDY # >ERRMSG
          JSR PRMSG
          LDX YSAVE
          LDA #0
          JSR OUTNUM
          LDA #253
          JSR CHROUT
          LDA # <DIRMSG
          LDY # >DIRMSG
          JSR PRMSG
          JSR GETAKEY
          JSR DOSMSG
          JMP JNAME
Inverse the filename field of the currently selected filename. Used to create the bar cursor.
INVNAME   LDY #12
INVLP     LDA (SCR),Y
          EOR #128
          STA (SCR),Y
          DEY
          BPL INVLP
          RTS
DOSMSG erases the bottom line of the screen and prints the DOSPAK command line, an abbreviated menu.
DOSMSG    JSR BOTCLR
          LDA # <DIRINS
          LDY # >DIRINS
          JSR PRMSG
          LDA DIRNAME+1
          JMP CHROUT
          .END
Filename: SPEED.2
This is the main input/output portion of SpeedScript, responsible for loading, saving, and all printing functions.
CAST and CINSTOAS (standing for Convert to ASCII and Convert INTernal code to ASCII) translate the way SpeedScript stores text in memory (internal screen codes) into ASCII so that disk files will be compatible with most other software. In addition, the return-mark is changed to character 155, and vice versa. This is why you can’t load a machine language file into SpeedScript, edit it, then save it back as a runnable modification. All back-arrows are turned into carriage returns on output, and all carriage returns (155’s) are turned into back-arrows (30’s) on input.
CAST      LDA #0
          STA CONVFLAG
          JMP CAST1
CINTOAS   LDA #128
          STA CONVFLAG
CAST1     LDA TEXSTART
          STA TEX
          LDA TEXSTART+1
          STA TEX+1
          JMP CIN
CASTOIN   LDA #0
          STA CONVFLAG
          LDA CURR
          STA TEX
          LDA CURR+1
          STA TEX+1
CIN SEC
          LDA LASTLINE+1
          SBC TEX+1
          TAX
          INX
          LDY #0
CVLOOP    LDA (TEX),Y
          BIT CONVFLAG
          BMI COTHER
          CMP #155
          BNE NOTRTN
          LDA #RETCHAR
          JMP OVEROTHER
NOTRTN    JSR ASTOIN
          JMP OVEROTHER
COTHER    CMP #RETCHAR
          BNE NOTRC
          LDA #155
          JMP OVEROTHER
NOTRC     JSR INTOAS
OVEROTHER STA (TEX),Y
          INY
          BNE CVLOOP
          INC TEX+1
          DEX
          BNE CVLOOP
          RTS
Here is where most of the input/output routines start. TSAVE saves the entire document area using the CIO block output routine (PUT TEXT). TOPEN is called by both TSAVE and TLOAD to get the filename and open the file. The device specification (D: or C:) must be typed in by the user.
TSAVE prints the Save: prompt, goes to TOPEN with an 8 (for output, the same number in OPEN 1,8,0,"D:file"), and uses IOCB #7 (LDX #$70) to send a PUT TEXT command (11). Text is written from the start-of-text with a length of LASTLINE − TEXSTART.
TSAVE     JSR TOPCLR
          LDA # <SAVMSG
          LDY # >SAVMSG
          JSR PRMSG
          LDA #8
          JSR TOPEN
          BMI ERROR
          JSR CINTOAS
          LDX #$70
          LDA TEXSTART
          STA ICBADR,X
          LDA TEXSTART+1
          STA ICBADR+1,X
          SEC
          LDA LASTLINE
          SBC TEXSTART
          STA ICBLEN,X
          LDA LASTLINE+1
          SBC TEXSTART+1
          STA ICBLEN+1,X
          LDA #11
          STA ICCOM,X
          JSR CIO
The N (negative) bit is set when an error occurs after a call to CIO or a routine that ends up calling CIO. Therefore, we can use BMI to branch on an error condition.
          BMI ERR1
          JSR CAST
          JSR CLOSE7
          BMI ERROR
          JMP FINE
ERR1      TYA
          PHA
          JSR CAST
          PLA
          TAY
The error routine uses the error number found in the Y register, prints the error message with PRMSG, and the error number with OUTNUM. The open file is closed. If the BREAK key was used to stop the operation, we distinguish this from an ordinary error, and print “BREAK Abort” instead.
ERROR     CPY #128
          BEQ STOPPED
          TYA
          PHA
          LDA #125
          JSR CHROUT
          LDA # <ERRMSG
          LDY # >ERRMSG
          JSR PRMSG
          PLA
          TAX
          LDA #0
          JSR OUTNUM
ERXIT     JSR IOCLOSE
          JSR HIGHLIGHT
          LDA #1
          STA MSGFLG
          RTS
STOPPED   JSR TOPCLR
          LDA # <BRMSG
          LDY # >BRMSG
          JSR PRMSG
          JMP ERXIT
General file closing routine. IOCB contains the channel number times 16.
IOCLOSE   LDX IOCB
          LDA #12
          STA ICCOM,X
          JMP CIO
TOPEN is used to get a filename, including the device specification. It’s used by Save, Load, and Print. It forces the CAPS key to uppercase for the filename, which is not quite as satisfactory as converting the filename if lowercase was used. It does return the CAPS key to its former value, though. TOPEN opens the file and returns with the error code in the Y register.
TOPEN     LDX #$70
          STX IOCB
          STA ACCESS
Save current CAPS value.
          LDA SHFLOK
          PHA
CAPS On.
          LDA #64
          STA SHFLOK
          JSR INPUT
Restore CAPS value.
          PLA
          STA SHFLOK
          LDA INLEN
          BNE OPCONT
OPABORT   JSR SYSMSG
          PLA
          PLA
          JMP HIGHLIGHT
OPCONT    JSR IOCLOSE
          LDX IOCB
          LDA # <INBUFF
          STA ICBADR,X
          LDA # >INBUFF
          STA ICBADR+1,X
          LDA INLEN
          STA ICBLEN,X
          LDA #0
          STA ICBLEN+1,X
          LDA ACCESS
          STA ICAUX1,X
          LDA #3
          STA ICCOM,X
          JMP CIO
The Load routine checks the cursor position. If the cursor is at the top-of-text (CURR=TEXSTART), we call the ERASE routine to wipe out memory before the load. Otherwise, the load starts at the cursor position, performing an append, and we change the command line to green ($C4, sorry about not using a label) to warn the user. We open the file for reading by passing a 4 to TOPEN, then at LOADLINK use GET TEXT (command 7) to get no more than the length of the text area. The actual length loaded is found in ICBLEN, so we add this to TEXSTART and the offset between the cursor position and TEXSTART to get the position of the end-of-text (LASTLINE).
A funny thing happens, though. Up to 255 garbage characters appear following an otherwise normal load, after the end-of-text. I was never able to figure out why (and I puzzled over it for a week), so I wrote a stopgap routine to just clear out one page past the end-of-text. The bug is not fixed per se, but it has no effect anymore! I still think it must be the fault of the operating system (I know...).
TLOAD     SEC
          LDA CURR
          SBC TEXSTART
          STA TEX
          STA INDIR
          LDA CURR+1
          SBC TEXSTART+1
          STA TEX+1
          STA INDIR+1
          ORA TEX
          BEQ LOAD2
          LDA #$C4
          STA WINDCOLR
LOAD2     JSR TOPCLR
          LDA # <LOADMSG
          LDY # >LOADMSG
          JSR PRMSG
          LDA #4
          JSR TOPEN
          BPL OKLOD
GOERROR   JMP ERROR
OKLOD     LDA WINDCOLR
          CMP #$C4
          BEQ NOER
          JSR ERASE
NOER      JSR LOADLINK
          CPY #128
          BCC JFINE
          JMP ERROR
JFINE     JMP FINE
Entry point for linked files loading.
LOADLINK  LDX IOCB
          LDA CURR
          STA ICBADR,X
          LDA CURR+1
          STA ICBADR+1,X
          SEC
          LDA TEXEND
          SBC CURR
          STA ICBLEN,X
          LDA TEXEND+1
          SBC CURR+1
          STA ICBLEN+1,X
          LDA #7
          STA ICCOM,X
          JSR CIO
          BPL TEXOK
          CPY #136
          BEQ TEXOK
          RTS
TEXOK     LDX IOCB
          CLC
          LDA ICBLEN,X
          ADC TEXSTART
          STA LASTLINE
          LDA ICBLEN+1,X
          ADC TEXSTART+1
          STA LASTLINE+1
          CLC
          LDA LASTLINE
          ADC INDIR
          STA LASTLINE
          LDA LASTLINE+1
          ADC INDIR+1
          STA LASTLINE+1
          JSR CASTOIN
          LDA LASTLINE
          STA TEX
          LDA LASTLINE+1
          STA TEX+1
          LDA #0
          TAY
NOGARBAGE STA (TEX),Y
          INY
          BNE NOGARBAGE
          RTS
FINE      JSR IOCLOSE
          BPL PROKMSG
          JMP ERROR
PROKMSG   LDA #125
          JSR CHROUT
          LDA # <OKMSG
          LDY # >OKMSG
          JSR PRMSG
          JMP ERXIT
Disable display-list interrupt and restore screen colors.
DELITE    LDA #$40
          STA $D40E
          LDA SCRCOL
          STA 710
          STA 712
          LDA TEXCOLR
          STA 709
          RTS
A rather short routine that converts a string of ASCII digits into a number in hex and the accumulator. It takes advantage of decimal mode. In decimal mode, the accumulator is adjusted after additions and subtractions so that it acts like a two-digit decimal counter. We shift BCD over a nybble and add in the left nybble of the ASCII number until we reach the end of the ASCII number. We then subtract 1 from BCD and increment X (which doesn’t conform to decimal mode) until BCD is down to 0. The X register magically holds the converted number. Naturally, decimal mode is cleared before this routine exits, or it would wreak major havoc. ASCHEX is used to convert the parameters of printer commands like left margin.
ASCHEX    LDX #0
          STX BCD
          STX BCD+1
          STX HEX
          STX HEX+1
DIGIT     SEC
          LDA (TEX),Y
          SBC #16
          BCC NONUM
          CMP #10
          BCS NONUM
          ASL BCD
          ROL BCD+1
          ASL BCD
          ROL BCD+1
          ASL BCD
          ROL BCD+1
          ASL BCD
          ROL BCD+1
          ORA BCD
          STA BCD
          INY
          BNE DIGIT
          INC TEX+1
          JMP DIGIT
NONUM     SED
DECHEX    LDA BCD
          ORA BCD+1
          BEQ DONENUM
          SEC
          LDA BCD
          SBC #1
          STA BCD
          LDA BCD+1
          SBC #0
          STA BCD+1
          INC HEX
          BNE NOHEXINC
          INC HEX+1
NOHEXINC  JMP DECHEX
DONENUM   LDA HEX
          CLD
          RTS
Insert the buffer. This is the recall routine called by CTRL-R. It must not allow an insertion that would overfill memory. It calls DMOVE to open a space in memory, then UMOVE (which is a little faster than DMOVE) to copy the buffer to the empty space.
INSBUFFER SEC
          LDA TPTR
          SBC TEXBUF
          STA BUFLEN
          LDA TPTR+1
          SBC TEXBUF+1
          STA BUFLEN+1
          ORA BUFLEN
          BNE OKBUFF
          JSR TOPCLR
          LDA # <INSMSG
          LDY # >INSMSG
          JSR PRMSG
          LDA #1
          STA MSGFLG
          RTS
OKBUFF    CLC
          LDA CURR
          STA FROML
          ADC BUFLEN
          STA DESTL
          LDA CURR+1
          STA FROMH
          ADC BUFLEN+1
          STA DESTH
          SEC
          LDA LASTLINE
          SBC FROML
          STA LLEN
          LDA LASTLINE+1
          SBC FROMH
          STA HLEN
          CLC
          ADC DESTH
          CMP TEXEND+1
          BCC OKMOV
          JSR TOPCLR
          LDA # <INSERR
          LDY # >INSERR
          JSR PRMSG
          LDA #1
          STA MSGFLG
          RTS
OKMOV     JSR DMOVE
          CLC
          LDA BUFLEN
          STA LLEN
          ADC LASTLINE
          STA LASTLINE
          LDA BUFLEN+1
          STA HLEN
          ADC LASTLINE+1
          STA LASTLINE+1
          LDA CURR
          STA DESTL
          LDA CURR+1
          STA DESTH
          LDA TEXBUF
          STA FROML
          LDA TEXBUF+1
          STA FROMH
          JSR UMOVE
          JMP CHECK
Exchange the character highlighted by the cursor with the character to the right of it. Not a vital command, but it was included due to the brevity of the code.
SWITCH    LDY #0
          LDA (CURR),Y
          TAX
          INY
          LDA (CURR),Y
          DEY
          STA (CURR),Y
          INY
          TXA
          STA (CURR),Y
          RTS
Change the case of the character highlighted by the cursor.
ALPHA     LDY #0
          LDA (CURR),Y
          AND #63
          CMP #33
          BCC NOTALPHA
          CMP #59
          BCS NOTALPHA
          LDA (CURR),Y
          EOR #64
          STA (CURR),Y
NOTALPHA  JMP RIGHT
Convert internal (screen code) format to Atari ASCII (ATASCII). Used to convert the screen-code format of SpeedScript documents to ASCII for the sake of printing.
INTOAS    PHA
          AND #128
          STA TEMP
          PLA
          AND #127
          CMP #96
          BCS XINT
INCONT    CMP #64
          BCC INT1
          SBC #64
          JMP XINT
INT1      ADC #32
XINT      ORA TEMP
          RTS
The start of the printer routines. This part could logically be called a separate program, but many variables are common to the above code.
DEFTAB: Table of default settings for left margin, right margin, page length, top margin, bottom margin, etc. See the table starting at LMARGIN at the end of this source code.
DEFTAB .BYTE 5,75,66,5,58,1,1,1,0,1,0,80
Table of default printer codes.
PRCODES .BYTE 27,14,15,18
Another advantage of modular coding is that you can change the behavior of a lot of code by just changing one small common routine. This is a substitute for the normal CHROUT routine. It checks to see if the current page number equals the page number specified by the user to start printing. It also checks for the BREAK to abort the printing and permits printing to be paused with CTRL-1.
PCHROUT   STA PCR
          TXA
          PHA
          TYA
          PHA
          SEC
          LDA PAGENUM
          SBC STARTNUM
          LDA PAGENUM+1
          SBC STARTNUM+1
          BCC SKIPOUT
          LDA #1
          STA 766
          LDX #$70
          LDA #0
          STA ICBLEN,X
          STA ICBLEN+1,X
          LDA #11
          STA ICCOM,X
          LDA PCR
          JSR CIO
          PHP
          LDA #0
          STA 766
          PLP
          BPL SHIFTFREEZE
ERRLINK   JSR ERROR
          LDX #$FA
          TXS
          JMP MAIN
SHIFTFREEZE LDA $02FF ;CTRL-1
          BNE SHIFTFREEZE
SKIPOUT   PLA
          TAY
          PLA
          TAX
          LDA PCR
          RTS
Displays “Printing...”
PRIN      JSR TOPCLR
          LDA # <PRINMSG
          LDY # >PRINMSG
          JMP PRMSG
PBORT     JMP PEXIT
Called by CTRL-P. We get the filename to print to (usually P:, although you can use E: to print to the screen) with ICAUX1 set to 8 for output. We exit on any error. The DELITE routine turns off the display-list interrupt, which might otherwise interfere with output timing.
PRINT     JSR TOPCLR
          LDA # <FNMSG
          LDY # >FNMSG
          JSR PRMSG
          JSR DELITE
          LDA #8
          JSR TOPEN
          BPL PROK
          JMP PEXIT
Reset several flags (footer length, header length, true ASCII, underline mode, and linefeed mode). Notice how DELITE is called again. This isn’t a mistake. The first time we called DELITE, we then may have opened a file to the Editor device. This reset the screen to the default colors, so the second DELITE retains the user’s true color choice.
PROK      JSR DELITE
          JSR PRIN
          LDX #0
          STX FTLEN
          STX HDLEN
          STX NEEDASC
          STX UNDERLINE
          STX LINEFEED
Copy definition tables and default printercodes.
COPYDEF   LDA DEFTAB,X
          STA LMARGIN,X
          INX
          CPX #12
          BNE COPYDEF
          LDA #$FF
          STA LINE
          STA NOMARG
          LDX #4
COPYDEFS  LDA PRCODES-1,X
          STA CODEBUFFER+16,X
          DEX
          BNE COPYDEFS
Reentry point for printing after linked files.
RETEX     LDA TEXSTART
          STA TEX
          LDA TEXSTART+1
          STA TEX+1
Main printing loop. We print the left margin, grab a line of text, scan backward until we find a space or a carriage return, then break the line there. If printer codes are encountered, they’re passed on to the SPECIAL routine. Otherwise, we end up calling BUFPRT to print the line and process some other control codes.
PLOOP     LDY #0
          STY POS
          CPY NOMARG
          BEQ PLOOP1
          LDA LMARGIN
          STA POS
PLOOP1    LDA (TEX),Y
          BPL NOTSP
          JMP SPECIAL
NOTSP     CMP #RETCHAR
          BEQ FOUNDSPACE
NOTRET    STA PRBUFF,Y
          INY
          INC POS
          LDA POS
          CMP RMARGIN
          BCC PLOOP1
          STY FINPOS
FINDSPACE LDA (TEX),Y
          CMP #SPACE
          BEQ FOUNDSPACE
          DEC POS
          DEY
          BNE FINDSPACE
          LDY FINPOS
FSPACE    INY
          LDA (TEX),Y
          CMP #SPACE
          BEQ FOUNDSPACE
          DEY
FOUNDSPACE STY FINPOS
OVERSTOR TYA
          SEC
          ADC TEX
          STA TEX
          LDA TEX+1
          ADC #0
          STA TEX+1
          LDY #0
If this is the first page, we need to print the header, if any, with JSR TOP.
DOBUFF    LDA LINE
          CMP #$FF
          BNE DOBUF2
          JSR TOP
DOBUF2    LDA NOMARG
          BEQ OVERMARG
          JSR LMARG
OVERMARG  SEC
          ROL NOMARG
          LDA FINPOS
          STA ENDPOS
          LDA # <PRBUFF
          STA INDIR
          LDA # >PRBUFF
          STA INDIR+1
          JSR BUFPRT
A line has been printed. We check to see if we’ve hit the bottom margin and, if so, go to PAGE, which goes to the end of the page, prints the footer (if any), and feeds to the next page.
ZBUFF     JSR CRLF
          LDA LINE
          CMP BOTMARG
          BCC NOTPAGE
          JSR PAGE
Have we reached the end-of-text?
NOTPAGE   SEC
          LDA TEX
          SBC LASTLINE
          STA TEMP
          LDA TEX+1
          SBC LASTLINE+1
          ORA TEMP
          BEQ DORPT
          BCC DORPT
If so, we check for a footer. If there is one, we set HDLEN and TOPMARG to 0 (so that the printhead will end up at the right place on the last page) and call PAGE, which prints the footer. If there is no footer, we leave the printhead on the same page so that paper isn’t wasted.
          LDA FTLEN
          BEQ PXIT
          LDA #0
          STA HDLEN
          STA TOPMARG
          JSR PAGE
Exit routines. If screen output was selected, we wait for a keystroke before going back to editing mode.
PXIT      LDA INBUFF
          CMP #'E
          BNE PEXIT
          LDA #155
          JSR CHROUT
          LDA # <DIRMSG
          LDY # >DIRMSG
          JSR PRMSG
          JSR GETAKEY
PEXIT     JSR CLOSE7
          LDX #$FA
          TXS
          JSR HIGHLIGHT
          LDA #125
          JSR CHROUT
          JSR SYSMSG
          JMP MAIN
DORPT     JMP PLOOP
Paging routines. We skip (PAGELENGTH − LINE) — two blank lines to get to the bottom of the page, print a footer (if there is one) or a blank line (if not), then page to the beginning of the next page, skipping over the paper perforation. If the wait mode is enabled, we wait for the user to insert a new sheet of paper.
PAGE      SEC
          LDA PAGELENGTH
          SBC LINE
          TAY
          DEY
          DEY
          BEQ NOSK
          BMI NOSK
NEXPAGE   JSR CR
          DEY
          BNE NEXPAGE
NOSK      LDA FTLEN
          BEQ SKIPFT
          STA ENDPOS
          LDA # <FTBUFF
          STA INDIR
          LDA # >FTBUFF
          STA INDIR+1
          JSR LMARG
          JSR BUFPRT
SKIPFT    JSR CR
          JSR CR
          JSR CR
Increment the page number.
          INC PAGENUM
          BNE NOIPN
          INC PAGENUM+1
The page wait mode is inappropriate when printing to the screen or to disk, or when skipping over pages with the ? format command.
NOIPN     LDA CONTINUOUS
          BNE TOP
          SEC
          LDA PAGENUM
          SBC STARTNUM
          LDA PAGENUM+1
          SBC STARTNUM+1
          BCC TOP
          JSR TOPCLR
          LDA # <WAITMSG
          LDY # >WAITMSG
          JSR PRMSG
          JSR GETAKEY
          JSR PRIN
Print the header; skip to the top margin.
TOP       LDA HDLEN
          BEQ NOHEADER
          STA ENDPOS
          LDA # <HDBUFF
          STA INDIR
          LDA # >HDBUFF
          STA INDIR+1
          JSR LMARG
          JSR BUFPRT
NOHEADER  LDY TOPMARG
          STY LINE
          DEY
          BEQ SKIPTOP
          BMI SKIPTOP
TOPLP     JSR CR
          DEY
          BNE TOPLP
SKIPTOP   RTS
Left margin routine. This routine is not called if NOMARG is selected (margin release).
LMARG     LDA #32
          LDY LMARGIN
          STY POS
          BEQ LMEXIT
LMLOOP    JSR PCHROUT
          DEY
          BNE LMLOOP
LMEXIT    RTS
CRLF is called at the end of most printed lines. It increments the LINE count and takes into account the current line spacing mode set by the a format command.
CRLF      LDY SPACING
          CLC
          TYA
          ADC LINE
          STA LINE
CRLOOP    JSR CR
          DEY
          BNE CRLOOP
          RTS
CR just prints a single carriage return and linefeed (if specified).
CR        LDA #155
          JSR PCHROUT
          LDA LINEFEED
          BEQ NOLF
          JSR PCHROUT
NOLF      RTS
Handle special printer codes like left margin. This looks up the printer code using a routine similar to CONTROL.
SPECIAL   STA SAVCHAR
          AND #127
          JSR INTOAS
          LDX SPTAB
SRCHSP    CMP SPTAB,X
          BEQ FSP
          DEX
          BNE SRCHSP
          DEC POS
          JMP DEFINE
FSP       DEX
          TXA
          ASL A
          TAX
          STY YSAVE
          LDA # >SPCONT-1
          PHA
          LDA # <SPCONT-1
          PHA
          LDA SPVECT+1,X
          PHA
          LDA SPVECT,X
          PHA
          RTS
After the format code is processed, we must skip over the format command and its parameter so that it’s not printed.
SPCONT    SEC
          LDA YSAVE
          ADC TEX
          STA TEX
          LDA TEX+1
          ADC #0
          STA TEX+1
          JMP PLOOP
If the format command ends with a return-mark, we must skip over the return-mark as well.
SPCEXIT   LDA (TEX),Y
          CMP #RETCHAR
          BEQ NOAD
          DEY
NOAD      STY YSAVE
          RTS
Special format code table. It starts with the number of format commands, then the characters for each format command.
SPTAB     .BYTE 17
          .BYTE "wlrtbsnhf@p?xmigj"
The address-1 of each format routine.
SPVECT    .WORD PW-1,LM-1,RM-1,TP-1
          .WORD BT-1,SP-1,NX-1,HD-1,FT-1
          .WORD PN-1,PL-1,SPAGE-1,ACROSS-1
          .WORD MRELEASE-1,COMMENT-1,LINK-1
          .WORD LFSET-1
m Margin release. INY is used to skip over the format character.
MRELEASE  INY
          LDA #0
          STA NOMARG
          JMP SPCEXIT
x Columns across, used by centering.
ACROSS    INY
          JSR ASCHEX
          STA PAGEWIDTH
          JMP SPCEXIT
? Start printing at specified page.
SPAGE     INY
          JSR ASCHEX
          STA STARTNUM
          LDA HEX+1
          STA STARTNUM+1
          JMP SPCEXIT
@ Set starting default page number.
PN        INY
          JSR ASCHEX
          STA PAGENUM
          LDA HEX+1
          STA PAGENUM+1
          JMP SPCEXIT
p Page length.
PL        INY
          JSR ASCHEX
          STA PAGELENGTH
          JMP SPCEXIT
w Set page wait mode.
PW        LDA #0
          STA CONTINUOUS
          INY
          JMP SPCEXIT
j Set linefeed mode.
LFSET     LDA #10
          STA LINEFEED
          INY
          JMP SPCEXIT
l Left margin.
LM        INY
          JSR ASCHEX
          STA LMARGIN
          JMP SPCEXIT
r Right margin.
RM        INY
          JSR ASCHEX
          STA RMARGIN
          JMP SPCEXIT
t Top margin.
TP        INY
          JSR ASCHEX
          STA TOPMARG
          JMP SPCEXIT
b Bottom margin.
BT        INY
          JSR ASCHEX
          STA BOTMARG
          JMP SPCEXIT
s Set line spacing.
SP        INY
          JSR ASCHEX
          STA SPACING
          JMP SPCEXIT
n Jump to next page.
NX        LDY YSAVE
          INY
          TYA
          PHA
          JSR PAGE
          PLA
          TAY
          STY YSAVE
          RTS
h Define header. Copy header into header buffer.
HD        JSR PASTRET
          DEY
          STY HDLEN
          LDY #1
HDCOPY    LDA (TEX),Y
          STA HDBUFF-1,Y
          INY
          CPY HDLEN
          BCC HDCOPY
          BEQ HDCOPY
          INY
          JMP SPCEXIT
Skip just past the return-mark.
PASTRET   INY
          LDA (TEX),Y
          CMP #RETCHAR
          BNE PASTRET
          RTS
f Define footer.
FT        JSR PASTRET
          DEY
          STY FTLEN
          LDY #1
FTCOPY    LDA (TEX),Y
          STA FTBUFF-1,Y
          INY
          CPY FTLEN
          BCC FTCOPY
          BEQ FTCOPY
          JMP SPCEXIT
i Ignore a line of information.
COMMENT   JSR PASTRET
          JMP SPCEXIT
Define programmable printkeys. We check for =. If not found, this is not an assignment, so we just skip past the code. Otherwise, we use the screen code value as the index into the CODEBUFFER and put the value there, ready to be called during printing by BUFPRT.
DEFINE    INY
          LDA (TEX),Y
          CMP #'=-32
          BEQ DODEFINE
          DEY
          LDA SAVCHAR
          JMP NOTRET
DODEFINE  INY
          JSR ASCHEX
          PHA
          LDA SAVCHAR
          AND #127
          TAX
          PLA
          STA CODEBUFFER,X
          JSR SPCEXIT
          JMP SPCONT
g Link to next file. We get the filename from text and put it into the input buffer, just as if the filename were typed in with INPUT. We then jump into the TOPEN routine to open the file, and into the Load routine to load the file. After the load, we check for a load error, then jump to RETEX to continue printing.
LINK      LDY #1
          LDX #0
FNCOPY    LDA (TEX),Y
          CMP #RETCHAR
          BEQ FNEND
          JSR INTOAS
          STA INBUFF,X
          INY
          INX
          CPX #14
          BNE FNCOPY
FNEND     STX INLEN
          LDA #0
          STA INBUFF,X
          LDX #$60
          STX IOCB
          LDA #4
          STA ACCESS
          JSR OPCONT
          BPL LNOERR
          JMP ERRLINK
LNOERR    LDA #0
          STA INDIR
          STA INDIR+1
          JSR ERASE
          JSR LOADLINK
          BPL LCONT
          JMP ERRLINK
LCONT     PLA
          PLA
          LDX #$70
          STA IOCB
          JMP RETEX
Global search and replace. This just links together the search-specify routine, the replace-specify routine, then repeatedly calls Hunt and Replace, until Hunt returns “Not Found.” (FPOS+1 is $FF after a search failure.)
SANDR     JSR RESET
          LDA HUNTLEN
          BEQ NOSR
          JSR ASKREP
SNR       JSR CONTSRCH
          LDA FPOS+1
          CMP #$FF
          BEQ NOSR
          JSR REPL
          JSR REFRESH
          JMP SNR
NOSR      JMP SYSMSG
If OPTION is held down with CTRL-F, we ask for and store the search phrase. If OPTION is not down, we perform the actual search. The line in the INBUFF is compared with characters in text. If at any point the search fails, we continue the comparison with the first character of INBUFF. The search is a failure if we reach the end-of-text. If the entire length of INBUFF matches, the search succeeds, so we change the CURRent cursor position to the found position, save the found position for the sake of the replace routine, then call CHECK to scroll to the found position.
HUNT      LDA #8
          STA 53279
          LDA 53279
          CMP #3
          BNE CONTSRCH
RESET     JSR TOPCLR
          LDA # <SRCHMSG
          LDY # >SRCHMSG
          JSR PRMSG
          JSR INPUT
          STA HUNTLEN
          BNE OKSRCH
          JMP SYSMSG
OKSRCH    LDY #0
TOBUFF    LDA INBUFF,Y
          STA HUNTBUFF,Y
          INY
          CPY INLEN
          BNE TOBUFF
          JMP SYSMSG
CONTSRCH  LDA CURR
          STA TEX
          LDA CURR+1
          STA TEX+1
          LDA #$FF
          STA FPOS+1
          LDY #1
SRCH0     LDX #0
          LDA HUNTLEN
          BEQ NOTFOUND
SRCH1     LDA HUNTBUFF,X
          JSR ASTOIN
          CMP (TEX),Y
          BEQ CY
          CPX #0
          BNE SRCH0
          DEX
CY        INY
          BNE NOVFL
          INC TEX+1
          LDA TEX+1
          CMP LASTLINE+1
          BEQ NOVFL
          BCS NOTFOUND
NOVFL     INX
          CPX HUNTLEN
          BNE SRCH1
          CLC
          TYA
          ADC TEX
          STA TEMP
          LDA TEX+1
          ADC #0
          STA TEMP+1
          LDA LASTLINE
          CMP TEMP
          LDA LASTLINE+1
          SBC TEMP+1
          BCC NOTFOUND
          SEC
          LDA TEMP
          SBC HUNTLEN
          STA CURR
          STA FPOS
          LDA TEMP+1
          SBC #0
          STA CURR+1
          STA FPOS+1
          JSR CHECK
          RTS
NOTFOUND  JSR TOPCLR
          LDA # <NFMSG
          LDY # >NFMSG
          JSR PRMSG
          LDA #1
          STA MSGFLG
          RTS
The change (replace) routine checks to see if OPTION is held down with CTRL-C. If it is, we ask for a replace phrase, and exit. If not, we check to see if the cursor is at the position previously located by the search routine. If it is, we delete the found phrase, then insert the replace phrase. The cursor is moved past the replace phrase for the sake of the next search. This also prevents endless recursion, as in replacing in with winner.
REPSTART  LDA #8
          STA 53279
          LDA 53279
          CMP #3
          BNE REPL
ASKREP    JSR TOPCLR
          LDA # <REPMSG
          LDY # >REPMSG
          JSR PRMSG
          JSR INPUT
          STA REPLEN
          BEQ NOREP
          LDY #0
REPMOV    LDA INBUFF,Y
          STA REPBUFF,Y
          INY
          CPY INLEN
          BNE REPMOV
NOREP     JMP SYSMSG
REPL      SEC
          LDA CURR
          STA DESTL
          SBC FPOS
          STA TEMP
          LDA CURR+1
          STA DESTH
          SBC FPOS+1
          ORA TEMP
          BNE NOREPL
          LDA #$FF
          STA FPOS+1
          CLC
          LDA HUNTLEN
          ADC CURR
          STA FROML
          LDA #0
          ADC CURR+1
          STA FROMH
          SEC
          LDA LASTLINE
          SBC DESTL
          STA LLEN
          LDA LASTLINE+1
          SBC DESTH
          STA HLEN
          JSR UMOVE
          SEC
          LDA LASTLINE
          SBC HUNTLEN
          STA LASTLINE
          LDA LASTLINE+1
          SBC #0
          STA LASTLINE+1
          LDA REPLEN
          BEQ NOREPL
          STA INSLEN
          LDA #0
          STA INSLEN+1
          JSR INSBLOCK
          LDY #0
REPLOOP   LDA REPBUFF,Y
          JSR ASTOIN
          STA (CURR),Y
          INY
          CPY REPLEN
          BNE REPLOOP
          CLC
          LDA CURR
          ADC REPLEN
          STA CURR
          LDA CURR+1
          ADC #0
          STA CURR+1
NOREPL    JMP CHECK
Suddenly, we’re back to a PRINT subroutine. This examines the buffer as it’s being printed, checking for printkeys and Stage 2 commands like centering.
BUFPRT    LDY #0
BUFLP     CPY ENDPOS
          BEQ ENDBUFF
          LDA (INDIR),Y
          BMI SPEC2
          JSR INTOAS
          JSR PCHROUT
In underline mode, after we print the character, we backspace the printhead and print an underline character.
          LDA UNDERLINE
          BEQ NOBRK
          LDA #8
          JSR PCHROUT
          LDA #95
          JSR PCHROUT
NOBRK     INY
          JMP BUFLP
ENDBUFF   RTS
Stage 2 format commands.
SPEC2     STY YSAVE
          AND #127
          STA SAVCHAR
          JSR INTOAS
OTHER     CMP #'c
          BNE NOTCENTER
c Centering looks at the length of the line, then sends out extra spaces (the left margin has already been printed) to move the printhead to the right place.
          SEC
          LDA PAGEWIDTH
          SBC ENDPOS
          LSR A
          SEC
          SBC LMARGIN
          TAY
          LDA #32
CLOOP     JSR PCHROUT
          DEY
          BNE CLOOP
          LDY YSAVE
          JMP NOBRK
NOTCENTER CMP #'e
          BNE NOTEDGE
e Edge right. This subtracts the length of the line from the right margin position and moves the printhead to this position.
EDGE      SEC
          LDA RMARGIN
          SBC ENDPOS
          SEC
          SBC LMARGIN
          TAY
          LDA #32
          JMP CLOOP
NOTEDGE   CMP #'u
          BNE NOTOG
u Toggle underline mode.
          LDA UNDERLINE
          EOR #1
          STA UNDERLINE
NOTOG     CMP #'#
          BNE DOCODES
# Substitute the current page number for the # symbol.
DOPGN     STY YSAVE
          LDX PAGENUM
          LDA PAGENUM+1
          JSR PROUTNUM
          LDY YSAVE
          JMP NOBRK
Do special format codes. This just uses the screen-code value of the character as an index into the CODEBUFFER, then sends out the code. SpeedScript makes no judgment on the code being sent out.
DOCODES   LDX SAVCHAR
          LDA CODEBUFFER,X
          JSR PCHROUT
          JMP NOBRK
Display free memory using OUTNUM.
FREEMEM   JSR TOPCLR
          SEC
          LDA TEXEND
          SBC LASTLINE
          TAX
          LDA TEXEND+1
          SBC LASTLINE+1
          JSR OUTNUM
          LDA #1
          STA MSGFLG
          RTS
          .END
Filename: DATA
Data tables
Messages are stored in ATASCII, with a zero byte for a delimiter.
MSG1      .BYTE "SpeedScript 3.0"
          .BYTE 0
MSG2      .BYTE " by Charles Brannon"
          .BYTE 0
KILLMSG   .BYTE "Buffer Cleared"
          .BYTE 0
BUFERR    .BYTE "Buffer Full"
          .BYTE 0
DELMSG    .BYTE "Delete (S,W,P)"
          .BYTE 0
YMSG      .BYTE ": Are you sure? (Y/N):"
          .BYTE 0
CLRMSG    .BYTE "ERASE ALL TEXT"
          .BYTE 0
ERASMSG   .BYTE "Erase (S,W,P): RETURN to exit"
          .BYTE 0
SAVMSG    .BYTE "Save (Device:Filename)>"
          .BYTE 0
ERRMSG    .BYTE "Error #"
          .BYTE 0
BRMSG     .BYTE "BREAK Key Abort"
          .BYTE 0
OKMSG     .BYTE "No Errors"
          .BYTE 0
LOADMSG   .BYTE "Load (Device:Filename)>"
          .BYTE 0
DIRMSG    .BYTE " Press RETURN"
          .BYTE 0
DIRNAME   .BYTE "D1:*.*"
INSERR    .BYTE "Memory Full"
          .BYTE 0
INSMSG    .BYTE "No text in buffer"
          .BYTE 0
FNMSG     .BYTE "Print (Device:Filename)>"
          .BYTE 0
PRINMSG   .BYTE "Printing..."
          .BYTE 155,155,0
WAITMSG   .BYTE "Insert next sheet, press RETURN"
          .BYTE 0
SRCHMSG   .BYTE "Find:"
          .BYTE 0
NFMSG     .BYTE "Not found"
          .BYTE 0
REPMSG    .BYTE "Change to:"
          .BYTE 0
The {ESC}’s represent the ESCape key. The arrows are the cursor keys, which must be preceded by ESC to be entered into text. There is actually only one space between the e of Rename and the E of ESC.
DIRINS    .BYTE "{ESC}{up}{ESC}{down}{ESC}{left}{ESC}{right} CTRL-Delete Lock Unlock Rename ESC CTRL-Load Drive [1 2 3 4]: ",0
RENMSG    .BYTE "Rename to:",0
FORMSG    .BYTE "Format disk",0
The .OPT NO OBJ and .OPT OBJ pseudo-ops turn on and off object code generation. This insures that no object code is generated for the variable table.
          .OPT NO OBJ
TEXSTART  *= *+2       ;Start-of-text area
TEXEND    *= *+2       ;End-of-text area
TEXBUF    *= *+2       ;Start of buffer
BUFEND    *= *+2       ;End-of-buffer area
LENTABLE  *= *+1       ;Length of first screen line
TOPLIN    *= *+2       ;Home position in text
MSGFLG    *= *+1       ;Message flag
INSMODE   *= *+1       ;Insert mode
ENDPOS    *= *+1       ;Used by delete routines
FINPOS    *= *+1       ;""
LASTLINE  *= *+2       ;End-of-text position
LIMIT     *= *+1       ;Used by INPUT
INLEN     *= *+1       ;""
BOTSCR    *= *+2       ;Bottom of screen in text
LBUFF     *= *+40      ;Line buffer (REFRESH)
INBUFF    *= *+40      ;INPUT buffer
SAVCURR   *= *+2       ;Used by delete routines
BCD       *= *+2       ;Used by ASCHEX
HEX       *= *+2       ;""
TPTR      *= *+2       ;Last character in buffer
BUFLEN    *= *+2       ;Buffer length
GOBLEN    *= *+2       ;Size of deleted text
FROMSAV   *= *+2       ;Used by delete routines
DESTSAV   *= *+2       ;""
HDLEN     *= *+1       ;Header length
FTLEN     *= *+1       ;Footer length
LMARGIN   *= *+1       ;Holds left margin
RMARGIN   *= *+1       ;Right margin
PAGELENGTH *= *+1      ;Page length
TOPMARG   *= *+1       ;Top margin
BOTMARG   *= *+1       ;Bottom margin
SPACING   *= *+1       ;Line spacing
CONTINUOUS *= *+1      ;Page wait mode
PAGENUM   *= *+2       ;Page number
STARTNUM  *= *+2       ;Start printing at #
PAGEWIDTH *= *+1       ;Columns across
NOMARG    *= *+1       ;Margin release flag
POS       *= *+1       ;POSition within line
LINE      *= *+1       ;Line count
YSAVE     *= *+1       ;Preserves Y register
SAVCHAR   *= *+1       ;Preserves accumulator
INSLEN    *= *+1       ;Length of an insertion
DEVNO     *= *+1       ;Device number
NEEDASC   *= *+1       ;True ASCII flag
UNDERLINE *= *+1       ;Underline mode flag
FPOS      *= *+2       ;Found position
PCR       *= *+1       ;Used by PCHROUT
HUNTLEN   *= *+1       ;Length of hunt phrase
HUNTBUFF  *= *+30      ;Holds hunt phrase
REPLEN    *= *+1       ;Length of replace phrase
REPBUFF   *= *+30      ;Holds replace phrase
CODEBUFFER *= *+128    ;Holds definable printkeys
PRBUFF    *= *+256     ;Printer line buffer
HDBUFF    *= *+256     ;Holds header
FIRSTRUN  *= *+1       ;Has program been run before?
FTBUFF    *= *+256     ;Holds footer
SAVCOL    *= *+1       ;Save SCRCOL
LINEFEED  *= *+1       ;Linefeed mode flag
ESCFLAG   *= *+1       ;Was ESC pressed?
CONVFLAG  *= *+1       ;Used by CAST and CINTOAS
SELFLAG   *= *+1       ;The SELECT key flag
IOCB      *= *+1       ;Which IOCB is OPEN
ACCESS    *= *+1       ;Direction of ACCESS (read/write)
FNBUFF    *= *+40      ;Filename buffer
FNLEN     *= *+1       ;Filename length
XSLOT     *= *+1       ;Number of filename slots (DOSPAK)
SLOT      *= *+130     ;Slot positions (DOSPAK)
XPTR      *= *+1       ;Current filename slot (DOSPAK)
WHICHFLAG *= *+1       ;Which key is pressed
DIRCOUNT  *= *+1       ;Directory count
BLINK     *= *+1       ;Cursor blink flag
LINELEN   *= *+1       ;Length of screen lines
RLM       *= *+1       ;REFRESH Left margin value
KEYVAL    *= *+1       ;Which key is pressed
END       =  *         ;High byte of this +$100 is TEXSTART
          .OPT OBJ
Autorun vector
          *=    $02E2
          .WORD BEGIN
          .END
Label Cross Reference. This chart makes it easier to find your place in the object code while looking at the source code. The number to the left of each label is its value or position within the object code. Labels preceded by an = mark are equates. Others are internal labels for object code positions.
43BA ACCESS 3A2E ACROSS 294B ADYCURR 3721 ALPHA 3614 ASCHEX 3C3C ASKREP 262C ASTOIN 3FCD BCD 1F00 BEGIN 446A BLINK 3029 BLIP = 0074 BLUE 2983 BORDER 33AA BOTCLR 3FE1 BOTMARG 3F79 BOTSCR 24D3 BREAK 3E3A BRMSG 3A92 BT 3F6C BUFEND 3DBB BUFERR 3FD3 BUFLEN 3CDE BUFLP 3CDC BUFPRT 33FF CAST 340C CAST1 3419 CASTOIN 3100 CATALOG 27CF CHECK 282D CHECK2 2F7F CHROUT 2FCB CHRYSAVE 3426 CIN 3407 CINTOAS = E456 CIO 284C CK3 2D02 CLEAR 2501 CLEARED 28E2 CLEFT 3D1F CLOOP 3184 CLOSE7 254C CLR2 24F4 CLRLN 2543 CLRLOOP 3DED CLRMSG 4033 CODEBUFFER 3AF0 COMMENT 3FE3 CONTINUOUS 2732 CONTROL 3BB7 CONTSRCH 43B7 CONVELAG 24D7 COPY 3296 COPYD 37EC COPYDEF 3801 COPYDEFS 32A3 COPYNAME 3332 COPYR 3446 COTHER 3998 CR 25AF CRIGHT 3986 CRLF 3991 CRLOOP 2753 CTBL = 0086 CURR 2EE7 CURSIN 3430 CVLOOP 3BDC CY 3282 DDOWN 3654 DECHEX 3AF6 DEFINE 3752 DEFTAB 2A6C DEL1 2A80 DEL1A 2A89 DEL2 2A7D DELABORT 2AA0 DELC 2B32 DELCHAR 2B5C DELETE 32E5 DELFILE 2B4D DELIN 35FF DELITE 3DC7 DELMSG 288A DELSENT 2B7D DELWORD = 0083 DESTH = 0082 DESTL 3FD9 DESTSAV 3FEF DEVNO 3622 DIGIT 4469 DIRCOUNT 3F00 DIRINS 3156 DIRLOOP 3E6C DIRMSG 3E7A DIRNAME 25E9 DISKBOOT 3247 DLEFT 2E0A DLI 2DEE DLIST 2DC8 DLOOP 2474 DMOV1 244D DMOVE 2476 DMOVLOOP 3170 DNOT8 315B DNOTCR 3873 DOBUF2 3869 DOBUFF 3D62 DOCODES 3B04 DODEFINE 26F4 DOINS 2D25 DOIT 3678 DONENUM 3D50 DOPGN 38EB DORPT 31BB DOS 3229 DOSADR 33B6 DOSERR 33FF DOSMSG 3219 DOSTABLE 3254 DRIGHT 336F DRIVE 3271 DUP 2BD9 EATSPACE 3D2F EDGE 2F99 ENAME = 446E END 3D00 ENDBUFF 3194 ENDIR 319E ENDLP 3F73 ENDPOS 2967 ENDTEX 2814 EQA 2E97 ERA1 2EA6 ERA2 2E33 ERAS 2E42 ERAS1 2E4C ERASAGAIN 251F ERASE 2E7B ERASENT 3DFC ERASMSG 2E6E ERASWORD 34A7 ERR1 379B ERRLINK 3E32 ERRMSG 34AE ERROR 34C7 ERXIT 27BD ESC 3399 ESCDOS 43B6 ESCFLAG 2F2E ESCKEY 2C75 FILLSP 3201 FINDIT 3841 FINDSPACE 35E8 FINE 3F74 FINPOS 4283 FLRSTRUN 29F4 FIRSTWORD 2B3B FIXTP 2687 FLIPIT 43BB FNBUFF 3B1D FNCOPY 3B2F FNEND 43E3 FNLEN 3E9E FNMSG 3355 FORMAT 3F5A FORMSG 2740 FOUND 320C FOUNDIT 3858 FOUNDSPACE 3FF2 FPOS 3D6E FREEMEM = 0081 FROMH 0080 FROML 3FD7 FROMSAV 39BF FSP 3850 FSPACE 3AD7 FT 42B4 FTBUFF 3AE0 FTCOPY 3FDC FTLEN 31A9 GET7 256F GETAKEY 2FD6 GETCHAR 2FCC GETIN 31D6 GETNAME 2D4F GOADY 3FD5 GOBLEN 3565 GOERROR 2C06 GOINC 2FC1 GOPCHR 2AD4 GOSAV 32EA GOXIO 3001 GXIT 3AB5 HD 4183 HDBUFF 3ABE HDCOPY 3FDB HDLEN 3FCF HEX 2DAD HIGHLIGHT = 0085 HLEN 2BA1 HOME 2BC3 HOMEPAUSE 3B85 HUNT 3FF6 HUNTBUFF 3FF5 HUNTLEN = 034A ICAUX1 = 034B ICAUX2 = 0344 ICBADR = 0348 ICBLEN = 0342 ICCOM = 0343 ICSTAT 3FA3 INBUFF 250C INCNOT 3744 INCONT = 008E INDIR 2F4D INEXIT 2589 INIT 25EA INIT2 2726 INKURR 3F78 INLEN 2CE1 INOUT 2ED5 INP1 2ECE INPUT 2868 INRANGE 2C92 INSBLOCK 367D INSBUFFER 2C7C INSCHAR 3E80 INSERR 3FEE INSLEN 3F72 INSMODE 3E8C INSMSG 2CE2 INSTGL 374D INT1 3738 INTOAS 33E5 INVLP 33E3 INVNAME 03B9 IOCB 34E0 IOCLOSE 2575 JDOS 357B JFINE 32F2 JNAME 3040 KEYBOARD 2694 KEYPRESS 446D KEYVAL 2A50 KILLBUFF 3DAC KILLMSG 3F75 LASTLINE 295A LAST WORD 3F7B LBUFF 3B5A LCONT 28B8 LEFT 3F6E LENTABLE 298B LETTERS 3A68 LFSET 3F77 LIMIT 3FEB LINE 43B5 LINEFEED 446B LINELEN 3B19 LINK = 0084 LLEN 3A74 LM 3975 LMARG 3FDD LMARGIN 3985 LMEXIT 397F LMLOOP 3B49 LNOERR 3554 LOAD2 3377 LOADIT 357E LOADLINK 3E54 LOADMSG 32F8 LOCK 2C4C LOTTASPACE 2645 LOWR 2648 MAIN 2651 MAIN2 2428 MOV1 242A MOV2 242F MOVLOOP 3A25 MRELEASE 3D88 MSG1 3D98 MSG2 3F71 MSGFLG 31E5 NAMELP 3294 NAMER 3FF0 NEEDASC 38FC NEXPAGE 3EEB NFMSG 39ED NOAD 2F1B NOBACK 28AC NOBIGGER 2583 NOBLINK 3CFC NOBRK 28E8 NODEC 3571 NOER 2F04 NOESC 2A37 NOFIXCURR 35E2 NOGARBAGE 3963 NOHEADER 3675 NOHEXINC 272C NOINC2 28B5 NOINCR 2C63 NOINCY 3929 NOIPN 39A5 NOLF 3FE9 NOMARG 26B8 NOMSG 334F NONAME 3653 NONUM 2E91 NOPAR 31FF NOPROB 3C5C NOREP 3CD9 NOREPL 3902 NOSK 3B82 NOSR 32B2 NOSTOR 3735 NOTALPHA 26AC NOTBKS 300F NOTCAPS 3D2B NOTCENTER 26C2 NOTCR 2642 NOTCTRL 32BF NOTDOT 3D40 NOTEDGE 3C20 NOTFOUND 26F7 NOTINST 3024 NOTLOCKED 2455 NOTNULL 3D4C NOTOG 389E NOTPAGE 2BA0 NOTPAR 344F NOTRC 382F NOTRET 3440 NOTRTN 26A6 NOTSEL 2B93 NOTSENT 3004 NOTSET 382B NOTSP 2B86 NOTWORD 2F13 NOTZERO 3BEA NOVFL 2E77 NOWORD 326E NRANGE 3AA6 NX 24C7 NXCUR 2941 OIDS 27FF OK1 282C OK2 36A5 OKBUFF 2D0F OKCLEAR 2CA9 OKINS 3568 OKLOD 36DF OKMOV 3E4A OKMSG 3BA6 OKSRCH 27C6 ONOFF 2FCA ONUMEXIT 2FB1 ONUMLOOP 3508 OPABORT 3510 OPCONT 2F59 OPENEDITOR 3D0C OTHER 244C OUT 2BC9 OUTHOME 2FA0 OUTNUM 287A OUTRANGE 2C0B OUTSPACE 26E2 OVERCTRL 387B OVERMARG 3452 OVEROTHER 2FC4 OVERPCHR 385B OVERSTOR 2FA2 OVERZAP 38EE PAGE 3FDF PAGELENGTH 3FE4 PAGENUM 3FE8 PAGEWIDTH 2D64 PARCONT 2D31 PARIGHT 2D52 PARLEFT 2D5E PARLOOP 2D33 PARLP 3ACF PASTRET 37BB PBORT 3762 PCHROUT 3FF4 PCR 2514 PDONE 38D7 PEXIT 3A58 PL 24B1 PLINE 3814 PLOOP 3824 PLOOP1 29A7 PMANY 3A48 PN 3FEA POS 24AF PPAGE 40B3 PRBUFF 375E ERCODES 256E PREXIT 37B1 PRIN 3EB7 PRINMSG 37BE PRINT 2564 PRLOOP 2559 PRMSG 37D5 PROK 35F0 PROKMSG 2F9B PROUTNUM 29BD PSLOOP 29B9 PSRCH 29DE PUNCT 2A26 PUNCT2 3A62 PW 38C1 PXIT = 0032 RED 312D REDIR 2826 REF 248B REFRESH 3308 RENAME 3F4F RENMSG 4015 REPBUFF 29EF REPEAT 3C5F REPL 4014 REPLEN 3CBD REPLOOP 3C50 REPMOV 3EF5 REPMSG 3C30 REPSTART 3B91 RESET 3261 RESLOT = 005E RETCHAR 380A RETEX 2D75 RETF2 2D4A RETFOUND 2885 RIGHT 446C RLM 2925 RLOOP 3A7E RM 3FDE RMARGIN 2933 ROUT 297A SAFE 3B64 SANDR 3FED SAVCHAR 43B4 SAVCOL 3FCB SAVCURR 3E1A SAVMSG 24D2 SBRK = 0088 SCR 298A SCRCOL 43B8 SELFLAG = 02BE SHFLOK 37A4 SHIFTFREEZE 2481 SKIPDMOV 1F34 SKIPERAS 3918 SKIPFT 2448 SKIPMOV 37A9 SKIPOUT 2F3E SKIPSEL 29E2 SKIPSPC 3974 SKIPTOP 299B SLEFT 24C3 SLOOP 43E5 SLOT 3036 SLOW 3031 SNDLOOP 3B6F SNR 3A9C SP = 0000 SPACE 3FE2 SPACING 3A38 SPACE 39E6 SPCEXIT 39D5 SPCONT 2BE7 SPCSRCH 3D01 SPEC2 39A6 SPECIAL 39F1 SPTAB 3A03 SPVECT 2735 SRCH 3BC6 SRCHO 3BCD SRCH1 3EE5 SRCHMSG 39B1 SRCHSP 2A23 SREXIT 2A01 SRIGHT 2A03 SRLP 3FE6 STARTNUM 34D3 STOPPED 28F9 STRIP 2903 STRLOOP 37B1 SWITCH 260A SYSMSG 2C54 TAB 2C66 TAB2 = 008C TEMP = 008A TEX 3F6A TEXBUF 299A TEXCOLR 3F68 TEXEND 35AB TEXOK 3F66 TEXSTART 2DA2 TEXTOCURR 3178 THROWS 3539 TLOAD 3BA8 TOBUFF 28DF TOOSMALL 394D TOP 261A TOPCLR 34EB TOPEN 2BCC TOPHOME 3F6F TOPLIN 261E TOPLOOP 396E TOPLP 3FE0 TOPMARG 3A88 TP 3FD1 TPTR 345D TSAVE 2410 UMOVE = 0090 UNDERCURS 3FF1 UNDERLINE 3300 UNLOCK 2E84 UNSENT 2777 VECT 2667 WAIT 3EC5 WAITMSG 2BBC WAITST 4468 WHICHFLAG = 0091 WINDCOLR 28ED WLEFT 2906 WLOOP 2923 WRIGHT 2914 WROUT 2957 WRTN 374F XINT 32C8 XIO 4467 XPTR 43E4 XSLOT 3DD6 YMSG 2CEB YORN 2CF2 YORNKEY 3FEC YSAVE 3890 ZBUFF
ASCII files 13
ASCII value, use of in defining a
  printkey 21-22
Atari DOS 2.0, use of 4, 15
Atari DOS 3.0, use of 4, 15
“The Automatic Proofreader” 34-36
  preparing the program 34
  program listing 35-36
  using the program 35
command line 5
control key commands 7-15
  CTRL-A 14
  CTRL-B 14
  CTRL-C 11-12
  CTRL-CLEAR 7
  CTRL-D 9, 10
  CTRL-DELETE/BACK S 9
  CTRL-E 9, 10
  CTRL-F 11
  CTRL-G 11, 12
  CTRL-I 8
  CTRL-INSERT 8
  CTRL-K 10
  CTRL-L 11-12
  CTRL-M 13
  CTRL-O 14
  CTRL-P 16
  CTRL-R 10
  CTRL-S 12
  CTRL-T 14
  CTRL-U 6
  CTRL-X 14
  CTRL-Z 8, 13
  CTRL-1 16
  CTRL-+ 7
  CTRL-* 7
  CTRL-- 7
  CTRL-= 7
  ESC key, use of with CTRL 8
  explanation of how to enter 7
  OPTION button, use of with CTRL 7, 11, 14
cursor movement 7-8
  cursor-down key 7
  cursor-left key 7
  cursor-right key 7
  cursor-up key 7
delete mode 9-10
disk commands 13-14
entering of text 5-9
erase mode 9
erasing of text 9-10
format commands 15-23
  SELECT key 16-17, 21
  Stage 1 commands 16-20
  Stage 2 commands 20-21
  summary of 19
insert mode 8-9
keyboard commands 7-12. See also
  control key commands; keyboard
  map, illustration of
  BREAK key 16
  CAPS/LOWR key 15
  DELETE/BACK S key 9
  OPTION-CTRL-C 11
  OPTION-CTRL-F 11
  OPTION-CTRL-G 11
  OPTION-CTRL-+ 14
  OPTION-CTRL-* 14
  SELECT key 16-17, 21
  SHIFT-DELETE/BACK S 9
  SHIFT-INSERT 8
  SHIFT-+ 7
  SHIFT-* 7
  SHIFT-- 7
  SHIFT-= 7
  START button 8
  SYSTEM RESET button 15
  TAB key 8
keyboard map, illustration of 18
loading of a document 12
loading of program
  binary disk file 4
  boot tape 4-5
“The Machine Language Editor: MLX” 27-33
  commands 4, 28-29
  ending address 3, 27, 37
  explanation of use 27
  program listing 29-33
  run/init address 3, 27, 37
  starting address 3, 27, 37
  typing in multiple sittings 4-5
MAC/65 Assembler 69
merging, of files 13
Optimized Systems Software, Inc. 5, 69
OPTION button, use of 11
OS/A+ DOS, use of 4, 15
overscanning 14
parsing 6
printing of documents
  default settings 16
  explanation of use 15-23
  to an RS-232 printer 16
printkey, defining of 21-23
program listing 37-65
return-mark 7
saving of the program
  as a binary file 3, 27
  as a boot tape 3, 27
screen formatting 6-7
scrolling 6-7
search and replace 11-12
source code 69-111
  explanation of 69-70
  listing of 71-111
start a new document 11
storing of a document 12
text buffer 10
typing it in 3-5
  in multiple sittings 4-5
using the program 3-23
width of the screen, how to change it 14
word wrap 6
Thousands of people have already made SpeedScript COMPUTE! Publications’ most popular program ever. Offering nearly every feature and convenience you expect to find in a quality word processor, SpeedScript is the perfect writing tool. With SpeedScript, writing, editing, formatting, and printing any document—from the shortest letter to the longest novel—become easier. Anything can be changed, modified, or rewritten with just a few keystrokes on your Atari 400/800, 600XL/800XL, 1200XL, or new XE and at least 24K of memory. The mechanics of writing become less intrusive—so you can concentrate on the writing, not the process itself.
SpeedScript 3.0 is our most powerful version of this easy-to-use word processor. Commands have been added, other features enhanced, to give you the best possible writing instrument.
Here are just a few of the features of this book:
- Complete program listing for SpeedScript 3.0
- Detailed documentation that shows you how to use all of SpeedScript’s commands and capabilities
- “The Machine Language Editor: MLX,” an entry program which insures that you’ll type in SpeedScript right the first time
- SpeedScript 3.0’s source code (by studying it, you’ll see how SpeedScript was written)
SpeedScript is a most impressive word processor. It’s a writer’s tool that you can use from the moment you run it. With SpeedScript The Word Processor for the Atari, you have a complete package—the word processor and the complete documentation.
ISBN 0-87455-003-3