In This Issue...
Another New Book: Bag of Tricks
The authors of Beneath Apple DOS (Don Worth and Pieter Lechner) have done it again! This time you get a diskette with four powerful disk utilities on it, and a book expaining their use. The retail price is $39.95, but I will have them for only $36.
The utilities are TRAX, INIT, ZAP, and FIXCAT. TRAX examines any track on a disk, reading it in as pure nibbles and displaying in a partially analyzed form. INIT reformats any track or tracks, optionally retaining existing data in whatever readable sectors are in the track. You can reorder the sectors, change the volume number, and more. ZAP is a general purpose disk utility: sectors may be read, written, displayed, modified with a powerful assortment of over 50 commands. It works with 13- and 16-sector DOS, as well as Pascal and CP/M diskettes. You can even "program" in ZAP, with labels, loops, and macro-commands. FIXCAT can automatically repair or reconstruct a catalog track by analyzing the rest of the disk.
Beyond the utilities themselves, there is about 40 pages of advanced tutorial material which starts where "Beneath Apple DOS" ends.
Unless you are fully satisfied with your present collection of disk utilities, you ought to get this set.
[ Greg is a subscriber from Albuquerque, New Mexico. ]
One of the nice features of the new S-C Macro Assembler is the title directive (.TI). This directive causes a title and page number to be printed at the top of each page of an assembly listing. The title directive gave me the idea for the Automatic Save command program which follows.
I felt the need for an Auto Save command because of my own carelessness. After extensive editing of a rather lengthy program, I decided it was a good time to save the program before I proceeded. The file names I use are usually descriptive and forgettable, so to save a file, I list the Catalog, then use the cursor controls to copy the file name. After the file name appeared on the screen, I zipped the cursor next to the name I wanted to save the file under and, succumbing to temporary insanity, typed an "L". The word "LOAD" flashed on the screen and my mouth dropped open in disbelief. The only sounds that could be heard were the whirr of the disk drive and the screams of my new code byting the dust cover!
I decided to try to simplify the task of saving a program, giving myself less chance of making an error. From this came the Auto Save command. With this command, typing SAVE does not save your program on cassette. Instead, the SAVE command searches your source program for a title. If a title is found and it is a valid DOS name, the source program is automatically saved, using the title as the file name. In addition, if you end your title with a version number in the form N.N, Auto Save automatically increments the version number in the source program and saves the program using the new version number. The version number option does not erase your old file, which means your old file is a back-up. Be careful, though. A few saves and your disk is full of back-up files. You'll need to go back and delete a file or two every once in a while.
The version number goes up to a maximum of 9.9, after which it starts back at 0.0. If the version number option is not desired, don't put a number in the form N.N at the end of your title.
Leading and trailing blanks are ignored by Auto Save. If there is more than one consecutive blank in a title, the blanks are compressed to one. Thus, the title ".TI 56,TI TLE" generates a SAVE to the file named "TI TLE". Also, any commas in your title are changed to dashes so as not to confuse DOS.
To use the Auto Save command, the vector address of the SAVE command must be changed. The address must be one less than the actual start of the Auto Save command. For example, if Auto Save is assembled at $800, the address would be changed in the table inside the S-C Macro Assembler to $07FF.
For the version of the S-C Macro Assembler which loads at $1000, change the contents of address $1679 to $07 and $1678 to $FF. Shown as a monitor command, this would be:
:$1678:FF 07
For the Language Card version of the S-C Macro Assembler, change the content of address $D679 to $07 and $D678 to $FF. You have to write-enable the card first:
:$C083 C083 D678:FF 07
I like to keep Auto Save behind the Language Card version of the Macro Assembler. I put the program at $F320 and the changes are:
:$C083 C083 D678:1F F3
One thing you'll have to look out for. If you type an illegal DOS SAVE command such as "SAVE 1 4 THE ROAD", DOS ignores this command and the Auto Save goes into effect; the "1 4 THE ROAD" is ignored. Also note that the save is performed on the drive that is active. Since commas are changed to dashes, there is currently no way to specify which drive you want the save to be performed on. Perhaps you would like to try to implement this enhancement yourself.
After you've installed the Auto Save program, type in this program:
1000 * A TEST OF AUTO SAVE 1010 .TI 54, TITLE TEST VER. 0.9
Then type SAVE, and CATALOG. See how the file was saved? List the file and notice the change in line 1010. Voila!
For those of you who haven't updated to the Macro Assembler yet, Auto Save can be implemented with S-C Version 4.0 by using the .US command for the title. The changes which are necessary are outlined below.
1. The following lines must be deleted: 1490-1540, 2090-2150, 2460-2470, 2560-2930. 2. The following lines must be added: 1210 .US S-C VER. 4.0 AUTO SAVE 1.0 1600 BNE .2 ...ALWAYS 1920 * CHECK THE OP CODE FOR .US 2170 BCS TITLE 2480 .1 CMP #$80 3480 OPS .AS /.US/ 3510 NO.TTL .AS /*** NO TITLE ERRO/ 3515 .AS -/R/ 3520 .AS /*** ILLEGAL TITLE FIRST CHARACTE/ 3525 .AS -/R/ 3. Change the SAVE vector address. For an origin of $800, that would be :$1271:FF 07 4. To use the command, put the title you want to use for the file name like so: .US MY TITLE VER. 1.0
1000 *-------------------------------- 1010 * AUTOMATIC SAVE PROGRAM 1020 * THIS PROGRAM CHECK'S FOR A TITLE 1030 * AND IF ONE IS FOUND, THE CURRENT PROGRAM 1040 * IS SAVED UNDER THE TITLE 1050 * ALSO, IF THE VERSION NUMBER IS APPENDED 1060 * IT IS UPDATED BEFORE EACH SAVE 1070 *-------------------------------- 1080 * SYSTEM EQUATES 1090 *-------------------------------- 1100 MON.COUT .EQ $FDED 1110 MON.CROUT .EQ $FD8E 1120 MON.BELL1 .EQ $FBDD 1130 IN.BUF .EQ $200 1140 SRC.END .EQ $4C,4D 1150 SRC.START .EQ $CA,CB 1160 NEXT .EQ $1D 1170 SEARCH .EQ $1E,1F 1180 *-------------------------------- 1190 .OR $800 1200 .TF AUTO.SAVE.OBJECT A$800 1210 *-------------------------------- 1220 * INITIALIZE SEARCH REGISTERS AND 1230 * DETERMINE IF AT END OF SOURCE PROGRAM 1240 *-------------------------------- 1250 AUTO.SAVE 1260 LDA SRC.START GET START OF SOURCE PROGRAM ADDRESS 1270 STA SEARCH AND MOVE TO THE SEARCH ADDRESS REGISTER 1280 LDA SRC.START+1 1290 STA SEARCH+1 1300 CLD 1310 ADDRESS.END.CMP 1320 LDA SEARCH 1330 CMP SRC.END SEE IF AT END OF SOURCE PROGRAM 1340 BNE .1 1350 LDA SEARCH+1 1360 CMP SRC.END+1 1370 BEQ ERROR1 DIDN'T FIND TITLE 1380 *-------------------------------- 1390 * SEARCH LINE FOR OP CODE 1400 *-------------------------------- 1410 .1 LDY #0 Y OFFSET FOR LINE EXAMINATION 1420 LDA (SEARCH),Y NEXT LINE OFFSET 1430 STA NEXT 1440 LDY #3 POINT TO CHARACTER AFTER LINE NUMBER 1450 LDA (SEARCH),Y 1460 CMP #'* COMMENT LINE? 1470 BEQ NEW.LINE YEP 1480 .5 CMP #$C0 COMPRESSED CODE? 1490 BNE .2 NOPE 1500 .4 INY MOVE OFFSET PAST COMPRESSED INFO 1510 INY 1520 CLV 1530 BVC .3 ...ALWAYS 1540 .2 CMP #$80 SPACE(S)? 1550 BCS OPCHK YES, CHECK THE OP-CODE 1560 .3 INY 1570 LDA (SEARCH),Y 1580 BEQ NEW.LINE END OF LINE (EOL) IS 0 1590 BNE .5 ...ALWAYS 1600 *-------------------------------- 1610 * CALCULATE ADDRESS OF NEXT LINE 1620 *-------------------------------- 1630 NEW.LINE 1640 CLC 1650 LDA SEARCH MOVE SEARCH ADDRESS TO NEXT LINE 1660 ADC NEXT 1670 STA SEARCH 1680 BCC ADDRESS.END.CMP 1690 INC SEARCH+1 1700 BNE ADDRESS.END.CMP ...ALWAYS 1710 *-------------------------------- 1720 * ERROR ROUTINES 1730 *-------------------------------- 1740 ERROR1 1750 LDY #0 POINT TO NO TITLE ERROR 1760 PRTERR LDA NO.TTL,Y 1770 BMI ERREND 1780 ORA #$80 1790 JSR MON.COUT 1800 INY 1810 BNE PRTERR 1820 ERREND JSR MON.COUT 1830 JSR MON.BELL1 1840 JSR MON.BELL1 1850 JSR MON.CROUT 1860 RTS 1870 ERROR2 1880 LDY #18 POINT TO ILLEGAL CHAR. ERROR 1890 BNE PRTERR ...ALWAYS 1900 *-------------------------------- 1910 * CHECK THE OP CODE FOR .TI 1920 *-------------------------------- 1930 OPCHK LDX #0 1940 .1 INY 1950 LDA (SEARCH),Y 1960 BEQ NEW.LINE EOL 1970 CMP OPS,X COMPARE OP CODE 1980 BNE NEW.LINE THAT'S NOT IT 1990 INX 2000 CPX #3 IF ALL 3 COMPARE, FOUND OP CODE 2010 BNE .1 2020 *-------------------------------- 2030 * NOW LOOK FOR TITLE 2040 *-------------------------------- 2050 TITLE INY 2060 LDA (SEARCH),Y 2070 BEQ ERROR1 NO TITLE? 2080 CMP #', LOOKING FOR COMMA (TITLE FOLLOWS) 2090 BNE TITLE 2100 .1 INY 2110 LDA (SEARCH),Y 2120 BEQ ERROR1 NO TITLE? 2130 CMP #$C0 COMPRESSED? 2140 BEQ COMP.CODE1 2150 CMP #$80 SPACE? 2160 BCS .1 YEP--SKIP 2170 CMP #'A MAKE SURE 1ST CHAR. IS LETTER 2180 BCC ERROR2 NOT LETTER 2190 CMP #$5B 1 MORE THAN "Z" 2200 BCS ERROR2 2210 *-------------------------------- 2220 * TITLE FOUND 2230 * OUTPUT CTRL-D, "SAVE" AND TITLE 2240 *-------------------------------- 2250 PHA 2260 LDX #0 2270 .2 LDA SAVE,X 2280 JSR MON.COUT 2290 INX 2300 CPX #5 2310 BNE .2 2320 PLA 2330 NEXT.CHAR1 2340 ORA #$80 2350 JSR MON.COUT 2360 INX X KEEPS TRACK OF INPUT BUFFER OFFSET 2370 NEXT.CHAR2 2380 INY 2390 LDA (SEARCH),Y 2400 BEQ GOT.TTL2 EOL--GOT THE TITLE 2410 CMP #', NO COMMAS ALLOWED 2420 BNE .1 2430 LDA #'- REPLACE COMMA WITH DASH 2440 BNE NEXT.CHAR1 ...ALWAYS 2450 .1 CMP #$C0 2460 BEQ COMP.CODE2 2470 CMP #$80 2480 BCC NEXT.CHAR1 2490 INY CHECK FOR CHARACTER AFTER SPACE 2500 LDA (SEARCH),Y 2510 BEQ GOT.TTL1 DROP TRAILING SPACES 2520 DEY MOVE POINTER BACK TO CORRECT POSITION 2530 LDA #$20 SPACE--SPACES IN TITLE COMPRESSED TO 1 2540 BNE NEXT.CHAR1 ...ALWAYS 2550 *-------------------------------- 2560 * COMPRESSED CHARACTER ROUTINES 2570 *-------------------------------- 2580 COMP.CODE1 2590 INY 2600 LDA (SEARCH),Y THIS IS NUMBER OF CHARACTERS COMPRESSED 2610 STA NEXT 2620 INY 2630 LDA (SEARCH),Y ACTUAL CHARACTER 2640 CMP #'A MAKE SURE IT'S A LETTER 2650 BCC ERROR2 2660 CMP #$5B 2670 BCS ERROR2 2680 PHA 2690 LDX #0 2700 .1 LDA SAVE,X 2710 JSR MON.COUT 2720 INX 2730 CPX #5 2740 BNE .1 2750 PLA 2760 BNE STORE ...ALWAYS 2770 COMP.CODE2 2780 INY 2790 LDA (SEARCH),Y 2800 STA NEXT 2810 INY 2820 LDA (SEARCH),Y 2830 CMP #', 2840 BNE STORE 2850 LDA #'- 2860 STORE 2870 ORA #$80 2880 JSR MON.COUT 2890 INX 2900 DEC NEXT 2910 BNE STORE 2920 BEQ NEXT.CHAR2 2930 *-------------------------------- 2940 * SEARCH FOR VERSION NUMBER AND CHANGE IF FOUND 2950 *-------------------------------- 2960 GOT.TTL1 2970 DEY 2980 GOT.TTL2 2990 DEY MOVE Y POINTER TO THIRD NON-BLANK 3000 DEY CHARACTER FROM THE END OF LINE 3010 DEY 3020 DEX 3030 LDA (SEARCH),Y THIRD CHAR. FROM END 3040 CMP #'0 3050 BCC DOS.OP 3060 CMP #': ASCII ":" IS 1 MORE THAN ASCII 9 3070 BCS DOS.OP 3080 INY 3090 LDA (SEARCH),Y 2ND CHAR. FROM END 3100 CMP #'. SHOULD BE PERIOD 3110 BNE DOS.OP 3120 INY 3130 LDA (SEARCH),Y LAST CHARACTER 3140 CMP #'0 3150 BCC DOS.OP 3160 CMP #': 3170 BCS DOS.OP 3180 ADC #1 3190 CMP #': 3200 BNE STORIT 3210 LDA #'0 3220 STA (SEARCH),Y CHANGE DIGIT IN SOURCE CODE 3230 ORA #$80 3240 STA IN.BUF,X CHANGE DIGIT IN DOS COMMAND 3250 DEX 3260 DEX 3270 DEY 3280 DEY 3290 LDA (SEARCH),Y 3300 CLC 3310 ADC #1 3320 CMP #': 3330 BNE STORIT 3340 LDA #'0 3350 STORIT STA (SEARCH),Y 3360 ORA #$80 3370 STA IN.BUF,X 3380 *-------------------------------- 3390 * CR OUTPUT CAUSES DOS TO PERFORM SAVE 3400 * AFTERWARDS, RETURN TO ASSEMBLER 3410 *-------------------------------- 3420 DOS.OP JSR MON.CROUT 3430 END RTS 3440 *-------------------------------- 3450 * MESSAGES 3460 *-------------------------------- 3470 OPS .AS /.TI/ 3480 SAVE .HS 84 CTRL-D 3490 .AS -/SAVE/ 3500 NO.TTL .AT /*** NO TITLE ERROR/ 3510 .AT /*** ILLEGAL TITLE FIRST CHARACTER/ 3520 ZZZEND .EQ * 3530 ZZZLEN .EQ ZZZEND-AUTO.SAVE |
One of the joys of putting the Apple Assembly Line out each month has been the knowledge that a lot of readers are putting making good use out of what I print. A case in point: William Linn, of Lithonia, Georgia, was inspired by a combination of several articles to produce a new software product we all can use!
He calls it AED, which stands for Applesoft EDitor. AED combines in one easy-to-use package:
Line Editing as in PLE and the S-C Macro Assembler Automatic Line Numbering Global Search and Replace (with wildcard matching) Controlled LISTing (Page- or Line-at-a-time, and Slow Scroll) Display of Variables after execution Quick entry of DOS commands from a mini-menu And a lot more.
I said it is easy to use. Why? Here are a few reasons:
The screen is split, with the line being entered at the bottom 6 lines and two possiblities for the top 18 lines. The top 18 lines are used for listing or for display of the most frequently used commands and edit controls.
The commands and edit controls are single letters or control-letters, with mnemonic value.
An inverse letter appears before the prompt character indicating which of six special modes you are in, so you don't get lost.
Clicks and tones provide pleasant feedback at appropriate times.
One very unusual feature, which I have grown to love in a very short time, is a new kind of cursor. Rather than the flashing cursor of the standard Apple input routines, AED alternates the underline character with the character already on the screen. This alternation is done at the same rate as the Apple's flashing mode, but doesn't tire the eyes.
AED loads into memory from $8500 through $95FF, and uses a 256-byte buffer from $8400 to $84FF. HIMEM is set to $83FF.
AED is normally in charge of all input, until the Control-Q command (QUIT) is typed. If you type a letter A, C, E, F, L, M, R, S, or V the rest of the AED command starting with that letter will be displayed. If the command requires no additional information, it is immediately executed. Otherwise, it waits for you to finish the command and type a carriage return. The period is also a command: call it "dot", and think of "DOS", because its purpose is to call up the DOS Command Mini-Menu. If you type a line beginning with a non-command character, it is passed on to Applesoft. Thus you can enter numbered lines, or type immediate mode commands such as NEW or PRINT X(3) or PR#1.If you do leave AED control, typing "&" will enter AED again. If you have the Autostart Monitor, hitting RESET will re-enter AED.
It is important to realize that you are always in an editing mode. Even commands can be edited using the edit control keys.
Here is a list of the commands:
Letter Commands
A AUTO line #,increment C CHANGE /string1/string2/A E EDIT line # F FILE = filename to use in DOS commands L LIST [ line #,line # ] M MANUAL line numbering R Repeat last LIST command S SEARCH /string/ V Variable display . DOS Mini-Menu
Control Commands
^A Assistance ^C Clear Scroll Area ^Q Quit ^X Clear Edit Area ESC Edit Next Line
Editing Commands
^B Cursor to beginning ^D Delete a character ^E Cursor to end of line ^Fx Cursor to next "x" ^I Begin Insert mode ^M (RETURN) Submit line ^N Cursor to end of line ^R Recall last line edited ^Tx Delete through next "x" ^T^T Delete to end of line ^V Next character verbatim ^W Enter word cursor mode
AED does not have user-defined keyboard macros. The keyboard macros in PLE are a big selling point; however, the ones you actually end up using in PLE are built-in to AED as actual commands or as part of the DOS Mini-Menu. Of course, PLE words with both Integer BASIC and Applesoft; AED is only for Applesoft.
If you use Applesoft, are not already firmly addicted to PLE, and if you do not use Integer BASIC, then you should consider picking up a copy of AED. It is only $40 (same price as PLE), and packs a lot of usefulness for the dollars.
How many times have you read or heard about a way to modify your Apple so that the shift-key would function like a normal typewriter? It is a relatively safe and easy thing to do, but the directions can really be frightening.
Words like "solder", "wire", "take the bottom off your Apple", and so on.
If you have an Apple with the piggy-back board hanging down under your keyboard (Revision 7 or newer), take heart! There is a little device you can pick up for only $15 postpaid, called Ashby's Shift-Key Modifier, which hooks up the modification without any tools or trouble. And it only takes a minute or so! (In fact, only a few seconds if you have done it a few times like I have.)
The Modifier consists of a piece of wire fitted with a plug for the game connector on one end, and with a clip on the other end. The plug is devised so that you still have an empty game socket on top, for attaching paddles or whatever.
To install the Modifier, all you have to do is insert the plug into the game socket, and clip the other end onto the connector from the keyboard to the piggy-back board at the second wire from the right (the RESET key side).
I have installed them on all my Apples, except for my oldest one. (That one is serial #219, bought in August of 1977, and is so old it doesn't even have ventilation slots on the case! Yes, I installed the open-case-and-solder-a-wire modification in the old one.)
Now I can use the shift-key the way I was taught in typing class when I am using Data Capture 4.0, SuperText II, Apple Pie 2.0, the S-C Macro Assembler, or the Word Handler. And more and more programs are being created to take advantage of a REAL shift key on an Apple.
The normal retail price of the Ashby Shift-Key Modifier is $18. I have bought a bunch of them, and you can have them for only $15 each. They come complete with directions for installation.
[ Bob is a subscriber in Westport, Connecticut. ]
The article by Peter Bartlett on improving the Epson Controller Card (which appeared in the February 1982 issue of AAL) has prompted me to write to bring to the attention of fellow AAL readers that the TYMAC controller card, which is a lower-cost alternative to the official Epson card, has a potentially serious problem.
To achieve slot independence, controller card ROM programs JSR to an RTS instruction in the Monitor. Then they extract the slot from the return address the JSR put on the stack. The Apple II Reference Manual details the process on page 81-82.
Most controller cards use the Apple technique verbatim, JSR'ing to $FF58, which is an RTS instruction in the Monitor ROM. However, the TYMAC card JSR's to $FDFF. That location also contains an RTS, so there is no problem using the TYMAC card as long as the Monitor ROM is enabled.
The problem occurs when the TYMAC card is used with Pascal. While Apple Computer has specifically guaranteed an RTS instruction at $FF58 in the Pascal Basic Input/Output System (BIOS), no RTS exists at $FDFF. Therefore TYMAC loses control and causes a Pascal crash as soon as it is called.
If any of you have TYMAC cards, and plan to make the Peter Bartlett modification (or perhaps even if you don't plan to), you should also change the JSR instruction at $0A relative to the beginning of the ROM from 20FFFD to 2058FF.
[ Art is a subscriber in Manvel, North Dakota; he is the programming side of S&H Software. Art wrote the Universal Boot Initializer, The DOS Enhancer, and the AmperCat Utility. ]
The new S-C Macro Assembler is truly the best assembler around. With the addition of Macros, easier programming is limited only by your imagination. All you have to do is dream up some uses for Macros. Are Macros and Nested Macros really worth using? You bet! One of my source files was 104 sectors long, but after going back through it and implementing macros, the file shortened to only 96 sectors; it was also easier to read.
As Bob pointed out in the manual, nested macros are allowed in this new version, but he frowned on their use. I beg to differ with him, as I believe that nested macros can make your source files easier to read, as well as easier to write. They may seem complex at first, but after setting them up they become very easy to use.
In my example program, I've defined a macro called GOTO.XY that will take two variables and use them to position the cursor. Another defined macro called CLEAR.XY is a singly nested macro that uses GOTO.XY to position the cursor, and then clears from there to the end of screen. CLEAR.PRINT.XY positions the cursor (using GOTO.XY inside CLEAR.PRINT.XY), clears the rest of the screen, and prints a message. It may sound confusing, but after examining the source listing and th macro definitions, it should be easy to understand how this all works.
In all the macros, the first variable is the horizontal cursor position and the second variable is the vertical cursor position. CLEAR.PRINT.XY calls on a subroutine (JSR PRNT), which expects the message to follow the JSR instruction. The message is terminated by a 00 byte, and execution proceeds at the instruction which follows the message in memory.
The PRNT subroutine came from a Call A.P.P.L.E. article by Andy Hertzfeld.
Have fun with your new S-C Macro Assembler!
1000 *-------------------------------- 1010 * USE OF MACROS & NESTED MACROS 1020 * BY ART SCHUMER - 3/25/82 1030 *-------------------------------- 1040 VTAB .EQ $FB5B 1050 CLREOP .EQ $FC42 1060 HOME .EQ $FC58 1070 RDKEY .EQ $FD0C 1080 COUT .EQ $FDED 1090 *-------------------------------- 1100 PTR .EQ $6 1110 CH .EQ $24 1120 CV .EQ $25 1130 *-------------------------------- 1140 * MACRO DEFINITIONS 1150 * 1160 * CLR.PRNT.XY AND GOTO.PRNT.XY 1170 * ARE EXAMPLES OF NESTED MACROS 1180 *-------------------------------- 1190 .MA GOTO.XY 1200 LDA #]1 1210 STA CH 1220 LDA #]2 1230 JSR VTAB 1240 .EM 1250 *-------------------------------- 1260 .MA CLEAR.XY 1270 >GOTO.XY ]1,]2 1280 JSR CLREOP 1290 .EM 1300 *-------------------------------- 1310 .MA CLEAR.PRNT.XY 1320 >CLEAR.XY ]1,]2 1330 JSR PRNT 1340 .EM 1350 *-------------------------------- 1360 .MA GOTO.PRNT.XY 1370 >GOTO.XY ]1,]2 1380 JSR PRNT 1390 .EM 1400 *-------------------------------- 1410 .MA READ.XY 1420 >GOTO.XY ]1,]2 1430 JSR RDKEY 1440 .EM 1450 *-------------------------------- 1460 * THE PROGRAM . . . . 1470 *-------------------------------- 1480 START JSR HOME 1490 >GOTO.PRNT.XY 4,12 1500 .AS -/THIS EXAMPLE USES NESTED MACROS/ 1510 .HS 00 1520 >READ.XY 36,12 1530 >CLEAR.PRNT.XY 4,12 1540 .AS -/AND THIS ONE ALSO!/ 1550 .HS 00 1560 >READ.XY 22,12 1570 RTS 1580 *-------------------------------- 1590 * ANDY HERTZFELD'S PRINT ROUTINE 1600 *-------------------------------- 1610 PRNT PLA 1620 STA PTR 1630 PLA 1640 STA PTR+1 1650 LDY #0 1660 .1 INC PTR 1670 BNE .2 1680 INC PTR+1 1690 .2 LDA (PTR),Y 1700 BEQ .3 1710 JSR COUT 1720 JMP .1 1730 .3 LDA PTR+1 1740 PHA 1750 LDA PTR 1760 PHA 1770 RTS 1780 *-------------------------------- |
[ Lee is a subscriber from Arlington, Texas. He wrote the original code for the .TF directive and REPLACE command in the S-C Assemblers. ]
Here is short example of a useful macro that uses a recursive definition. By recursive I mean that the definition calls itself.
Most large computers have a shift instruction which can shift any number of bits; the 6502 shifts only shift one bit at a time. The LSR macro shown here accepts a shift count as the first parameter, and generates one LSR opcode for each bit shift you want.
The second parameter is optional. If there is no second parameter, the A-register will be shifted. If you specify a variable for the second parameter, that memory location will be shifted. Both cases are shown in the example below.
How does it work? The definiton says to test the first parameter; if it is greater than zero, generate the LSR with the optional second parameter as the address field, and call on the LSR macro with the first parameter decremented by one. If the first parameter is zero (and it eventually will be), no code is generated. Read the listing carefully, noting the indentation, and you should be able to follow it.
1000 .MA LSR Define LSR macro 1010 .DO ]1>0 1020 LSR ]2 1030 >LSR ]1-1,]2 1040 .FIN 1050 .EM 1060 *-------------------------------- 0800- 1070 >LSR 3,$12 Shift $12 left 3 times 0000> .DO 3>0 0800- 46 12 0000> LSR $12 0802- 0000> >LSR 3-1,$12 0000>> .DO 3-1>0 0802- 46 12 0000>> LSR $12 0804- 0000>> >LSR 3-1-1,$12 0000>>> .DO 3-1-1>0 0804- 46 12 0000>>> LSR $12 0806- 0000>>> >LSR 3-1-1-1,$12 0000>>>> .DO 3-1-1-1>0 0000>>>> .FIN 0000>>> .FIN 0000>> .FIN 0000> .FIN 0806- 1100 >LSR 2 Shift A-register left 2 times 0000> .DO 2>0 0806- 4A 0000> LSR 0807- 0000> >LSR 2-1,$12 0000>> .DO 2-1>0 0807- 4A 0000>> LSR 0808- 0000>> >LSR 2-1-1,$12 0000>>> .DO 2-1-1>0 0000>>> .FIN 0000>> .FIN 0000> .FIN |
Paul Schlyter's article on moving the S-C Assembler into the language card (AAL January 1982) couldn't have come at a better time for me. I was working on a project that had just outgrown the available memory space, and LANGASM came to the rescue. Long live LANGASM!
LANGASM and the extensions to the S-C Assembler that have appeared in the AAL bring to the fore an important subject: controlling the configuration of your copy of someone else's software.
How do I know that a particular "patched" copy I have of the assembler is compatible with another extension that will appear in next month's AAL? What kind of documentation must I keep somewhere to keep track of patched object code for which I have no source code? And how many different patched source code versions (to which I have given different names) of the S-C Assembler am I willing to keep track of?
For my use, I've chosen to keep track of only two modified copies of the assembler; I call them ASM II.1 and LANGASM.1. These two versions are simply the "standard issue" S-C Assembler Version 4.0 and LANGASM, each augmented with the listed .DA directive patch described by Bob in the December, 1980 issue of AAL. (I chose this configuration because the extension was written by Bob himself, and because other AAL articles have used the listed .DA directive. The feature is upward compatible, and listed .DAs presented to unmodified copies of the assembler will cause invisible errors by seemingly accepting those directives, while generating no code for items beyond the comma.)
To add the extensions I want, I first load in ASM II.1 or LANGASM.1, and then modify the copy in memory with a configuration file before using it.
The source listing of LANGASM.1 EXT.SRC shows the method I use to add HOME, COPY and EDIT commands to my copy of LANGASM.1. This particular routine is .OR'd at the beginning of one of the 4K language card memory blocks located at $D000, which permits several extensions to be loaded in one contiguous area of memory, while leaving the main memory area free for the source file and symbol table.
Lines 1160-1570 install the patches in the memory-resident copy of LANGASM.1 and then return to a calling routine. Lines 1320-1400 patch the FAST command (disabled by the LANGASM patches) to render it a HOME command that works like Applesoft's does.
Lines 1260-1430 make similar modifications to LANGASM's command table entries, replacing LOAD with COPY and SAVE with EDIT, along with their assembled addresses (less one).
Lines 1440-1520 are the patches that were contained in Mike Laumer's source code for the EDIT command, found in the January, 1981 issue of AAL.
The source files for EDIT and COPY used within LANGASM.1 EXT.SRC in lines 1590 to the end of the file are identical to those written by Mike Laumer and Bob Sander-Cederlof, with a couple of exceptions. As stated above, the patch code for NML was moved to the modification area in lines 1440-1520. Second, all .OR and .TF directives were removed from both files. Third, a few redundant .EQ directives (internal assembler reference addresses) had to be removed to avoid any EXTRA DEFINITION errors. Finally, $D000 was added to all internal assembler references to make them compatible with LANGASM's $E000 origin.
To install these patches to LANGASM.1, I EXEC the following text file, which I call LANGASM:
CALL -151 (get into the monitor) C0C1 (turn off any firmware card) C081 C081 (write enable the language card) BLOAD LANGASM.1 (load LANGASM into the language card) BLOAD MONITOR EXTENSIONS (load in page 3 extensions from 10/81 issue of AAL) BLOAD LANGASM.1 EXTENSIONS (load in the mods) A5B8:80 (patch DOS to use the language card) A5C0:81 300G (install monitor extensions) C083 (switch in Bank 2) D000G (install LANGASM mods) 3D3G (return to DOS and Applesoft) INT (enter the assembler)
To use this method of in-memory configuration with ASM II.1 (where patches can't always be added in contiguous memory), I use a separate file for each command patch, each .OR'd at the proper address, and then install all patch routines within a single text file that is EXEC'd. Since I'm not dealing with the language card, and each of the commands added above are indepedent of one another, I can skip the EXEC and just BLOAD and install each command (or group of commands) I want to add with the monitor. The result is an easy configuration of the assembler, done at run time.
The use of configuration files to modify the assembler takes a few extra seconds (and a couple of extra files on my utility disk), but it is no more work thanks to the EXEC file. It permits me to keep only a single copy of the assembler (in a known configuration), while enabling me to fully document any modifications I make to the assembler with configuration files for which I have the source code. By creating different EXEC files, I can quickly and easily intermix configuration files to create (and document!) any version of the assembler I wish.
Even though I suppressed the listing of the EDIT and COPY commands to save newsletter space, the source code is on the Quarterly Disk (#7) which will include this program.
1000 *--------------------------------- 1010 * INSTALL EXTENSIONS TO LANGASM 1020 * 1030 * AUTHOR: DON TAYLOR 1040 * DATE: 2/6/82, 4:00 PM 1050 * 1060 *--------------------------------- 1070 .OR $D000 1080 .TF LANGASM.1 EXTENSIONS 1090 *--------------------------------- 1100 DOS.REENTRY .EQ $03D0 1110 MON.HOME .EQ $FC58 1120 SCA.LOAD.CMD .EQ $E246 1130 SCA.SAVE.CMD .EQ $E26E 1140 SCA.SLOW.CMD .EQ $E273 1150 *--------------------------------- 1160 INSTALL.MODIFICATIONS 1170 LDY #2 MODIFY ASSEMBLER 1180 .1 LDA HOME.TABLE,Y COMMAND JUMP 1190 STA SCA.SLOW.CMD,Y 1200 DEY 1210 BPL .1 1220 LDA #MON.HOME-1 1230 STA SCA.SLOW.CMD+3 1240 LDA /MON.HOME-1 1250 STA SCA.SLOW.CMD+4 1260 LDY #2 1270 .2 LDA COPY.TABLE,Y 1280 STA SCA.LOAD.CMD,Y 1290 DEY 1300 BPL .2 1310 LDA #COPY-1 1320 STA SCA.LOAD.CMD+3 1330 LDA /COPY-1 1340 STA SCA.LOAD.CMD+4 1350 LDY #2 1360 .3 LDA EDIT.TABLE,Y 1370 STA SCA.SAVE.CMD,Y 1380 DEY 1390 BPL .3 1400 LDA #EDIT-1 1410 STA SCA.SAVE.CMD+3 1420 LDA /EDIT-1 1430 STA SCA.SAVE.CMD+4 1440 LDA #$60 PATCH NML TO 1450 STA $E125 MAKE IT A 1460 LDA #$4C SUBROUTINE 1470 STA NML 1480 STA $E078 1490 LDA #NEW.NML 1500 STA NML+1 1510 LDA /NEW.NML 1520 STA NML+2 1530 RTS 1540 *--------------------------------- 1550 HOME.TABLE .AS ^HOM^ 1560 COPY.TABLE .AS ^COP^ 1570 EDIT.TABLE .AS ^EDI^ 1580 *--------------------------------- 1590 * COPY COMMAND FOR S-C ASSEMBLER 1600 * VERSION 4.0 1610 * 1620 * SOURCE: BOB SANDER-CEDERLOF 12/80 1630 * 1640 *--------------------------------- 1650 * 1660 * 1670 * NOTE: COPY FUNCTION SOURCE IS 1680 * ASSEMBLED HERE... 1690 .LIST OFF 1700 * 1710 * COPY FUNCTION <COPY L1,L2,L3> 1720 * L1= FIRST LINE OF RANGE TO COPY 1730 * L2= LAST LINE OF RANGE TO COPY 1740 * L3= LINE BEFORE WHICH TO INSERT COPY 1750 * 1760 * ROUTINE BY BOB SANDER-CEDERLOF 1770 * APPLE ASSEMBLY LINE 12/80 1780 * 1790 *--------------------------------- 1800 SS .EQ $00,01 START OF SOURCE BLOCK 1810 SE .EQ $02,03 END OF SOURCE BLOCK 1820 SL .EQ $04,05 LENGTH OF SOURCE BLOCK 1830 NEWPP .EQ $06,07 NEW PROGRAM POINTER 1840 A0L .EQ $3A,3B 1850 A0H .EQ $3B 1860 A1L .EQ $3C,3D 1870 A1H .EQ $3D 1880 A2L .EQ $3E 1890 A2H .EQ $3F 1900 A4L .EQ $42 1910 A4H .EQ $43 1920 LOMEM .EQ $4A,4B 1930 PP .EQ $CA,CB 1940 *--------------------------------- 1950 SYNX .EQ $E05E 1960 MFER .EQ $E128 1970 SCND .EQ $E12D 1980 SERTXT .EQ $E4F6 1990 MON.MOVE .EQ $FE2C 2000 *--------------------------------- 2010 ERR1 JMP SYNX 2020 ERR2 .EQ ERR1 2030 ERR3 JMP MFER 2040 ERR4 .EQ ERR1 2050 *--------------------------------- 2060 COPY 2070 JSR SCND GET THIRD PARAMETER 2080 CPX #6 BE SURE WE GOT THREE 2090 BCC ERR1 NOT ENOUGH PARAMS 2100 LDX #A0L FIND BEGINNING OF SOURCE 2110 JSR SERTXT 2120 LDA $E4 SAVE POINTER 2130 STA SS 2140 LDA $E5 2150 STA SS+1 2160 LDX #A1L FIND END OF SOURCE BLOCK 2170 JSR SERTXT 2180 SEC SAVE POINTER AND COMPUTE 2190 LDA $E6 LENGTH 2200 STA SE 2210 SBC SS 2220 STA SL SOURCE LENGTH 2230 LDA $E7 2240 STA SE+1 2250 SBC SS+1 2260 STA SL+1 2270 BCC ERR2 RANGE BACKWARD 2280 BNE .4 2290 LDA SL 2300 BEQ ERR2 NOTHING TO MOVE 2310 *--------------------------------- 2320 .4 LDA PP COMPUTE NEW PP POINTER 2330 SBC SL 2340 STA NEWPP 2350 LDA PP+1 2360 SBC SL+1 2370 STA NEWPP+1 2380 *--------------------------------- 2390 LDA NEWPP SEE IF ROOM FOR THIS 2400 CMP LOMEM 2410 LDA NEWPP+1 2420 SBC LOMEM+1 2430 BCC ERR3 MEM FULL ERROR 2440 *--------------------------------- 2450 LDX #A2L FIND TARGET LOCATION 2460 JSR SERTXT 2470 LDA SS BE SURE NOT INSIDE SOURCE 2480 CMP $E4 2490 LDA SS+1 2500 SBC $E5 2510 BCS .1 BELOW SOURCE BLOCK 2520 LDA $E4 2530 CMP SE 2540 LDA $E5 2550 SBC SE+1 2560 BCC ERR4 INSIDE SOURCE BLOCK 2570 * TARGET IS ABOVE SOURCE BLOCK, SO WE HAVE TO 2580 * ADJUST SOURCE BLOCK POINTERS. 2590 SEC 2600 LDA SS 2610 SBC SL SS=SS-SL 2620 STA SS 2630 LDA SS+1 2640 SBC SL+1 2650 STA SS+1 2660 SEC 2670 LDA SE 2680 SBC SL SE=SE-SL 2690 STA SE 2700 LDA SE+1 2710 SBC SL+1 2720 STA SE+1 2730 *--------------------------------- 2740 .1 LDA PP SET UP MOVE TO MAKE HOLE 2750 STA A1L 2760 LDA PP+1 2770 STA A1H 2780 LDA NEWPP 2790 STA PP 2800 STA A4L 2810 LDA NEWPP+1 2820 STA PP+1 2830 STA A4H 2840 LDA $E5 2850 STA A2H 2860 LDA $E4 2870 STA A2L 2880 BNE .2 2890 DEC A2H 2900 .2 DEC A2L A2=A2-1 2910 LDY #0 2920 LDA A2L 2930 CMP A1L 2940 LDA A2H 2950 SBC A1H 2960 BCC .5 2970 JSR MON.MOVE A4<A1.A2M 2980 *--------------------------------- 2990 .5 LDA SS MOVE IN SOURCE BLOCK 3000 STA A1L (MON.MOVE LEFT 3010 LDA SS+1 A4 POINTING AT FIRST 3020 STA A1H BYTE OF THE HOLE) 3030 LDA SE+1 3040 STA A2H 3050 LDA SE 3060 STA A2L 3070 BNE .3 3080 DEC A2H A2=A2-1 3090 .3 DEC A2L 3100 JSR MON.MOVE A4<A1.A2 3110 RTS 3120 .LIST ON 3130 * 3140 * 3150 * NOTE: EDIT FUNCTION SOURCE IS 3160 * ASSEMBLED HERE... 3170 .LIST OFF 3180 * 3190 * 3200 *--------------------------------- 3210 * EDIT COMMAND FOR S-C ASSEMBLER 3220 * VERSION 4.0 3230 * 3240 * SOURCE: MIKE LAUMER 12/6/80 3250 * 3260 *--------------------------------- 3270 * 3280 * SYSTEM EQUATES 3290 *--------------------------------- 3300 MON.COUT .EQ $FDED 3310 MON.BELL .EQ $FF3A 3320 MON.RDKEY .EQ $FD0C 3330 MON.CLREOP .EQ $FC42 3340 MON.VTAB .EQ $FC22 3350 CH .EQ $0024 3360 CV .EQ $0025 3370 *--------------------------------- 3380 * ASSEMBLER EQUATES 3390 *--------------------------------- 3400 GNL .EQ $E026 3410 NML .EQ $E063 3420 PLNO .EQ $E779 3430 GNB .EQ $E2C5 3440 DOIT .EQ $E874 3450 SEARCH .EQ $E64B 3460 SERNXT .EQ $E4FE 3470 NTKN .EQ $E2AF 3480 SRCP .EQ $DD,DE 3490 WBUF .EQ $0200 3500 CURRENT.LINE.NUMBER .EQ $D3,D4 3510 *--------------------------------- 3520 * PATCH ROUTINES FOR ASSEMBLER 3530 *--------------------------------- 3540 NEW.NML JSR MY.NML 3550 JMP GNL 3560 MY.NML LDY #0 3570 JSR $E28D 3580 JSR $E14A 3590 JMP $E066 3600 *--------------------------------- 3610 * LOCAL VARIABLES FOR EDIT COMMAND 3620 *--------------------------------- 3630 NEXT .DA 0 3640 END .DA 0 3650 CHAR .DA #0 3660 EDPTR .DA #0 3670 FKEY .DA #0 3680 *--------------------------------- 3690 EDIT DEX 3700 DEX 3710 BMI .2 NO ARGUMENTS 3720 BEQ .4 1 ARGUMENT 3730 JSR .3 2 ARGUMENTS 3740 LDX #A1L FIND END PTR 3750 JSR SERNXT 3760 LDA $E6 3770 STA END 3780 LDA $E7 3790 STA END+1 3800 .1 LDA NEXT+1 3810 STA SRCP+1 3820 PHA 3830 LDA NEXT 3840 STA SRCP 3850 CMP END 3860 PLA 3870 SBC END+1 PAST END LINE? 3880 BCS .2 YES, EXIT 3890 JSR E.LIST NO, LIST AND EDIT 3900 JMP .1 TRY FOR NEXT LINE 3910 .3 LDX #A0L FIND START PTR 3920 JSR SERTXT 3930 LDA $E4 3940 STA SRCP 3950 STA NEXT SAVE NEXT LINE ADRS 3960 LDA $E5 3970 STA SRCP+1 3980 STA NEXT+1 3990 .2 RTS 4000 .4 JSR .3 SEARCH FOR LINE 4010 BCC .2 NOT FOUND EXIT 4020 E.LIST JSR E.POSN POSITION FOR EDIT 4030 JSR MON.CLREOP PREPARE DISPLAY 4040 JSR GNB GET LINE SIZE 4050 CLC 4060 ADC NEXT COMPUTE NEXT LINE ADRS 4070 STA NEXT 4080 TYA 4090 ADC NEXT+1 4100 STA NEXT+1 4110 JSR GNB GET LINE # FOR DISPLAY 4120 STA CURRENT.LINE.NUMBER 4130 JSR GNB 4140 STA CURRENT.LINE.NUMBER+1 4150 SEC 4160 ROR $F8 STUFF WBUF FLAG 4170 JSR PLNO 4180 LSR $F8 TURN OFF FLAG 4190 LDA #$20 SPACE AFTER LINE # 4200 LDX #0 4210 .1 STX EDPTR 4220 ORA #$80 FORCE VIDEO BIT 4230 STA WBUF+4,X STORE INTO INPUT BUFFER 4240 CMP #$A0 TEST FOR CONTROL CHAR 4250 BCS .2 OK, IF NOT 4260 AND #$7F OUTPUT INVERSE ALPHA 4270 .2 JSR MON.COUT PRINT CHAR 4280 JSR NTKN GET NEXT TOKEN 4290 LDX EDPTR 4300 INX 4310 CMP #0 END TOKEN? 4320 BNE .1 NO,PRINT IT 4330 STA WBUF+4,X YES,PUT IT IN TOO 4340 E.LINE LDX #0 4350 E.0 STX EDPTR 4360 E.1 JSR E.INPUT GET INPUT CHAR 4370 E.2 LDA #EDTB 4380 STA $2 4390 LDA /EDTB 4400 STA $3 4410 LDA #CHAR 4420 STA $12 4430 LDA /CHAR 4440 STA $13 4450 JSR SEARCH SEARCH EDIT COMMAND TABLE 4460 BNE .2 NOT IN TABLE 4470 LDX EDPTR 4480 JSR DOIT EXECUTE COMMAND ROUTINE 4490 BCC E.0 NO DISPLAY ON RETURN 4500 BCS .5 DISPLAY ON RETURN 4510 .2 LDX EDPTR MUST BE TYPE OVER 4520 LDA CHAR 4530 CMP #$A0 4540 BCS .4 4550 .3 JSR MON.BELL ERR IF CONTROL KEY 4560 JMP E.1 4570 .4 LDA WBUF+5,X SEE IT END OF LINE 4580 BNE .6 TYPE OVER IF NOT 4590 STA WBUF+6,X SHIFT OVER END OF LINE 4600 .6 LDA CHAR STUFF CHAR INTO BUFFER 4610 STA WBUF+5,X 4620 CPX #256-5-2 TEST BUFFER SIZE 4630 BEQ .5 TYPE OVER LAST CHAR IN BUFFER 4640 INX INSTEAD OF BUFFER END 4650 .5 JSR E.DISP DISPLAY LINE 4660 JMP E.0 GET NEXT EDIT COMMAND 4670 *--------------------------------- 4680 E.POSN LDA #19 POSITION TO LINE 19, 4690 STA CV 4700 LDA #0 COLUMN 0 4710 STA CH 4720 JMP MON.VTAB 4730 *--------------------------------- 4740 E.DISP STX EDPTR 4750 JSR E.POSN POSITION DISPLAY 4760 LDX #$FF 4770 .1 INX 4780 LDA WBUF,X GET BUFFER CHAR 4790 BEQ .3 END OF BUFFER 4800 CMP #$A0 CONTROL CHAR? 4810 BCS .2 NO 4820 AND #$7F PRINT INVERSE ALPHA 4830 .2 JSR MON.COUT PRINT CHAR 4840 JMP .1 NEXT CHAR 4850 .3 JSR MON.CLREOP CLEAN ANY REMAINING SCREEN 4860 LDX EDPTR 4870 RTS 4880 *--------------------------------- 4890 E.BEG LDX #0 SET CURSOR TO BEGINNING OF LINE 4900 CLC 4910 RTS 4920 *--------------------------------- 4930 E.DEL LDA WBUF+5,X IS THIS END 4940 BEQ .2 4950 .1 INX 4960 LDA WBUF+5,X SHIFT TO LOWER MEMORY 4970 STA WBUF+4,X TO DELETE CHAR 4980 BNE .1 4990 LDX EDPTR 5000 .2 SEC RETURN WITH DISPLAY 5010 RTS 5020 *--------------------------------- 5030 E.END LDA WBUF+5,X END OF BUFFER? 5040 BEQ .1 YES 5050 INX NO 5060 BNE E.END TRY END AGAIN 5070 .1 CLC RETURN NO DISPLAY 5080 RTS 5090 *--------------------------------- 5100 E.FIND LDA WBUF+5,X END OF BUFFER? 5110 BNE .2 NO 5120 .1 STA FKEY YES SO ERR 5130 JSR MON.BELL RING BELL 5140 CLC RETURN NO DISPLAY 5150 RTS 5160 .2 JSR E.INPUT GET 1 CHAR 5170 STA FKEY SAVE KEY TO LOCATE 5180 .3 INX 5190 LDA WBUF+5,X TEST BUFFER 5200 BEQ .1 END OF BUFFER 5210 CMP FKEY NO, SEE IF KEY 5220 BNE .3 NO, GO FORWARD 5230 JSR E.INPUT TRY ANOTHER KEY 5240 CMP FKEY SAME CHAR? 5250 BEQ .3 YES, SEARCH AGAIN 5260 PLA 5270 PLA 5280 STX EDPTR NO, EXIT POINTING HERE 5290 JMP E.2 5300 *--------------------------------- 5310 E.BKSP TXA AT BEGINNING? 5320 BEQ .1 YES, STAY THERE 5330 DEX BACKUP 5340 .1 CLC RETURN NO DISPLAY 5350 RTS 5360 *--------------------------------- 5370 E.OVR JSR E.INPUT READ CHAR 5380 JMP E.INS1 SKIP CONTROL CHECK 5390 *--------------------------------- 5400 E.INS JSR E.INPUT READ CHAR 5410 CMP #$A0 CONTROL CHAR POPS USER OUT 5420 BCC E.INS2 OF INSERT 5430 E.INS1 CPX #256-5-2 END OF BLOCK 5440 BEQ .1 YES STAY THERE 5450 INX 5460 .1 STX EDPTR 5470 .2 PHA CHAR TO INSERT 5480 LDA WBUF+4,X SAVE CHAR TO MOVE 5490 TAY 5500 PLA GET CHAR TO INSERT 5510 STA WBUF+4,X PUT OVER SAVED CHAR 5520 INX 5530 TYA INSERT SAVED CHAR 5540 BNE .2 IF NOT BUFFER END 5550 STA WBUF+4,X STUFF END CODE 5560 STA WBUF+256-5-1 INSURE AN END CODE 5570 LDX EDPTR 5580 JSR E.DISP DISPLAY LINE 5590 JMP E.INS GET NEXT INSERT CHAR 5600 E.INS2 PLA SEND CHAR TO 5610 PLA COMMAND SEARCH 5620 LDX EDPTR 5630 *--------------------------------- 5640 JMP E.2 5650 E.RETQ LDA #0 CLEAR REST OF LINE 5660 STA WBUF+5,X 5670 JSR E.DISP DISPLAY LINE 5680 E.RET LDX #$FF SUBMIT LINE TO ASSEMBLER 5690 .1 INX COMPUTE LINE SIZE 5700 LDA WBUF,X 5710 BNE .1 5720 DEX 5730 .2 STX $E1 SAVE SIZE 5740 PLA 5750 PLA 5760 JMP MY.NML SUBMIT THE LINE 5770 *--------------------------------- 5780 E.TAB CPX #20 <COL 20? 5790 BCS .1 NO 5800 LDA WBUF+5,X END OF BUFFER? 5810 BEQ .1 YES 5820 INX MOVE FORWARD 5830 CPX #7 TAB MATCH? 5840 BEQ .1 5850 CPX #11 TAB MATCH? 5860 BNE E.TAB 5870 .1 CLC RETURN WITHOUT DISPLAY 5880 RTS 5890 *--------------------------------- 5900 E.RIT LDA WBUF+5,X END OF BUFFER? 5910 BNE .1 NO 5920 STA WBUF+6,X 5930 LDA #$A0 PUT A BLANK 5940 STA WBUF+5,X TO EXTEND LINE 5950 CPX #256-5-2 5960 BEQ .2 5970 .1 INX MOVE AHEAD 5980 .2 CLC RETURN NO DISPLAY 5990 RTS 6000 *--------------------------------- 6010 E.ABORT LDA #$DC OUTPUT BACKSLASH 6020 STA WBUF+5 6030 LDA #0 6040 STA WBUF+6 6050 JSR E.DISP SHOW CANCEL 6060 JMP GNL GET NEXT COMMAND 6070 *--------------------------------- 6080 E.INPUT LDA #19 6090 STA CV 6100 TXA POSITION TO CURSOR 6110 CLC 6120 ADC #5 6130 .1 CMP #40 THIS LINE? 6140 BCC .2 YES 6150 SEC 6160 SBC #40 6170 INC CV ON NEXT LINE 6180 BNE .1 6190 .2 STA CH 6200 JSR MON.VTAB SET BASL 6210 JSR MON.RDKEY INPUT A CHAR 6220 STA CHAR 6230 RTS 6240 *--------------------------------- 6250 * COMMAND TABLE 6260 *--------------------------------- 6270 EDTB .DA #3,#1 ITEM SIZE, KEY SIZE 6280 .DA #$82,E.BEG-1 ^B 6290 .DA #$84,E.DEL-1 ^D 6300 .DA #$8E,E.END-1 ^N 6310 .DA #$86,E.FIND-1 ^F 6320 .DA #$88,E.BKSP-1 ^H 6330 .DA #$89,E.INS-1 ^I 6340 .DA #$8D,E.RET-1 ^M 6350 .DA #$8F,E.OVR-1 ^O 6360 .DA #$91,E.RETQ-1 ^Q 6370 .DA #$94,E.TAB-1 ^T 6380 .DA #$95,E.RIT-1 ^U 6390 .DA #$98,E.ABORT-1 ^X 6400 .DA #0 6410 .EN |
This funny program uses the contents of RAM and ROM from $0000 to $BFFF and from $D000 to $FFFF as timers to control a speaker-toggle loop. How it sounds depends on what you have in memory!
1000 *-------------------------------- 1010 * FUNNY NOISE 1020 *-------------------------------- 1030 SPKR .EQ $C030 SPEAKER TOGGLE ADDRESS 1040 KYBD .EQ $C000 KEYBOARD INPUT 1050 STROBE .EQ $C010 KEYBOARD STROBE 1060 *-------------------------------- 1070 PNTR .EQ 0 ADDRESS OF CURRENT RANDOM VALUE 1080 *-------------------------------- 1090 NOISE JSR $FC58 CLEAR SCREEN, HOME CURSOR 1100 N0 LDY #0 POINT TO FIRST BYTE IN PAGE 1110 LDA #$D000 START AT $D000 1120 STA PNTR 1130 LDA /$D000 1140 STA PNTR+1 1150 JSR $FDDA PRINT PAGE NUMBER 1160 N1 LDA SPKR TOGGLE SPEAKER 1170 LDA (PNTR),Y GET HALF-CYCLE TIMER 1180 TAX 1190 N2 DEX DELAY LOOP FOR HALF-CYCLE 1200 BNE N2 1210 INY NEXT BYTE IN PAGE 1220 BNE N1 1230 INC PNTR+1 NEXT PAGE 1240 LDA PNTR+1 BYPASS I/O AREA 1250 CMP /$C000 1260 BEQ N0 1270 JSR $FDDA PRINT PAGE NUMBER 1280 LDA KYBD SEE IF ANY KEY PRESSED 1290 BPL N1 NO, KEEP MAKING NOISE 1300 STA STROBE YES, CLEAR STROBE 1310 RTS THAT'S ALL, FOLKS! |