Apple Assembly Line
Volume 2 -- Issue 7 April 1982

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.


Adding Auto-SAVE to S-C Macro Assembler Greg H. Anders

[ 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

AED -- A New Applesoft Program Editor Reviewed by Bob Sander-Cederlof

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.


Ashby's Easy Shift-Key Modifier Bob Sander-Cederlof

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.


Potential Trouble in TYMAC Robert H. Bernard

[ 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.


Using Macros and Nested Macros Art Schumer

[ 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  *--------------------------------

Recursive Macro Example Lee Meador

[ 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

Controlling Software Configuration Don Taylor

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

Funny Noise Bob Sander-Cederlof

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!

Apple Assembly Line is published monthly by S-C SOFTWARE, P. O. Box 280300, Dallas, TX 75228. Phone (214) 324-2050 Subscription rate is $15 per year, in the USA, sent Second Class Mail; $18 per year sent First Class Mail in USA, Canada, and Mexico; $28 per year sent Air Mail to other countries. Back issues are available for $1.50 each (other countries add $1 per back issue for postage). All material herein is copyrighted by S-C SOFTWARE, all rights reserved. Unless otherwise indicated, all material herein is authored by Bob Sander-Cederlof. (Apple is a registered trademark of Apple Computer, Inc.)