Volume 8 -- Issue 1 | October 1987

In This Issue...

- Key-Edit Utility Program for the IIgs
- INDEX to Volume 7 (October 1986 thru September 1987)
- How to Clear the ProDOS-8 Back-Up Bit
- Sean Nolan's Proposed ProDOS-8 SETUP File Standard

Thanksgiving

I know the date above says October, but it is now the day before Thanksgiving on my calendar. Since Bill Morgan moved to a new job in Austin, Texas, it has been quite a challenge to put the newsletter together! I am thankful that you are patient, and that God is faithful. And He reigns. Even in this day of wild stock markets, economic uncertainty, natural disasters, and wars we can see that He is, and that "He has made the earth by his power, He has established the world by His wisdom, and has stretched out the heaven by His understanding."

Using Laumer Research Full Screen Editor on IIgs

The ProDOS version of the Full Screen Editor is compatible with the IIgs and with Version 2.0 of the S-C Macro Assembler. The DOS version, on the other hand, requires a different setup file. This is now provided as the file "ED IIGS 2.0", a text file which you EXEC to load and install the FSE. Since there are a lot of you who may need this file so I will describe its contents here:

         MNTR
         BLOAD EDITOR,A$5000
         BLOAD B.DRIVER.AP2E,A$5DB5
         0=L
         0/D000<0/5000.5FFFM
         1=L
         0/D074:4C FA F7
         0/F7F4:AD 80 C0 4C 03 D0 AD 88 C0 4C 00 D0
         Q

You can create this file by typing the above lines with line numbers in the S-C Macro Assembler, and then save them on a text file using the command "TEXT ED IIGS 2.0" You may of course move the files ED IIGS 2.0, EDITOR, and B.DRIVER.AP2E to your assembler disks, and create a composite load file so that the FSE installation is automatic.

Key-Edit Utility Program for the IIgs | Bob Boughner

Key-Edit is a IIgs utility program that permits the rapid recall and easy editing of previously entered commands or program source lines. Key-Edit works in either 40- or 80-column mode, and will work inside a window smaller than the full screen if you set the proper values in the monitor window definition bytes. The program is patterned after a similar program I use at work on an IBM AT, which explains some of the rather strange keyboard choices.

The current version, shown here, of Key-Edit works only under DOS. I hope to modify it for at least ProDOS-8 in the near future. Because of the keyboard choices I made, it is currently tied to the IIgs. Toward the end of this article I will describe the changes needed to make it work in a //e or //c.

Key-Edit requires four pages (1024 bytes) for itself and the buffer of previously-typed commands. I obtained these four pages by moving the DOS buffers down (an old trick). When you BRUN KEY.EDIT it loads at $5000; the code at $5000 then moves the buffers down four pages, copies Key-Edit into the hole starting at $9900, and clears a command buffer at $9C00-$9CFF. I also patch in a RESET routine so that RESET will re-install Key-Edit. The vector which was at $3F2,3F3 is copied into my patch, so that RESET will still function normally. Of course if you later patch a new RESET vector, my patch will be left out in the cold.

Key-Edit works by intercepting the normal keyboard input stream. A table (lines 2660-2870) defines fifteen special combinations of normal keys with the Open-Apple, Option (Solid-Apple), Control, and Shift keys. If any of these special keystrokes is detected, Key-Edit performs an editing operation on the input buffer and the screen. Other keystrokes are passed to the program which asked for input. Key-Edit is compatible with the S-C Macro Assembler and Applesoft, and may work with other DOS-based applications.

When you finally type a RETURN, the current line is copied into my one-page buffer. A pointer keeps track of the end of the last line copied in my buffer, so the each command is copied onto the end of the previous command. I separate the commands in my buffer with $00 bytes rather than RETURN ($8D) codes, because it is easier to test for them in the various loops. When you type the "up arrow" key, the most recently entered command line is retrieved, placed into the buffer at $200, and displayed on the screen. Another "up arrow" will move back in time to the command line before that one, and so on. Since the buffer is only 256 bytes long, there is a limit to how many commands are remembered. The buffer is circular, so after you have looked at the oldest one another "up arrow" will show you the newest one. The "down arrow" key moves you around the buffer in the opposite direction. When you find the command you want, simply hit RETURN to execute it. Or, if it is only approximately what you want, edit it and then hit RETURN.

When you start up Key-Edit, the command buffer is cleared. Each time you enter a new command, it is copied on the end of the previous command. Once the end of the buffer is reached, the buffer wraps around to the beginning, and the command there is over-written. The over-written command is obviously the oldest command in the buffer. Then enough $00 bytes are stored to clear out any partial command line. This allows the up- and down-arrows to scan smoothly forward or backward around the buffer.

The editing commands in Key-Edit allow you to scan back and forth along the input line, delete characters, insert characters, and submit the line without needing to scan to the end-of-line first. Regardless of where the cursor is on the line, you can type the RETURN key and the whole line will be submitted. Scanning back and forth is done with either the TAB key or the left and right arrow keys, with or without the open-apple key:

           left arrow      move back one character
           right arrow     move ahead one character
           OA-left         move to beginning of line
           OA-right        move to end of line
           TAB             move ahead to next "tab" stop
           OA-TAB          move back to next "tab" stop

These keys will not move backward beyond the beginning of the line, nor forward past the end of the line. A "tab" stop is defined as the next occurrence of any of five characters: space, comma, period, semi-colon, or colon. The cursor will move until it encounters one of those five characters or the end or beginning of the line. The five "tab" characters are contained in a table at line 5710, so you modify the list as you wish.

There are six different commands available to delete characters from the current line. The simplest is simply the DELETE key, which deletes the key to the left of the cursor. If the cursor is at the beginning of the line, the first character is deleted. Pressing the Open Apple with the DELETE key deletes the entire line. Pressing the Control-key with DELETE deletes from the cursor to the end of line. Control-Shift-DELETE scrubs everything from the left of the cursor to the beginning of the line. Option (or Solid-Apple) with DELETE causes my internal command buffer to be cleared. Finally, hitting the decimal point key on the numeric key pad with the Open-Apple key deletes the key under the cursor. Here they are in tabular format:

           DELETE       Delete char before cursor
           OA-DEL       Delete entire line
           C-DEL        Delete to end of line
           CS-DEL       Delete to beginning
           OP-DEL       Clear command buffer
           OA-PAD-"."   Delete char under cursor

That last one is there because of the program I use at work on my IBM AT. It has a DELETE CHAR key on the key pad decimal point, and INSERT TOGGLE key on the key pad "0" key. If you do not have a numeric key pad, change the equate line 1010 to "HAVE.PAD .EQ 0"; then it will assemble Open-Apple Period for the DELETE CHAR function, and Open-Apple Comma for the INSERT TOGGLE function.

Speaking of INSERT.... If you hold down the Open-Apple and type the "0" on the numeric key pad (or comma on the regular keyboard if you select the "HAVE.PAD .EQ 0" option), the cursor will be changed to a flashing "^". Then any normal characters you type will be inserted before the cursor. Typing the OA-PAD-0 again will toggle insert mode back off, and you will be back in the "replace" mode.

Key-Edit does not interfere with the other editing commands which are available in Applesoft and the S-C Macro Assembler, it supplements them. However, the ESCAPE key functions may work a little differently than you expect. I was not able to get them to work exactly as they should. Maybe you can do it.

Since Key-Edit uses the input hook, it can be disconnected by typing PR#3 (which engages both input and output hooks and turns on 40-columns), or any IN# command. Hitting RESET will reconnect it. Remember that the DOS buffers have been moved down to make space for Key-Edit. If you move them back up, be sure you also unhook the input vector change the RESET vector to no longer point into Key-Edit, as it will be G-O-N-E.

Lines 1210-1580 are the code which install Key-Edit. Lines 1210-1230 check to see if it is already installed, and if so just return without doing anything. Lines 1600-1870 are an alternate installation routine which I used during development. I deleted the .TF at line 1070, so that assembly was into RAM at $5000. Then the first time I tested Key-Edit I typed $5000G to install it. After subsequent patches and re-assembly, I typed MGOT to copy the new code into place. If you start making changes, you can use the same technique. In fact, you might want to change the "BEQ .6" at line 1230 to "BEQ T", to make it semi-automatic.

The command table (lines 2660-2870) uses a macro to simplify typing it in. The listing shows the macro expansion, so you can type them directly if you wish. The first byte of each four-byte entry is the ASCII value of the character. The second byte is the contents of the keyboard modfifier register, which is $C025 in the Apple IIgs. The eight bits of this byte tell you which modifier keys were pressed when the key was typed:

           bit 7:  Open-Apple
           bit 6:  Option (Solid Apple)
           bit 5:  (data updated without keypress)
           bit 4:  numeric key pad
           bit 3:  repeat active
           bit 2:  caps lock down
           bit 1:  control key down
           bit 0:  shift key down

I only look at bits 7, 6, 4, 1, and 0. If you modify this program for a //e or //c, you will have to change all code which accesses $C025 (called KEY.STATE in the program), because it doesn't exist in these older machines.

By modifying the keyboard command table and the insert-mode cursor, you could use Key-Edit on a //e or //c equipped with a 65802 processor. A little more work would eliminate the 65802-specific opcodes and let it run in a normal //c or enhanced //e with a 65C02 processor. In fact, I only used one opcode which is in the 65802 or 65816 and not in the 65C02, and I only used it one time: the TYX at line 5460. You could replace it with two lines: TYA and TAX. The insert-mode cursor would give a little more trouble, but you could just delete that code and leave the cursor alone. You have to modify the keyboard command table to use key combinations that are available and testable on the //e and //c. Then the PROCESS.CHAR subroutine would have to access the Open- and Solid-Apple information in a different way.

When I sent this program to AAL, it was nearly a full 3 pages plus the buffer and some patches inside DOS over the top of the INIT code. A few days later I thought of some changes and sent them on to AAL which shortened the code enough to eliminate the need for the patches inside DOS. However, the program as you see it here has been significantly revised by Bob Sander-Cederlof.

[Editor's note: Bob Boughner's code was good, but I just couldn't leave it alone. Blame any bugs you find on me! Hopefully you will be afflicted with the same impulse, and start modifying to your own taste.]

There is now room to add new features without expanding to more than a total of four pages. The end of code is currently at $9BA7, and you can go on up to $9BFF, so you have $58 (88 decimal) bytes left to play in. If you go too far, lines 5980-6000 will catch you and signal the fact when you try to assemble.

      900        .TI 76,Key Edit Program by Bob Boughner & Bob S-C......11-19-87.......
      1000        .LIST CON
      1010 HAVE.PAD   .EQ 0    =0 IF NO PAD, =1 IF PAD PRESENT
      1020        .OP 65816
      1030 *--------------------------------
      1040 * SAVE S.KEY.EDIT
      1050 *--------------------------------
      1060        .OR $5000
      1070        .TF KEY.EDIT
      1080 *--------------------------------
      1090 * VARIABLES NEEDED FOR LOADING
      1100 * KEY.EDIT
      1110 *--------------------------------
      1120 DOS.IO.HOOK         .EQ $3EA
      1130 BLD.DOS.BUFRS       .EQ $A7D4
      1140 DOS.BUFR.LOC        .EQ $9D00
      1150 KSWL                .EQ $38
      1160 KSWH                .EQ $39
      1170 COL80               .EQ $C300
      1180 MON.RESET           .EQ $3F2
      1190 PWRUP               .EQ $3F4
      1200 *--------------------------------
      1210 BGN    LDA /RESET.PTCH
      1220        CMP MON.RESET+1
      1230        BEQ .6       ALREADY SETUP
      1240 *---Copy BODY to $9900-9BFF------
      1250        LDY #0
      1260 .1     LDA IMAGE,Y
      1270        STA $9900,Y
      1280        LDA IMAGE+256,Y
      1290        STA $9A00,Y
      1300        LDA IMAGE+512,Y
      1310        STA $9B00,Y
      1320        INY
      1330        BNE .1
      1340 *---Clear command buffer---------
      1350        JSR CLEAR.BUFFER
      1360 *---Set up RESET vector----------
      1370        LDY #1
      1380 .5     LDA MON.RESET,Y   POINT MY RESET AT CURRENT
      1390        STA NORM.RESET,Y
      1400        LDA MY.RESET,Y    POINT RESET AT MY PATCH
      1410        STA MON.RESET,Y
      1420        DEY
      1430        BPL .5
      1440        LDA /RESET.PTCH^$A500   VALIDATE THE VECTOR
      1450        STA PWRUP
      1460 *---Drop DOS buffers 4 pages-----
      1470        SEC
      1480        LDA DOS.BUFR.LOC+1
      1490        SBC #4
      1500        STA DOS.BUFR.LOC+1
      1510        JSR BLD.DOS.BUFRS
      1520 *---Install my input hook--------
      1530        LDA #HOOK
      1540        LDY /HOOK
      1550        STA KSWL
      1560        STY KSWH
      1570        JSR DOS.IO.HOOK
      1580 .6     RTS
      1590 *--------------------------------
      1600 T
      1610 *---Copy BODY to $9900-9BFF------
      1620        LDY #0
      1630 .1     LDA IMAGE,Y
      1640        STA $9900,Y
      1650        LDA IMAGE+256,Y
      1660        STA $9A00,Y
      1670        LDA IMAGE+512,Y
      1680        STA $9B00,Y
      1690        INY
      1700        BNE .1
      1710 *---Clear command buffer---------
      1720        JSR CLEAR.BUFFER
      1730 *---Setup RESET Vector-----------
      1740        LDY #1
      1750 .5     LDA MY.RESET,Y    POINT RESET AT MY PATCH
      1760        STA MON.RESET,Y
      1770        DEY
      1780        BPL .5
      1790        LDA /RESET.PTCH^$A500   VALIDATE THE VECTOR
      1800        STA PWRUP
      1810 *---Install my input hook--------
      1820        LDA #HOOK
      1830        LDY /HOOK
      1840        STA KSWL
      1850        STY KSWH
      1860        JSR DOS.IO.HOOK
      1870 .6     RTS
      1880 *--------------------------------
      1890 MY.RESET .DA RESET.PTCH
      1900 *--------------------------------
      1910 *  VARIABLES AND CONSTANTS
      1920 *--------------------------------
      1930 MON.ADVANCE         .EQ $FBF4
      1940 MON.VTAB            .EQ $FC22
      1950 MON.RDKEY           .EQ $FD0C
      1960 MON.CLREOP          .EQ $FC42
      1970 MON.ESC             .EQ $FD2F
      1980 MON.COUT            .EQ $FDED
      1990 *--------------------------------
      2000 KEYIN.40            .EQ $FD1B
      2010 KEYIN.80            .EQ $C305
      2020 *--------------------------------
      2030 INBUF               .EQ $200
      2040 COL.STATE           .EQ $C01F
      2050 KEY.STATE           .EQ $C025
      2060 CV                  .EQ $25
      2070 CH40                .EQ $24
      2080 CH80                .EQ $57B
      2090 WNDWDTH             .EQ $21
      2100 WNDBTM              .EQ $23
      2110 *--------------------------------
      2120 IMAGE  .PH $9900
      2130 *--------------------------------
      2140 *   The input hook at KSWL,H branches here whenever
      2150 *      RDKEY is called.
      2160 *--------------------------------
      2170 HOOK   BRA .2            <<<MODIFIED TO SKIP OR NOT SKIP
      2180 .1     JMP TRUE.KEYIN             THIS JMP>>>
      2190 .2     CPX LNGTH         IS X POSITION GREATER THAN MY SAVED LENGTH?
      2200        BCC .3            NO. MUST BELONG TO ME
      2210        BNE .1            IF NOT EQUAL, THEN IT IS NOT MINE
      2220 *--------------------------------
      2230 .3     PHA               SAVE THE CURRENT SCRN CHAR
      2240        TXA               AT BEGINNING OF LINE?
      2250        BNE .5            NO.
      2260 *---Save line start position-----
      2270        LDA CV            GET POSITION OF LINE START AND SAVE
      2280        STA BOL
      2290        LDA CH40          ASSUME 40 COLUMNS
      2300        BIT COL.STATE     IS IT 40 OR 80 COLS?
      2310        BPL .4            ...40 COLUMNS
      2320        LDA CH80          ...80 COLUMMS
      2330 .4     STA BOC
      2340 .5     PLA               RETRIEVE SAVED SCREEN CHARACTER
      2350        JSR TRUE.KEYIN    GET A CHR FROM THE NORMAL INPUT ROUTINE
      2360        STZ HOOK+1        SWITCH TO LET MON.RDKEY FUNCTION
      2370 .6     JSR PROCESS.CHAR
      2380        JSR MON.RDKEY
      2390        BRA .6            NORMAL CHARS BUST THE LOOP
      2400 *--------------------------------
      2410 PROCESS.CHAR
      2420        STA CURRCHAR
      2430        LDY #-4
      2440 .1     INY
      2450        INY
      2460        INY
      2470        INY
      2480        LDA CMDTBL,Y
      2490        BEQ .2       ...END OF CMDTBL
      2500        CMP CURRCHAR
      2510        BNE .1       ...TRY NEXT ENTRY
      2520        LDA KEY.STATE
      2530        AND #%11010011    ONLY OA,SA,PAD,CTRL,SHIFT
      2540        CMP CMDTBL+1,Y
      2550        BNE .1       ...TRY NEXT ENTRY
      2560 .2     LDA CMDTBL+3,Y
      2570        PHA
      2580        LDA CMDTBL+2,Y
      2590        PHA
      2600        RTS
      2610 *--------------------------------
      2620        .MA CMD
      2630        .DA #$]1,#$]2,]3-1
      2640        .EM
      2650 *--------------------------------
      2660 CMDTBL
      2670   >CMD 88,00,BAKSPC      LEFT ARROW
      2680   >CMD 88,80,LINE.START  OA-LEFT ARROW
      2690   >CMD 95,00,FORWD       RIGHT ARROW
      2700   >CMD 95,80,END.OF.LINE OA-RIGHT ARROW
      2710   >CMD FF,00,DELCHR      DELETE
      2720   >CMD FF,80,DELALL      OA-DELETE
      2730   >CMD FF,02,DELEOL      CTRL-DELETE
      2740   >CMD FF,03,DELBOL      CTRL-SHIFT-DELETE
      2750   >CMD FF,40,CLEAR.BUFFER  SA-DELETE
      2760   .DO HAVE.PAD
      2770   >CMD AE,90,DELCUR      OA-PAD-"."
      2780   >CMD B0,90,INS.TOG     OA-PAD-"0"
      2790   .ELSE
      2800   >CMD AE,80,DELCUR      OA-"."
      2810   >CMD AC,80,INS.TOG     OA-","
      2820   .FIN
      2830   >CMD 8B,00,UP          UP ARROW
      2840   >CMD 8A,00,DOWN        DOWN ARROW
      2850   >CMD 89,00,TAB.FWD     TAB
      2860   >CMD 89,80,TAB.BAK     OA-TAB
      2870   >CMD 00,00,NORM.CHR   any other
      2880 *--------------------------------
      2890 BAKSPC TXA               AT LINE START?
      2900        BEQ RTS.1         YES, GET THE NEXT CHR
      2910        DEX               NO, BACKUP ONE SPACE
      2920        LDA #$88     PRINT A BACKSPACE
      2930 COUT.1 JMP MON.COUT
      2940 RTS.1  RTS
      2950 *--------------------------------
      2960 FORWD  CPX LNGTH         ALREADY AT END OF LINE?
      2970        BCS RTS.1         ...YES
      2980        INX               ...NO, ADVANCE
      2990        LDA #$9C          PRINT $9C TO SPACE FORWARD
      3000        BIT COL.STATE     80- OR 40-COLUMNS?
      3010        BMI COUT.1        ...80-COLUMNS
      3020        JMP MON.ADVANCE   ...40-COLUMNS
      3030 *--------------------------------
      3040 DELCHR JSR BAKSPC       Delete char to left of cursor
      3050 DELCUR JSR MON.CLREOP    Delete char under cursor
      3060        LDA LNGTH
      3070        BEQ .2
      3080        PHX
      3090 .1     INX
      3100        CPX LNGTH
      3110        BCS .3
      3120        LDA INBUF,X       MOVE INBUF DOWN BY ONE
      3130        STA INBUF-1,X
      3140        JSR MON.COUT
      3150        BRA .1
      3160 .3     PLX               RESTORE CURSOR POSITION ON SCREEN
      3170        JSR CURSOR.POSN
      3180        DEC LNGTH
      3190 .2     RTS
      3200 *--------------------------------
      3210 DELBOL CPX LNGTH    If at eol, delete entire line
      3220        BCS DELALL
      3230        PHX               SAVE LOCAL POSITION WITHIN INBUF
      3240        JSR LINE.START    GO TO BEGINNING OF LINE
      3250        PLY               (Y) points at remaining chars
      3260 .1     LDA INBUF,Y       MOVE INBUF DOWN TO BEGINNING OF BUFFER
      3270        STA INBUF,X
      3280        JSR MON.COUT      AND WRITE TO SCREEN
      3290        INY
      3300        INX
      3310        CPY LNGTH
      3320        BCC .1
      3330        JSR DELEOL        LOP OFF THE REST
      3340 LINE.START
      3350        LDX #0             INDICATE BEGINNING OF INBUF
      3360        JMP CURSOR.POSN
      3370 *--------------------------------
      3380 DELALL JSR LINE.START    Delete entire line
      3390 DELEOL STX LNGTH         Delete from cursor to eol
      3400        JMP MON.CLREOP    CLEAR TO END OF WINDOW
      3410 *--------------------------------
      3420 INS.TOG
      3430        LDY CURSOR   SWAP THE CURSORS
      3440        LDA $E10134       CURRENT ACTIVE CURSOR
      3450        STA CURSOR        SAVE IT
      3460        TYA               PREVIOUS CURSOR
      3470        STA $E10134       START USING IT AGAIN
      3480        LDA INS.FLAG      TOGGLE THE FLAG
      3490        EOR #$80
      3500        STA INS.FLAG
      3510        RTS
      3520 *--------------------------------
      3530 *   Select stored input line from buffer
      3540 *      by scanning forward in time
      3550 *--------------------------------
      3560 DOWN   JSR PREPARE.BUFFER.SEARCH
      3570        BPL RTS.2    Buffer is empty
      3580        DEY
      3590 .1     INY          SEARCH FOR "00"
      3600        LDA BUFFER,Y
      3610        BNE .1
      3620 .2     INY          SEARCH FOR NON-ZERO
      3630        LDA BUFFER,Y
      3640        BEQ .2
      3650        JSR CBTB.1   STORE CHAR AND COPY REST OF CMND
      3660        STY WHERE
      3670        JMP CURSOR.POSN    RTN WITH CURSOR AT LINE END, CHK ADJUSTMENT
      3680 *--------------------------------
      3690 *   Select stored input line from buffer
      3700 *      by scanning backward in time.
      3710 *--------------------------------
      3720 UP     JSR PREPARE.BUFFER.SEARCH
      3730        BPL RTS.2    Buffer is empty
      3740        INY
      3750 .1     DEY          BACKUP TO NON-ZERO
      3760        LDA BUFFER,Y
      3770        BEQ .1
      3780 .2     DEY          BACKUP TO "00"
      3790        LDA BUFFER,Y
      3800        BNE .2
      3810        STY WHERE
      3820        JSR CBTB.2   COPY COMMAND TO INBUF
      3830        JMP CURSOR.POSN    RTN WITH CURSOR AT LINE END, CHK ADJUSTMENT
      3840 *--------------------------------
      3850 PREPARE.BUFFER.SEARCH
      3860        JSR LINE.START    GO TO BEGINNING OF LINE
      3870        JSR MON.CLREOP    CLEAR THE LINE
      3880        LDY WHERE         GET LAST POSITION IN BUFFER
      3890        BIT BUF.FLAG      ANYTHING IN BUFFER?
      3900 RTS.2  RTS
      3910 *--------------------------------
      3920 CBTB.1 STA INBUF,X
      3930        JSR MON.COUT
      3940        INX
      3950 CBTB.2 INY                COPY BUFFER TO INPUT BUFFER AND
      3960        LDA BUFFER,Y       DISPLAY ON SCREEN
      3970        BNE CBTB.1
      3980        STX LNGTH          SAVE TOTAL LINE LENGTH
      3990        RTS
      4000 *--------------------------------
      4010 TAB.FWD
      4020 .1     CPX LNGTH          ELSE, MOVE FORWARD IF NOT AT LINE END
      4030        BCS NEWPOS
      4040        INX
      4050        JSR COMPARE.TAB.CHARS
      4060        BCC .1             NO. GET THE NEXT INBUF CHAR
      4070 NEWPOS JMP CURSOR.POSN    YES. CALC NEW POSITION OF CURSOR
      4080 *--------------------------------
      4090 TAB.BAK
      4100 .1     TXA                TAB BACKWARD IF NOT AT LINE BEGINNING
      4110        BEQ NEWPOS
      4120        DEX
      4130        JSR COMPARE.TAB.CHARS
      4140        BCC .1
      4150        BCS NEWPOS
      4160 *--------------------------------
      4170 NORM.CHR
      4180        PLA          POP A RETURN ADDRESS
      4190        PLA
      4200        JSR DRCT.OFF
      4210        LDA CURRCHAR      GET INPUT CHAR
      4220        PHA                SAVE CHR FOR LATER CODE
      4230        CMP #$A0     IS IT A CONTROL CHAR?
      4240        BCS .2       ...NO
      4250        CMP #$8D     CARRIAGE RETURN?
      4260        BNE .0
      4270        JSR MOVE.TO.BUFFER
      4280        JSR END.OF.LINE
      4290 .0     BIT INS.FLAG       INSERTION MODE ON?
      4300        BPL .1             NO.
      4310        JSR INS.TOG        YES, TOGGLE INSERT MODE OFF
      4320 .1     STZ LNGTH          CLEAR TOTAL LINE LENGTH
      4330        PLA
      4340        CMP #$9B           ESC CHARACTER?
      4350        BNE .5
      4360 *---Handle ESC-------------------
      4370         STZ HOOK+1        SET CODE FOR PASS THRU WHILE IN 'ESC' MODE
      4380         JSR MON.ESC       LET MONITOR HANDLE ESCAPE MOVES
      4390         PHA               SAVE CHR ON THE STACK
      4400         JSR DRCT.OFF      RESET SET CODE TO CHK EACH CHR
      4410         ASL KEY.STATE     MOVE OPEN APPLE STATUS TO CARRY
      4420         BCS .4      AND RTN IF SET
      4430         LDA #" "          ELSE, INSERT A SPACE INTO INBUF
      4440         STA INBUF,X
      4450         INX               AND INCREMENT POSITION SO THAT NEXT TIME THRU
      4460 *                         KEY.EDIT WILL IGNORE THE LINE
      4470         BRA .4
      4480 .2     ASL KEY.STATE      MOVE STATUS OF OPEN APPLE KEY TO CARRY
      4490        BCS .4       IF SET, THEN RTN NOW
      4500        BIT INS.FLAG       INSERTION MODE ON?
      4510        BMI INS.CHR        YES. GO HANDLE IT
      4520        CPX LNGTH          NO. INC LENGTH IF AT END.
      4530        BCC .4
      4540        JSR CURSOR.POSN    POSITION CURSOR AT LINE END AND CHK
      4550 *                         ADJUSTMENT FOR BTM OF WINDOW
      4560        INC LNGTH
      4570 .4     PLA                GET CHAR FROM STACK AND RTN
      4580 .5     RTS
      4590 *--------------------------------
      4600 * This portion handles character insertions
      4610 * while the insert flag is on.
      4620 *--------------------------------
      4630 INS.CHR
      4640        PLY               GET CHR FROM STACK INTO Y-REG
      4650        PHY               LEAVE ON STACK TOO
      4660        PHX               SAVE LOCAL POSITION WITHIN INBUF
      4670        INC LNGTH         INCREASE LINE LENGTH BY ONE
      4680 .1     TYA               INSERT CHAR IN INBUF
      4690        LDY INBUF,X       GET CURRENT CHAR
      4700        STA INBUF,X       PUT NEW CHAR
      4710        JSR MON.COUT      AND DISPLAY ON SCREEN
      4720        INX               MOVE ON DOWN THE LINE
      4730        CPX LNGTH
      4740        BCC .1            MORE TO GO...
      4750        JSR CURSOR.POSN   ADJUSTMENT NEEDED FOR BEING NEAR WINDOW BTM?
      4760        PLX               RESET POSITION IN INBUF
      4770        JSR CURSOR.POSN   RESET CURSOR TO ITS ORIGINAL POSITION
      4780        PLA               INSERTED CHARACTER
      4790        RTS
      4800 *--------------------------------
      4810 END.OF.LINE
      4820        LDX LNGTH          CALCULATE OFFSET FROM LINE START
      4830 *--------------------------------
      4840 *   (X)=position in INBUF
      4850 *   Compute screen line and column for current position
      4860 *      and position cursor there.
      4870 *   If that is below window, adjust BOL accordingly and
      4880 *      position to bottom line.
      4890 *--------------------------------
      4900 CURSOR.POSN
      4910        LDY BOL      GET ROW OF LINE START
      4920        CLC          virtual screen position = BOC+X
      4930        TXA
      4940        ADC BOC
      4950 *---Adjust for window width------
      4960 .1     CMP WNDWDTH
      4970        BCC .2       THIS IS THE LINE
      4980        SBC WNDWDTH
      4990        INY          MOVE DOWN ONE LINE
      5000        BRA .1
      5010 *---HTAB to position-------------
      5020 .2     STA CH80
      5030        BIT COL.STATE     In 80-column mode?
      5040        BMI .3            ...yes
      5050        STA CH40          ...no, store in 40-col CH
      5060 *---Adjust if below window-------
      5070 .3     CPY WNDBTM
      5080        BCC .4       ON THE SCREEN NOW
      5090        DEC BOL      ADJUST BEGINNING OF LINE ROW NUMBER
      5100        DEY
      5110        BNE .3
      5120 *---VTAB to line-----------------
      5130 .4     STY CV
      5140        JMP MON.VTAB       SET NEW LINE ROW VALUE
      5150 *--------------------------------
      5160 DRCT.OFF
      5170        LDA #3
      5180        STA HOOK+1
      5190        RTS
      5200 *--------------------------------
      5210 CLEAR.BUFFER
      5220        LDY #0             ZERO CONTENTS OF STORAGE BUFFER
      5230        TYA
      5240 .1     STA BUFFER,Y
      5250        INY
      5260        BNE .1
      5270        STA BUF.FLAG       INDICATE NO BUFFER CONTENTS
      5280        RTS
      5290 *--------------------------------
      5300 MOVE.TO.BUFFER
      5310        LDA LNGTH         ANY CHARACTERS IN INBUF?
      5320        BEQ .3            ...NO, RETURN NOW
      5330        PHX                YES. SAVE POSITION WITHIN INBUF
      5340        LDY TOP            MOVE INBUF TO STORAGE BUFFER
      5350        LDX #0
      5360 .1     INY                POINT TO NEXT LOCATION IN BUFFER
      5370        LDA INBUF,X        MOVE INBUF AND PLACE ON TOP
      5380        STA BUFFER,Y
      5390        INX
      5400        CPX LNGTH
      5410        BCC .1
      5420        STA BUF.FLAG       TURN BUFFER FLAG ON
      5430        INY
      5440        STY TOP            MARK NEW POSITION OF TOP
      5450        STY WHERE          AND WHERE WE START AGAIN
      5460        TYX
      5470 .2     STZ BUFFER,X       ZERO OUT ANY RESIDUAL CMNDS
      5480        INX
      5490        LDA BUFFER,X
      5500        BNE .2
      5510        PLX
      5520 .3     RTS
      5530 *--------------------------------
      5540 TRUE.KEYIN
      5550        ASL COL.STATE     40- OR 80-COLUMNS?
      5560        ROR KYBRD         SAVE ANSWER IN KEYBOARD STORAGE BYTE
      5570        BMI .1       ...80
      5580        JMP KEYIN.40
      5590 .1     JMP KEYIN.80
      5600 *--------------------------------
      5610 COMPARE.TAB.CHARS
      5620        LDA INBUF,X       GET CURRENT CHAR FROM LINE
      5630        LDY #TAB.SZ-1     NUMBER OF TAB CHARACTERS
      5640 .1     CMP TAB.CHARS,Y
      5650        BEQ .2            IF THEY ARE THE SAME, RTN WITH CARRY SET
      5660        DEY               ELSE GO CHK THE NEXT CHAR
      5670        BPL .1            ...MORE IN LIST
      5680        CLC               NO TAB CHARACTERS MATCH SO CLEAR CARRY AND
      5690 .2     RTS                RETURN TO CALLER
      5700 *--------------------------------
      5710 TAB.CHARS    .AS -" ,.;:"
      5720 TAB.SZ .EQ *-TAB.CHARS
      5730 *--------------------------------
      5740 *   COMES HERE DURING PROCESSING OF "RESET"
      5750 *--------------------------------
      5760 RESET.PTCH
      5770        JSR DRCT.OFF
      5780        BIT KYBRD    WAS I IN 80-COLUMN?
      5790        BPL .1       ...NO
      5800        JSR COL80    ...YES
      5810 .1     STZ KSWL     HOOK MYSELF IN
      5820        LDA /HOOK
      5830        STA KSWH
      5840        JMP $3D0     FILLED IN BY INIT CODE
      5850 NORM.RESET .EQ *-2
      5860 *--------------------------------
      5870 KYBRD      .DA #0
      5880 BOC        .BS 1
      5890 BOL        .BS 1
      5900 LNGTH      .DA #0
      5910 INS.FLAG   .DA #0
      5920 BUF.FLAG   .DA #0
      5930 TOP        .DA #0
      5940 WHERE      .DA #0
      5950 CURSOR     .AS -/^/
      5960 CURRCHAR   .BS 1
      5970 *--------------------------------
      5980        .DO *>$9BFF
      5990 ...ERROR:  KEY.EDIT IS LONGER THAN 3 PAGES...
      6000        .ELSE
      6010 BUFFER     .EQ $9C00
      6020        .FIN
      6030 *--------------------------------
      6040        .EP

How to Clear the Back-Up Bit | Bob Sander-Cederlof

I received a letter from Paul R. Santa-Maria today, with a very good question: "How is the backup bit in the file access byte cleared in ProDOS 8?" Paul is writing a program that can use the backup bit, but he needs to be able to clear it.

The information about this bit in the various reference manuals is contradictory and incomplete. Apple's ProDOS Technical Reference Manual (even the new ProDOS-8 edition) says:

ProDOS sets bit 5, the backup bit, of the access field to 1 whenever the file is changed (that is, after a CREATE, RENAME, CLOSE after WRITE, or SET_FILE_INFO operation). This bit should be reset to 0 whenever the file is duplicated by a backup program.

Note: ONly ProDOS may change bits 2-4; only backup programs should clear bit 5, using SET_FILE_INFO.

As Paul pointed out in his letter, these two paragraphs contradict each other. Other references to "backup bit" listed in the index did not clear up the difficulty.

Paul noticed that one of the bytes in the System Global Page is called BUBIT (at $BF95). The only explanation of this bit is that it can be changed before MLI calls, and a comment "BACKUP BIT DISABLE, SETFILEINFO ONLY".

Neither of us could find any further information in Apple's manuals, or even in the various third-party books.

I did get some help from the supplement to "Beneath Apple ProDOS", and also from my Apple itself. First I did a search of the ProDOS code while it was in RAM and found two references to $BF95, at $DE7A and at $F7EF. (These are the addresses in Version 1.1.1, and are slightly different from the addresses in Version 1.2, 1.3, and 1.4.) The first reference is at the general exit from all MLI calls, and it stores a zero at $BF95 (BUBIT). The second is inside the SET FILE INFO processor. Here is a piece of the code:

       F7EF-  LDA BUBIT
              EOR #$20
              AND $FE7D       CURRENT ACCESS BITS
              AND #$20        ISOLATE BACKUP BIT
              STA $FEB4

According to the BAP Supplement, $FEB4 is later ORed into the Access Bits, immediately before the update is complete.

Apparently the steps necessary to clear the backup bit are:

1. read the current file information using GET FILE INFO;
2. clear the backup bit in the access byte and set at least bit 5 of $BF95 to 1;
3. and use SET FILE INFO to install the change.

I wrote a test program to perform those steps, and it worked!

My program displays some information, so that I can see what it has done. Line 1170 reads the current file info and displays it in hex. The first byte displayed is the byte with the access bits. Lines 1180-1200 clear bit 5, the backup bit, in the access byte. Line 1210 changes BUBIT ($BF95) from $00 to $FF, so that SET FILE INFO will not set the backup bit. Lines 1220-1240 call MLI to SET FILE INFO. Finally, lines 1260-1380 read the file info and display it again, to see if it worked.

To make my test program simple, I assembled the pathname of a file I knew was on the mounted volume. The pathname is in line 1480. You should substitute here the name of the file you really want to play with.

By the way, there is another way to clear the backup bit. You can read and write directory sectors directly, using the READ_BLOCK and WRITE_BLOCK calls. If you are writing a super snazzy backup program, you may want to do it this way. It can be easier to follow the directory tree using such direct access.

      1000 *SAVE CLEAR.BUBIT
      1010 *--------------------------------
      1020 MLI    .EQ $BF00
      1030 BUBIT  .EQ $BF95
      1040 *--------------------------------
      1050 BELL   .EQ $FBDD
      1060 CROUT  .EQ $FD8E
      1070 PRBYTE .EQ $FDDA
      1080 COUT   .EQ $FDED
      1090 *--------------------------------
      1100        .MA MLI
      1110        JSR MLI
      1120        .DA #]1,]2
      1130        BCS ERROR
      1140        .EM
      1150 *--------------------------------
      1160 CLEAR.BUBIT
      1170        JSR GET.FILE.INFO.AND.DISPLAY.IT
      1180        LDA INFO+3
      1190        AND #$DF          CLEAR BACKUP BIT
      1200        STA INFO+3
      1210        DEC BUBIT         BUBIT = $FF
      1220        LDA #$07
      1230        STA INFO
      1240        >MLI $C3,INFO     SET INFO, CLEARING BUBIT
      1250 *--------------------------------
      1260 GET.FILE.INFO.AND.DISPLAY.IT
      1270        LDA #$0A
      1280        STA INFO
      1290        >MLI $C4,INFO     READ AND DISPLAY NEW INFO
      1300        LDY #3
      1310 .1     LDA INFO,Y
      1320        JSR PRBYTE
      1330        LDA #"."
      1340        JSR COUT
      1350        INY
      1360        CPY #18
      1370        BCC .1
      1380        JMP CROUT
      1390 *--------------------------------
      1400 ERROR  JSR PRBYTE
      1410        JMP BELL
      1420 *--------------------------------
      1430 INFO   .HS 0A
      1440        .DA PATH
      1450        .BS 15
      1460 *--------------------------------
      1470 PATH   .DA #LEN
      1480        .AS /PRODOS/
      1490 LEN    .EQ *-PATH-1
      1500 *--------------------------------

Sean Nolan's Proposed Setup File Standard | Bob Sander-Cederlof

Sean Nolan has written a very significant program, and released it to the public domain in the November 1987 issue of Call APPLE. SETUP.SYSTEM is a ProDOS-8 program to give startup features similar to those available in ProDOS-16.

The normal ProDOS-8 boot sequence simply installs the ProDOS image and then loads and runs the first type SYS file found in the main directory whose name ends with ".SYSTEM". Apple puts BASIC.SYSTEM (Applesoft) there, and I put the S-C Macro Assembler (SCASM.SYSTEM) there.

If you install SETUP.SYSTEM as the first SYStem file, it will gain control right after ProDOS is loaded. SETUP.SYSTEM scans the directory for a subdirectory named SETUPS. If one is found, all of the type SYS and type BIN files in that subdirectory will be executed, in the order found in the subdirectory. After all of those files have been executed, SETUP.SYSTEM will go back to the main directory and start up the first SYStem file which follows SETUP.SYSTEM.

I got kind of excited about this program, and took several hours to type it in. I installed it in my RamFactor card, and put PRODRIVE in the SETUPS directory. I have a non-standard clock-calendar card, so I also put a program called FIX.CLOCK in SETUPS which patches ProDOS so it can deal with my clock. You could put all kinds of neat things in there. Sean suggests Bill Basham's Diversi-Cache and Diversi-Hack. The requirements are few:

1. Programs must not touch RAM between $BD00 and BEFF.
2. BIN programs must end with an RTS.
3. SYS programs must end with a QUIT call.
4. Programs must not go past $B8FF during loading.

I think you will find Sean's program very useful. He suggests developers start using it, without modification so as to maintain compatibliity. Since he put it in the public domain, he has made it fairly easy. I can't list the program here, because it has already been published in Call APPLE. However, I did include the source code on the AAL Monthly Disk for October. I will also list the 512 bytes in hexadecimal here, so you can punch it in the hard way if you want to.

I have printed a checksum for every row of 16 bytes. Of course you don't type in the checksum. Instead, run the program below after typing in all of the bytes. If any of the row checksums is wrong, you know you made a mistake in that row. Sean set his version up with a checksum balancer at the end for the rest of the 512 bytes, so you can check for errors by using the second checksumming program below too. It should give a result of "00" if all the bytes are correct.

Since writing this article, I have discovered that ProDOS-8 (versions 1.3 and later) has a new "secret" feature: before loading and executing the first type "SYS" file named "anything.SYSTEM" it searches the main directory for a type $E2 file named "ATINIT". If ATINIT is there it is loaded at $2000 and called with a JSR. You could BSAVE Sean's program as a type $E2 file named "ATINIT" and save the trouble of making it first in the directory. I haven't tried it, but I think that would work without making any changes to his program at all.

[ For this electronic edition, I have included Sean's program after all.]

      1000  .LIF
      1010 *SAVE S.SETUP.SYSTEM
      1020 *--------------------------------
      1030 *      SETUP.SYSTEM by Sean Nolan
      1040 *   --------------------------------
      1050 *   A Proposed Startup File Standard
      1060 *
      1070 *   Published in Call APPLE, November, 1987
      1080 *   This program is in the public domain.
      1090 *
      1100 *   Converted to S-C Macro Assembler Format
      1110 *   by Bob Sander-Cederlof
      1120 *
      1130 *--------------------------------
      1140        .OR $BD00
      1150        .TA $2000
      1160 *--------------------------------
      1170        .MA MLI
      1180        JSR PRODOS
      1190        .DA #]1,]2
      1200        .EM
      1210 *--------------------------------
      1220 CH         .EQ $24
      1230 *--------------------------------
      1240 IN2        .EQ $280
      1250 FILETYPE   .EQ IN2+16
      1260 AUXCODE    .EQ IN2+31
      1270 *--------------------------------
      1280 RESET      .EQ $3F2
      1290 *--------------------------------
      1300 IOBUFFER   .EQ $B900
      1310 *---System Global Page-----------
      1320 PRODOS     .EQ $BF00
      1330 QUITVECT   .EQ $BF03
      1340 DEVNUM     .EQ $BF30
      1350 BITMAP     .EQ $BF58
      1360 *---Monitor Subroutines----------
      1370 INIT       .EQ $FB2F
      1380 VTABZ      .EQ $FC24
      1390 HOME       .EQ $FC58
      1400 RDKEY      .EQ $FD0C
      1410 SETVID     .EQ $FE93
      1420 SETKBD     .EQ $FE89
      1430 SETNORM    .EQ $FE84
      1440 *--------------------------------
      1450 VOLNAME
      1460        LDX #1
      1470        STX BITMAP+23
      1480        DEX
      1490 .1     LDA $2000,X
      1500        STA $BD00,X
      1510        LDA $2100,X
      1520        STA $BE00,X
      1530        INX
      1540        BNE .1
      1550        DEX
      1560        TXS
      1570        JMP ENTER
      1580 *--------------------------------
      1590 DIRNAME
      1600        .DA #6
      1610        .AS -/SETUPS/
      1620 *--------------------------------
      1630 ENTER
      1640        LDA DEVNUM
      1650        STA ONLINEN
      1660        >MLI $C5,ONLINEP
      1670        LDA VOLNAME+1
      1680        AND #$0F
      1690        TAX
      1700        INX
      1710        STX VOLNAME
      1720        LDA #'/'
      1730        STA VOLNAME+1
      1740        LDA QUITVECT+1
      1750        STA QUITMOD1+1
      1760        LDA QUITVECT+2
      1770        STA QUITMOD2+1
      1780 *--------------------------------
      1790 MAINLOOP
      1800        LDX #2
      1810 .1     LDA JUMP+1,X
      1820        STA RESET,X
      1830        LDA JUMP,X
      1840        STA QUITVECT,X
      1850        DEX
      1860        BPL .1
      1870        TXS
      1880        JSR CLOSE
      1890 *--------------------------------
      1900        LDX #23
      1910        LDA #0
      1920 .2     STA BITMAP,X
      1930        DEX
      1940        BPL .2
      1950        LDA #$CF
      1960        STA BITMAP
      1970        LDA #$07
      1980        STA BITMAP+23
      1990 *--------------------------------
      2000        LDA $C082    LANGUAGE CARD OFF
      2010        STA $C00C    40-COL
      2020        STA $C00E    NORM CHAR SET
      2030        STA $C000    80STORE OFF
      2040        JSR SETNORM
      2050        JSR INIT
      2060        JSR SETVID
      2070        JSR SETKBD
      2080 *--------------------------------
      2090 .3     JSR HOME
      2100        >MLI $C6,PFX2P
      2110        BCC .6       ...VOLUME IS HERE
      2120        LDX #13
      2130 .4     LDA VOLTEXT-1,X
      2140        STA $5A8+4,X
      2150        DEX
      2160        BNE .4
      2170 .5     LDA VOLNAME+1,X
      2180        ORA #$80
      2190        STA $5A8+19,X
      2200        INX
      2210        CPX VOLNAME
      2220        BCC .5
      2230        LDA #35
      2240        STA CH
      2250        LDA #11
      2260        JSR VTABZ
      2270        JSR RDKEY
      2280        JMP .3
      2290 *--------------------------------
      2300 .6     JSR NEXTFILE
      2310        BCS EXITLOOP
      2320 *--------------------------------
      2330        >MLI $C6,PFX1P
      2340        JSR READFILE
      2350 JUMP   JMP MAINLOOP
      2360        .DA /JUMP^$A500
      2370 *--------------------------------
      2380 EXITLOOP
      2390        INC RESET+2
      2400 QUITMOD1   LDA #0
      2410        STA QUITVECT+1
      2420 QUITMOD2   LDA #0
      2430        STA QUITVECT+2
      2440 *--------------------------------
      2450        LDA #0
      2460        STA NUMBER+1
      2470        STA CHEKTYPE+1
      2480        LDA #VOLNAME
      2490        STA NAMEPTR
      2500 .1     JSR NEXTFILE
      2510        BCS .4       ...QUIT
      2520        LDX IN2
      2530        LDY #6
      2540 .2     LDA IN2,X
      2550        CMP SYSTEXT,Y
      2560        BNE .1
      2570        DEX
      2580        DEY
      2590        BPL .2
      2600        INC .3+1
      2610 .3     LDA #$FF
      2620        BEQ .1
      2630        JSR READFILE
      2640 .4     >MLI $65,QUITP
      2650 SYSTEXT    .AS /.SYSTEM/
      2660 *--------------------------------
      2670 NEXTFILE
      2680        >MLI $C8,OPENP
      2690        BCS CLOSE
      2700        LDA OPENN
      2710        STA MARKN
      2720        STA READN
      2730        >MLI $CA,READP
      2740        BCS CLOSE
      2750        LDA IN2+35
      2760        STA ENTSIZE+1
      2770        LDA IN2+36
      2780        STA ENTRIES+1
      2790 NEXTENT
      2800        INC NUMBER+1
      2810 NUMBER LDA #0
      2820        LDX #$FE
      2830 LOOP5  INX
      2840        INX
      2850 ENTRIES    CMP #13
      2860        BCC .1
      2870        SBC ENTRIES+1
      2880        BCS LOOP5
      2890 .1     TAY
      2900        LDA #4
      2910 LOOP10 DEY
      2920        BMI OK2
      2930        CLC
      2940 ENTSIZE ADC #39
      2950        BCC LOOP10
      2960        INX
      2970        BNE LOOP10
      2980 OK2    STA MARK
      2990        STX MARK+1
      3000        >MLI $CE,MARKP
      3010        BCS CLOSE
      3020        >MLI $CA,READP
      3030        BCS CLOSE
      3040        LDA IN2
      3050        BEQ NEXTENT
      3060        AND #$0F
      3070        STA IN2
      3080        LDA FILETYPE
      3090        EOR #$FF
      3100        BEQ CLOSE
      3110 CHEKTYPE
      3120        EOR #$06^$FF
      3130        BNE NEXTENT
      3140 CLOSE  PHP
      3150        >MLI $CC,CLOSEP
      3160        PLP
      3170 ANRTS  RTS
      3180 *--------------------------------
      3190 READFILE
      3200        LDX FILETYPE
      3210        LDA #$20
      3220        INX
      3230        BEQ SETDEST
      3240        LDX AUXCODE
      3250        LDA AUXCODE+1
      3260 SETDEST
      3270        STX READ2D
      3280        STA READ2D+1
      3290        >MLI $C8,OPEN2P
      3300        BCS CLOSE
      3310        LDA OPEN2N
      3320        STA READ2N
      3330        >MLI $CA,READ2P
      3340        JSR CLOSE
      3350        BCS ANRTS
      3360        JMP (READ2D)
      3370 *--------------------------------
      3380 ONLINEP .HS 02
      3390 ONLINEN .BS 1
      3400        .DA VOLNAME+1
      3410 *--------------------------------
      3420 PFX1P  .DA #1,DIRNAME
      3430 PFX2P  .DA #1,VOLNAME
      3440 QUITP  .DA #4,0,0,0
      3450 CLOSEP .DA #1,#0
      3460 *--------------------------------
      3470 OPENP  .DA #3
      3480 NAMEPTR .DA DIRNAME
      3490        .DA IOBUFFER
      3500 OPENN  .BS 1
      3510 *--------------------------------
      3520 MARKP  .DA #2
      3530 MARKN  .BS 1
      3540 MARK   .BS 3
      3550 *--------------------------------
      3560 READP  .DA #4
      3570 READN  .BS 1
      3580        .DA IN2,39,0
      3590 *--------------------------------
      3600 OPEN2P .DA #3,IN2,IOBUFFER
      3610 OPEN2N .BS 1
      3620 *--------------------------------
      3630 READ2P .DA #4
      3640 READ2N .BS 1
      3650 READ2D .DA 0,$B900-$800,0
      3660 *--------------------------------
      3670 VOLTEXT .AS -/INSERT VOLUME/
      3680 *--------------------------------
      3690        .HS E8
      3700 END
      3710 *--------------------------------
      3720        .OR $800
      3730 CS     LDX #0
      3740        TXA
      3750 .1     EOR $2000,X
      3760        INX
      3770        BNE .1
      3780 .2     EOR $2100,X
      3790        INX
      3800        BNE .2
      3810        JSR $FDDA
      3820        RTS

Here is the checksummer program.

      1000 *SAVE S.CHECKSUMMER
      1010 *--------------------------------
      1020 *   Two CHECKSUM programs for testing your
      1030 *   entry of the SETUP.SYSTEM file.  First
      1040 *   BLOAD SETUP.SYSTEM,TSYS,A$2000, and then
      1050 *   execute either CHECKSUM program below.
      1060 *   If you use CS1, compare your results to
      1070 *   those printed in the newsletter.  If you
      1080 *   use CS2, the single result should be 00.
      1090 *--------------------------------
      1100 PNTR   .EQ $00,01
      1110 *--------------------------------
      1120 CROUT  .EQ $FD8E
      1130 PRBYTE .EQ $FDDA
      1140 COUT   .EQ $FDED
      1150 *--------------------------------
      1160 *   CHECKSUM 16 BYTES AT A TIME
      1170 *--------------------------------
      1180 CS1
      1190        LDA #$2000   POINT TO FIRST PAGE TO BE SUMMED
      1200        STA PNTR
      1210        LDA /$2000
      1220        STA PNTR+1
      1230 *--------------------------------
      1240 .1     JSR CROUT    START A NEW LINE
      1250        LDA PNTR+1   PRINT ADDRESS "XXXX-"
      1260        JSR PRBYTE
      1270        LDA PNTR
      1280        JSR PRBYTE
      1290        LDA #"-"
      1300        JSR COUT
      1310        LDY #0       FOR Y = 0 TO 15
      1320 .2     LDA (PNTR),Y      PRINT BYTE AS "XX "
      1330        JSR PRBYTE
      1340        LDA #" "
      1350        JSR COUT
      1360        INY          NEXT Y
      1370        CPY #16
      1380        BCC .2
      1390 *--------------------------------
      1400        JSR COUT     PRINT " ("
      1410        LDA #"("
      1420        JSR COUT
      1430        DEY          Y=15
      1440        LDA #0       FOR Y = 15 TO 0
      1450 .3     EOR (PNTR),Y      SUM = SUM.EOR.BYTE(Y)
      1460        DEY          NEXT Y
      1470        BPL .3
      1480        JSR PRBYTE   PRINT "XX)"
      1490        LDA #")"
      1500        JSR COUT
      1510 *--------------------------------
      1520        CLC          BUMP POINTER TO NEXT GROUP
      1530        LDA PNTR          OF 16 BYTES
      1540        ADC #16
      1550        STA PNTR
      1560        LDA PNTR+1
      1570        ADC #0
      1580        STA PNTR+1
      1590        CMP /$2200   AT END YET?
      1600        BCC .1       ...NO
      1610        RTS          ...YES, FINISHED
      1620 *--------------------------------
      1630 *   CHECKSUM ENTIRE 512 BYTES
      1640 *--------------------------------
      1650 CS2
      1660        LDX #0
      1670        TXA
      1680 .1     EOR $2000,X
      1690        INX
      1700        BNE .1
      1710 .2     EOR $2100,X
      1720        INX
      1730        BNE .2
      1740        JSR PRBYTE
      1750        RTS
      1760 *--------------------------------

    2000- A2 01 8E 6F  BF CA BD 00  20 9D 00 BD  BD 00 21 9D  (8B)
    2010- 00 BE E8 D0  F1 CA 9A 4C  21 BD 06 D3  C5 D4 D5 D0  (36)
    2020- D3 AD 30 BF  BD BF BE 20  00 BF C5 BE  BE AD 01 BD  (36)
    2030- 29 0F AA E8  8E 00 BD A9  2F 8D 01 BD  AD 04 BF 8D  (7B)
    2040- D2 BD AD 05  BF 8D D7 BD  A2 02 BD CB  BD 9D F2 03  (98)
    2050- BD CA BD 9D  03 BF CA 10  F1 9A 20 85  BE A2 17 A9  (5D)
    2060- 00 9D 58 BF  CA 10 FA A9  CF 8D 58 BF  A9 07 8D 6F  (1A)
    2070- BF AD 82 C0  8D 0C C0 8D  0E C0 9D 00  C0 20 84 FE  (45)

    2080- 20 2F FB 20  93 FE 20 90  FE 20 58 FC  20 00 BF C6  (33)
    2090- C5 BE 90 28  A2 0D BD F1  BE 9D AC 05  CA D0 F7 BD  (FA)
    20A0- 01 BD 09 80  9D BB 05 E8  EC 00 BD 90  F2 A9 23 85  (C2)
    20B0- 24 A9 0B 20  24 FC 20 0C  FD 4C 90 BD  20 15 BE BO  (EC)
    20C0- 0D 20 00 BF  C6 C2 BE 20  9E BE 4C 48  BD 18 EE F4  (83)
    20D0- 03 A9 00 8D  04 BF A9 00  8D 05 BF A9  00 8D 3E BE  (A6)
    20E0- 8D 82 BE A9  00 8D D2 BE  20 15 BE B0  1B AE 80 02  (F5)
    20F0- A0 06 BD 80  02 D9 0E BE  D0 EE CA 88  10 F4 EE 02  (84)

    2100- BE A9 FF F0  E3 20 8E BE  20 00 BF 65  C8 BE 2E 53  (1A)
    2110- 59 53 54 45  4D 20 00 BF  C8 Dl BE B0  68 AD D6 BE  (73)
    2120- 8D D8 BE 8D  DD BE 20 00  BF CA DC BE  B0 57 AD A3  (DB)
    2130- 02 8D 54 BE  AD A4 02 8D  44 BE EE 3E  BE A9 00 A2  (7C)
    2140- FE E8 E8 C9  0D 90 05 ED  44 BE B0 F5  A8 A9 04 88  (70)
    2150- 30 08 18 69  27 90 F8 E8  D0 F5 8D D9  BE 8E DA BE  (DB)
    2160- 20 00 BF CE  D7 BE B0 1D  20 00 BF CA  DC BE B0 15  (07)
    2170- AD 80 02 F0  C5 29 0F 8D  80 02 AD 90  02 49 FF F0  (4A)

    2180- 04 49 F9 D0  B5 08 20 00  BF CC CF BE  28 60 AE 90  (8D)
    2l90- 02 A9 20 E8  F0 06 AE 9F  02 AD A0 02  8E EC BE 8D  (F8)
    21A0- ED BE 20 00  BF C8 E4 BE  B0 DB AD E9  BE 8D EB BE  (17)
    2lB0- 20 00 BF CA  EA BE 20 85  BE B0 D2 6C  EC BE 02 00  (44)
    21C0- 01 BD 01 1A  3D 01 00 BD  04 00 00 00  00 00 00 01  (A3)
    21D0- 00 03 1A BD  00 B9 00 02  00 00 00 00  04 00 80 02  (99)
    21E0- 27 00 00 00  03 80 02 00  B9 00 04 00  00 00 00 B1  (AA)
    2lF0- 00 00 C9 CE  D3 C5 D2 D4  A0 D6 CF CC  D5 CD C5 E8  (57)

Apple Assembly Line (ISSN 0889-4302) is published monthly by S-C SOFTWARE CORPORATION, P. O. Box 280300, Dallas, TX 75228 Phone (214) 324-2050. Subscription rate is $18 per year in the USA, sent Bulk Mail; add $3 for First Class postage in USA, Canada, and Mexico; add $14 postage for other countries. Back issues are $1.80 each for Volumes 1-7 (other countries inquire for postage). A subscription to the newsletter and the Monthly Disk containing all source code is $64 per year in the USA, Canada and Mexico, and $87 to other countries.

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