Volume 5 -- Issue 8 | May 1985

- New Catalog for DOS 3.3
- 80-Column Window Utility for //e and //c
- AUTO/MANUAL Toggle Update for Version 2.0
- Apple ProDOS: Advanced Features for Programmers
- Adapting the Output Format of Rak-Ware DISASM
- DATE Command for ProDOS
- 32-bit Values in Version 2.0

S-C Macro Assembler for ProDOS

At long last, the news you've all been waiting for: the ProDOS version of the S-C Macro Assembler is almost ready. We have a working assembler in Beta testing, and it's doing just fine. We need to spend another month or two shaking on it and developing documentation, so it will be just a little longer 'til we start shipping, but it's on the way! Watch the front page of AAL for the announcement.

News from Don Lancaster

After nearly a year of delay at the publisher, Enhancing Your Apple II and //e, volume 2 is here! This followup to his very popular collection of Apple tricks, gimmicks, and techniques contains still more high-quality information on how to get the most out of our favorite computer. Here Don provides the tricks of microjustification and proportional spacing for Applewriter //e, an absolute "Old Monitor" style RESET for the //e, a software-only video synchronization technique for all Apple II's and //e's, and a just-for-fun guide to mapping and playing Castle Wolfenstein.

I've been saving the best for last: Tearing Into Applewriter //e. Here is 86 pages of priceless data on the internal workings of the most popular Apple Word Processor, including how to capture source code and customize it to your own taste. See our ad on page three for price and shipping.

As you will notice from his ad in this issue, Lancaster has been hard at work tearing into Appleworks, and has a set of disks available on that program. We haven't seen those yet, but I'll bet they're more of the same great inside info we've come to expect from Don.

A New Catalog for DOS 3.3 | Robert F. O'Brien Dublin, Ireland

In AAL March '85 Bob S-C presented re-writes of some loosely coded DOS sections to make space for patches - the Catalog Function Handler is another such loose bit of code, but rather than just free up some bytes I decided to add some useful features which Apple omitted and correct an annoying error at the same time. This new routine adds the following features to the CATALOG command:

1. Displays the free space remaining on the disk.
2. Allows you to terminate the Catalog during the normal pause after a screenful of files have been displayed by pressing the <ESC>-key (or other designated key).
3. Displays the correct number of sectors for each file in the Catalog for even the very large files - where the number of sectors exceeds 255 (which was the limit of the old PRINT.DECIMAL subroutine at $AE42 in DOS 3.3).
4. Optionally displays two filenames on each line of the Catalog - this is an 80-Column card option, also great for double-barrelled CATALOG printouts (for labels etc.).

In addition, the new Catalog retains the principal features of the old routine such as displaying the Volume number, the locked file indicator (*) and the file type abbreviation so that the user is not deprived of any essential information.

All the foregoing was achieved without using any additional DOS RAM space or zero-page locations other than that space already used by the Catalog Function Handler itself. Of course, something of the old routine had to be sacrificed in order to add the new features - it was necessary to omit the message "DISK VOLUME " from the beginning of the display. The 12-byte space where this message resided is now used to house a subroutine to check for locked files.

Even with all these enhancements, there are 17 free bytes left over! You could use some of them to print out an abbreviated form of the "DISK VOLUME " message, like "V=".

An additional constraint I saddled myself with in doing the re-write was that PRINT.DECIMAL (the DOS subroutine used to convert the hexadecimal numbers in locations $44,45 to decimal and print them) should retain its normal entry point ($AE42) so that the new code would be compatible with other programs which might use it.

For those who wish to get double-barrelled Catalog listings on an 80-column card or on a printer just change the "SEC" at line 2010 to "LSR". In other words, $AE12:4A will enable the wide printout, and $AE12:38 will put it back to normal.

To install the new patches just BLOAD the two binary files: NEW CATALOG PART 1, and NEW CATALOG PART 2. You can put the modified DOS onto any normal disk using Bob Perkins' technique (in AAL Aug 1982 p.24) without disturbing any other files present, or INIT a blank disk and the modified DOS will be incorporated on it. If you prefer to terminate long Catalog's with the <RETURN> key as you do for listings with the S-C Macro Assemblers just change byte $AE21:8D.

Also, if you are prepared to restrict yourself to 11 character file-names you can have a double-barrelled Catalog on the 40-Column screen by changing byte $ADF7:0B (POKE 44535,11), but I feel it would be of little value overall.

Now for a more detailed look at the program internals. Due to the requirement to save as many bytes as possible to squeeze in the desired features it was not possible to write the code in as straight-forward a manner as one would like. Even so, the routine was written with 17 byte to spare - after many re-writes to fit in all the features.

Lines 1020-1240 define various subroutines, variables, and data tables inside the rest of DOS.

Lines 1320-1360 use the same code as the original Catalog routine to initialize the File Manager and read the disk Volume Table Of Contents (VTOC).

In lines 1370-1410 we clear LINE.SKIP.FLAG which is used by SKIP.LINE subroutine to determine whether to tab to a second column or print a carriage return. Then we call PRINT.DECIMAL.YA to print the volume number. The volume number itself is passed in the A-register, and a zero high-byte in Y. Since we stripped out the code for printing "DISK VOLUME ", the volume number will be printed immediately to the right of the CATALOG command, on the same line. You will see "CATALOG 254 395", or the like, where the first number is the volume number and the second is the count of free sectors.

By making a special entry above the PRINT.DECIMAL subroutine which is used both here and at line 1830 below, we save several bytes. Of course we have already save a couple dozen bytes by not printing "DISK VOLUME ".

Calculation of the free disk space is made in lines 1420-1530. We make use of a new feature in the corrected PRINT.DECIMAL routine whereby $44 and $45 are reduced to 0 during the conversion - resulting in a saving of 4 bytes by not having to re-zero $45. (In the old routine only $44 was reduced to 0.)

In the VTOC 4 bytes are set aside for each track to indicate sector usage although only 2 are needed for a standard Apple disk. (The extra space allows up to 50 tracks and up to 32 sectors per track to be initialized.) A bit set=1 means that the corresponding sector on the track is available for use. If a bit is set=0 then the sector is already allocated. So it was simply a matter of counting every bit set from offset byte $38 (track 0) to Byte $C3 (for Trk $22) of the VTOC buffer to get a count of the free space. If you want to count all the way to the 50th track, in case the program is working with a hard disk like the Sider or Corvus, or a RANA 320K floppy, change lines 1430-1440:

           1430       LDX #$38
           1440       LDA VTOC.BUFFER,X

In line 1550 we have another departure from the original code - 2 bytes were saved by entering the tail end of the SKIP.LINE subroutine in order to set the number of lines to place on the screen before pausing during a Catalog. This has the added advantage that you can customize your Catalog more easily in that the line count can be adjusted by modifying a single byte ($AE25).

At lines 1570-1610 we start by clearing the Carry flag so that the first sector of the directory will be read (track $11, sector $0F). Also we set the index (X) to the first filename entry in the sector.

Lines 1620-1660 examine the track number of the Track/Sector list for the current filename entry. Should this number be 0 it indicates that we are at the end of the directory, at which point we would terminate the Catalog by exiting the File Manager routine by a jump to $B37F.

Fortunately, there was a JMP $B37F instruction within relative branching distance of the Catalog Function Handler. We could therefore dispense with the JMP to $B37F in the original code saving a further 3 bytes by branching to FM.EXIT at $AD86 instead. This is an address in the DELETE Function Handler ($AD2B-AD97) which precedes the Catalog routine in RAM. There are three ways we can terminate the Catalog, which all result in a branch to FM.EXIT: here at line 1600 when we find there are no more catalog sectors, at line 1650 when we find there are no more catalog entries, and at line 2090 when the ESC-key is typed during a screen-pause.

At line 1660 if the track number value is negative (bit 7 set) then we have found a deleted file. Deleted files don't show up on the Catalog, so we call on the subroutine at $B230 which sets the X-Register to the value of the entry point offset for the next entry in the sector, if any.

If on return from this subroutine the Carry flag bit is set (=1) then we have reached the end of the current catalog sector and we branch back to READ.SECTOR at line 1580 to read the next directory sector, if any. (Each directory sector accommodates 7 entries.)

At line 1680 we call the SKIP.LINE subroutine, which normally merely prints a carriage return. This routine was called from five different places in the original catalog code, so we have saved a dozen bytes by only calling it from this one place. (Putting it in-line would save four more!)

At line 1700 we call the new subroutine at the site of the DISK VOLUME message space to check for locked files and print the space or asterisk. This routine also leaves the file type code in the Y-register. This code could be placed in-line, rather than making it a subroutine, but then the final two lines could not be used as a short PRINT.SPACE subroutine.

Lines 1710-1790 convert the file type code to a file type character. The file type code is in bits 6-0, and is either zero (meaning type T), or a single bit. The hex values 40, 20, 10, 08, 04, 02, and 01 stand for file types B, A, R, S, B, A, and I. A string at $B4C8 holds "TIABSRAB", so we need to convert the bit position to an index value, and pick up the character out of that string. The ASL at line 1740 elminates the "lock/unlock" bit. The loop in line 1750-1770 shifts bits out until the value is zero, counting up in the Y-register. If the value was already zero, we exit immediately with Y=0, and type is "T". A type value of 1 gives an index of 1, up through $40 giving an index of 7.

By the way, types 40 and 20 are not Binary and Applesoft. They are hardly ever used, except in protection schemes. Types 04 and 02 are Binary and Applesoft.

The original catalog code had a significantly longer loop for converting the file type number to an index. You might want to compare the two.

The number of sectors in the file is picked up and converted in lines 1800-1830 and the decimal value is printed, surrounded by spaces. Lines 1840-1900 print out the file name.

Lines 1920-1950 advance to the next filename entry, and branch either to process it or to read in another catalog sector.

Lines 1970-2130 usually print a carriage return. If you have changed line 2010 to "LSR", to get double column catalogs, the least significant bit of LINE.SKIP.FLAG will determine whether to print a carriage return or not. When line 2010 is "SEC" we will always get a carriage return. If a carriage return is printed, we also count the line. When the line count is complete, we pause and wait for a keystroke. If that key is an ESC-key, the catalog will terminate. If not, the line count is re-initialized and we go back for more file names.

Line 2150 simply reserves 17 bytes, shoving the PRINT.DECIMAL routine down so that it still starts at $AE42 like it used to. These 17 bytes could be used for other code or data, whatever you like.

Lines 2160-2230 store a value to be converted and printed, print a blank, and then fall into the PRINT.DECIMAL subroutine.

The new corrected PRINT.DECIMAL subroutine is actually a little shorter than th buggy original. It left room for a JMP PRINT.SPACE at the end, which saved calling PRINT.SPACE from several other places. It also left room for the LINE.SKIP.FLAG variable.

The PRINT.DECIMAL subroutine (lines 2240-2490) effectively divides the number in $44,45 by subtracting in turn the values 100, 10 and 1 from it - a 16-bit subtraction. The count of the number of subtractions and the low order byte remainder are temporarily stored on the stack to conserve memory usage. We start with 100 and keep subtracting it and incrementing the subtraction-counter until we get borrow, at which point we print the counter value.

Now $44,45 will contain the remainder and so we continue using 10 and then 1 until three decimal digits are printed. This subroutine can accurately convert numbers having values up to 999 decimal.

CHALLENGE. Even though we have already squeezed out 17 bytes, while adding new features, we did lose the "DISK VOLUME " message. Can someone out there squeeze enough more out, without losing any features, to slip the message back in?

CAVEAT. If you decide to put this new CATALOG program on your disks, please be careful. There are some programs which temporarily patch the catalog routine themselves. In particular, ES-CAPE and other commercial programs patch the SKIP.LINES subroutine so that the pause is eliminated. Since SKIP.LINES has been moved and is different, no telling what might happen.

      1000 *SAVE S.NEW CATALOG
      1010 *--------------------------------
      1020 DOS.ARITH.REG          .EQ $44,45
      1030 *--------------------------------
      1040 ADV.NEXT.DIR.ENTRY     .EQ $B230
      1050 DOS.INIT.FM            .EQ $ABDC
      1060 EXIT.FM                .EQ $AD86
      1070 MON.COUT               .EQ $FDED
      1080 MON.CROUT              .EQ $FD8E
      1090 MON.RDKEY              .EQ $FD0C
      1100 READ.DIRECTORY.SECTOR  .EQ $B011
      1110 READ.VTOC              .EQ $AFF7
      1120 *--------------------------------
      1130 DEC.CONVERSION.TABLE   .EQ $B3A4
      1140 FILE.TYPE.NAME.TABLE   .EQ $B3A7
      1150 *--------------------------------
      1160 CATALOG.LINE.COUNT     .EQ $B39D
      1170 DIRECTORY.ENTRY        .EQ $B4C6
      1180 DIRECTORY.INDEX        .EQ $B39C
      1190 DISK.VOL.NUMBER        .EQ $B7F6
      1200 FILE.NAME              .EQ $B4C9
      1210 FILE.SIZE              .EQ $B4E7
      1220 FILE.TYPE              .EQ $B4C8
      1230 FM.VOL.NUMBER          .EQ $B5F9
      1240 VTOC.BUFFER            .EQ $B3BB
      1250 *--------------------------------
      1260 *    New Catalog for DOS 3.3
      1270 *    by  Robert F.O'Brien
      1280 *--------------------------------
      1290        .OR $AD98
      1300        .TF NEW CATALOG PART 1
      1310 *--------------------------------
      1320 CATALOG
      1330        JSR DOS.INIT.FM   Init file manager.
      1340        LDA #$FF          Set Volume = 0
      1350        STA FM.VOL.NUMBER   (matches any volume)
      1360        JSR READ.VTOC     Load in VTOC into buffer.
      1370 *---Print Volume Number----------
      1380        LDY #0            High byte = 0
      1390        STY LINE.SKIP.FLAG    (signal to skip)
      1400        LDA DISK.VOL.NUMBER   low byte
      1410        JSR PRINT.DECIMAL.YA
      1420 *---Calculate Free Space---------
      1430        LDX #$74          Trk 0 VTOC offset
      1440 .1     LDA VTOC.BUFFER+$38-$74,X     Bit Map Byte
      1450 .2     BPL .3            This sector in use
      1460        INC DOS.ARITH.REG   Count a free sector.
      1470        BNE .3
      1480        INC DOS.ARITH.REG+1
      1490 .3     ASL               Check next bit
      1500        BNE .2            Still more in this byte
      1510 .4     INX               Next byte of bit map
      1520        BNE .1            ...still more
      1530        JSR PRINT.DECIMAL    print number free
      1540 *---Start Line count-------------
      1550        JSR SET.LINE.COUNT        lines to print.
      1560 *---Start reading directory------
      1570        CLC               Get first sector.
      1580 READ.SECTOR
      1590        JSR READ.DIRECTORY.SECTOR
      1600        BCS EXIT.FM       No more sectors
      1610        LDX #0            Index to 1st file in sector
      1620 SET.ENTRY.INDEX
      1630        STX DIRECTORY.INDEX   Set entry offset
      1640        LDA DIRECTORY.ENTRY,X See if valid filename
      1650 EXIT   BEQ EXIT.FM       ...end of directory
      1660        BMI NEXT.ENTRY    ...ignore deleted file.
      1670 *---Start next file display------
      1680        JSR SKIP.LINE     Next line or Tab
      1690 *---Locked or Unlocked-----------
      1700        JSR LOCKED.FILE.CHECK     "*" if locked file.
      1710 *---File Type--------------------
      1720        TYA               Get file type byte
      1730        LDY #-1           Index to type table
      1740        ASL               Ignore Bit 7
      1750 .1     INY               Next file type code
      1760        LSR               Check bit of type byte
      1770        BNE .1            ...not yet
      1780 .2     LDA FILE.TYPE.NAME.TABLE,Y Get file type
      1790        JSR MON.COUT      ...and print it
      1800 *---File Size--------------------
      1810        LDY FILE.SIZE+1,X         high order byte
      1820        LDA FILE.SIZE,X           low order byte
      1830        JSR PRINT.DECIMAL.YA      print total sect.
      1840 *---File Name--------------------
      1850        LDY #30
      1860 .3     LDA FILE.NAME,X           char. no. in Y.
      1870        JSR MON.COUT          print file name.
      1880        INX                       next char.
      1890        DEY
      1900        BNE .3                    not done yet!
      1910 *---Next File in Directory-------
      1920 NEXT.ENTRY
      1930        JSR ADV.NEXT.DIR.ENTRY  Set X-Reg for next file
      1940        BCC SET.ENTRY.INDEX     more in sector
      1950        BCS READ.SECTOR         get next sector
      1960 *--------------------------------
      1970 SKIP.LINE
      1980        JSR PRINT.SPACE   Separate 2nd line entry
      1990        INC LINE.SKIP.FLAG  Toggle lsbit
      2000        LDA LINE.SKIP.FLAG  Check Odd or Even
      2010        SEC        <<<Change to "LSR" for double
      2020 *                    column CATALOG >>>
      2030        BCC RETURN
      2040        JSR MON.CROUT     Start a new line
      2050        DEC CATALOG.LINE.COUNT    continue countdown
      2060        BNE RETURN                not full screen yet
      2070        JSR MON.RDKEY     Pause for keypress!
      2080        CMP #$9B          Is it  ESC-key?
      2090        BEQ EXIT          ...yes, exit file manager
      2100 SET.LINE.COUNT
      2110        LDA #21           lines per screenful
      2120        STA CATALOG.LINE.COUNT
      2130 RETURN RTS               Continue catalog
      2140 *--------------------------------
      2150        .BS 17            17 FREE BYTES!
      2160 *--------------------------------
      2170 *   Print (YA) with leading and
      2180 *      trailing blanks.
      2190 *--------------------------------
      2200 PRINT.DECIMAL.YA
      2210        STY DOS.ARITH.REG+1
      2220        STA DOS.ARITH.REG
      2230        JSR PRINT.SPACE
      2240 *--------------------------------
      2250 *   Print ($44,45) with trailing blank
      2260 *--------------------------------
      2270 PRINT.DECIMAL
      2280        LDY #2            Set for 3 divisors
      2290 .1     LDA #$B0          ASCII zero
      2300 .2     PHA               save digit on stack
      2310        SEC               Subtract 100, 10, or 1
      2320        LDA DOS.ARITH.REG    from remainder
      2330        SBC DEC.CONVERSION.TABLE,Y
      2340        PHA               save remainder on stack
      2350        LDA DOS.ARITH.REG+1
      2360        SBC #0            (divisor high byte = 0)
      2370        BCC .3            ...far enough
      2380        STA DOS.ARITH.REG+1   Update remainder
      2390        PLA
      2400        STA DOS.ARITH.REG
      2410        PLA               get current digit
      2420        ADC #0            and count the subtraction
      2430        BNE .2            ...continue subtracting
      2440 .3     PLA               Discard stacked remainder byte
      2450        PLA               Get quotient digit
      2460        JSR MON.COUT      and print it!
      2470        DEY               Next divisor
      2480        BPL .1            ...not finished yet
      2490        JMP PRINT.SPACE   Trailing space
      2500 *--------------------------------
      2510 LINE.SKIP.FLAG .DA #0    LEAST SIGNIFICANT BIT IS FLAG
      2520 *--------------------------------
      2530        .OR $B3AF
      2540        .TF NEW CATALOG PART 2
      2550 *--------------------------------
      2560 *   OVERLAYS "DISK VOLUME " MESSAGE
      2570 *--------------------------------
      2580 LOCKED.FILE.CHECK
      2590        LDA #"*"
      2600        LDY FILE.TYPE,X   file type code.
      2610        BMI CAT.COUT      ...the file is locked
      2620 PRINT.SPACE
      2630        LDA #" "
      2640 CAT.COUT
      2650        JMP MON.COUT
      2660 *--------------------------------

80-Column Window Utility for //e and //c | Bill Reed New Orleans, LA

I throughly enjoyed "Fast Text Windows" by Michael Ching. However, I prefer not to use the area at $800-BFF as a text buffer; I much prefer to use the first bank of the language card, which is not normally used by Applesoft programs running under DOS 3.3.

I modified Mike's program by changing the immediate values in lines 1560 and 1580 from #$0C to #$D4 and adding lines 1644, 1646 and 1905. The first two lines enable the bank of RAM to be read or written to. The last re-enables the Applesoft ROMS.

         1644       LDA $C08B
         1646       LDA $C08B
         1905       LDA $C082

I further modified the program to function in 80 columns on a //e or //c. The big problem was to mimic the text card, which uses bank switching to store adjacent characters in the same address, but different locations (main RAM and aux RAM). This was solved by using one buffer for the "even" characters and another for the "odd".

Additional code was required to determine the even/odd condition, so I (being lazy) removed the border portion of the program to conserve room. The border routines could certainly be retained if part of the program was also moved to bank one of the language card area. (Be careful if you try this, because you must avoid calling the monitor or Applesoft ROMs when the ROMs are switched off. You can possibly get away with calling the monitor with the ROMs switched off, but only if you first make a copy of the monitor in the F800-FFFF area of RAM.)

I moved the data storage to the zero page, mostly because it was available and slightly faster.

      1000 ; SAVES.WINDOWS.80
      1010 *-AAL APRIL 85 P 16-------------
      1020       .OR $2F5
      1030       .TF B.WINDOWS.80
      1040 *-------------------------------
      1050 TOP       .EQ $00  $0-$6 DATA
      1060 BOTTOM    .EQ $01
      1070 LEFT      .EQ $02
      1080 RIGHT     .EQ $03
      1090 WIDTH     .EQ $04
      1100 LINE      .EQ $05
      1110 DIREC     .EQ $06
      1120 *
      1130 B1        .EQ $18,19   TEXT PNTR
      1140 B2        .EQ $1A,1B   BUFR PNTR
      1150 B3        .EQ $1C,1D   BUFR PNTR
      1160 WNDLFT    .EQ $20
      1170 WNDWDTH   .EQ $21
      1180 WNDTOP    .EQ $22
      1190 WNDBTM    .EQ $23
      1200 BASL      .EQ $28
      1210 BASH      .EQ $29
      1220 *-------------------------------
      1230 AMPERV    .EQ $3F5
      1240 PAG2OFF   .EQ $C054  READ MRBRD
      1250 PAG2ONN   .EQ $C055  READ AUXBRD
      1260 LCROM     .EQ $C082
      1270 LCRAM1    .EQ $C08B
      1280 GETBYTE   .EQ $E6F8
      1290 COMBYTE   .EQ $E74C
      1300 BASCALC   .EQ $FBC1
      1310 HOME      .EQ $FC58
      1320 *-------------------------------
      1330 SETUP
      1340       LDA #MOVE.WINDOW
      1350       STA AMPERV+1
      1360       LDA /MOVE.WINDOW
      1370       STA AMPERV+2
      1380       RTS
      1390 *-------------------------------
      1400 MOVE.WINDOW
      1410       JSR GETBYTE
      1420       STX TOP
      1430       STX LINE
      1440       JSR COMBYTE
      1450       STX BOTTOM
      1460       JSR COMBYTE
      1470       STX LEFT
      1480       JSR COMBYTE
      1490       STX RIGHT
      1500       INX
      1510       SEC
      1520       TXA
      1530       SBC LEFT
      1540       STA WIDTH
      1550       JSR COMBYTE
      1560       DEX
      1570       STX DIREC
      1580 *-------------------------------
      1590 *-------------------------------
      1600 MOVE.LINE
      1610       LDA LINE
      1620       JSR BASCALC
      1630       LDA BASH
      1640       STA B1+1
      1650       EOR #$D4
      1660       STA B2+1
      1670       CLC
      1680       ADC #$04      2ND BUFR
      1690       STA B3+1
      1700       LDA BASL
      1710       STA B1
      1720       STA B2
      1730       STA B3
      1740       LDA LCRAM1    ENABLE LANG
      1750       LDA LCRAM1    CARD R/W
      1760 *--MOVE THE LINE SEGMENT--------
      1770       LDA RIGHT
      1780       LSR           A/2 + EVN/ODD
      1790       TAY           TXT SCRN PNTR
      1800       LDX DIREC
      1810       BNE .3
      1820 *--MOVE IT UP-------------------
      1830       LDX WIDTH     DOWN COUNTER
      1840       BCC .2
      1850 .1    LDA (B1),Y    DO ODD COLS
      1860       STA (B2),Y
      1870       DEX
      1880       BMI .6
      1890 .2    LDA PAG2ONN   DO EVN COLS
      1900       LDA (B1),Y
      1910       STA (B3),Y
      1920       LDA PAG2OFF
      1930       DEY
      1940       DEX
      1950       BPL .1
      1960       BMI .6
      1970 *--MOVE IT DOWN-----------------
      1980 .3    LDX WIDTH
      1990       BCC .5
      2000 .4    LDA (B2),Y    DO ODD COLS
      2010       STA (B1),Y
      2020       DEX
      2030       BMI .6
      2040 .5    LDA PAG2ONN   DO EVN COLS
      2050       LDA (B3),Y
      2060       STA (B1),Y
      2070       LDA PAG2OFF
      2080       DEY
      2090       DEX
      2100       BPL .4
      2110 *--NEXT LINE--------------------
      2120 .6    INC LINE
      2130       LDA LCROM     RESTORE ROM
      2140       LDA BOTTOM
      2150       CMP LINE
      2160       BCS MOVE.LINE
      2170 *--IF CLEARING, SET WINDOW------
      2180       LDA DIREC
      2190       BNE .7
      2200       LDX LEFT
      2210       STX WNDLFT
      2220       LDX WIDTH
      2230       DEX
      2240       STX WNDWDTH
      2250       LDX TOP
      2260       INX
      2270       STX WNDTOP
      2280       LDX BOTTOM
      2290       STX WNDBTM
      2300       JSR HOME
      2310 .7    RTS
      2320 *-------------------------------
      2330 ZZEND .EQ *

AUTO/MANUAL Toggle Update for S-C Macro Assembler Version 2.0 | Robert F. O'Brien Dublin, Ireland

Here is a short routine (23 bytes) which makes use of the ESC-U command option to toggle the Auto-linenumbering mode on and off readily. The routine is relocatable so you can put it anywhere you have sufficient free space - just set the ESC-U vector to point to it, in this case :$C083 C083 D00C:4C 00 03 N C080.

When the cursor is waiting for input at the beginning of the command line, typing ESC-U will generate the command AUTO and then you have the option of entering a line number and/or RETURN. To cancel the AUTO mode just type ESC-U while the cursor is at the beginning of the line (just after the linenumber - 4 or 5 digit line numbers are catered for).

Extended AUTO command:

The second routine, starting at $317, is just 17 bytes long and extends the AUTO command so that you can specify the increment after the starting linenumber. For example, AUTO 3000,1 sets a starting line number of 3000 and an increment of 1. This code is also relocatable but you must patch the first instruction in the main AUTO command so that it uses the new code as a sub- routine. In this case it's :$C083 C083 D392:20 17 03 N C080.

The addresses specified for these new features are for the corrected version of the Assembler - i.e. serial nos. greater than 1251; see note in AAL March '85. Here is a table of what to expect at each of the addresses used, so you can find the equivalent spots in other copies of the assembler:

    $D198 -- 20 xx D2      (JSR GNC)
             B0 17         (BCS to RTS)
             49 30         (EOR #$30)

    $D392 -- 20 xx D1      (JSR GET.VALUE)
             CA            (DEX)
             30 0E         (BMI to SEC)

    $D40B -- 41 55 54 CF   (.AT /AUTO/)
             xx D3         (.DA AUTO-1)

    $DB9A -- 09 80         (ORA #$80)
             9D 00 02      (STA $0200,X)
             C9 A0         (CMP #$A0)

Note that with the Auto/Manual Toggle function installed you won't need the MANUAL command any more, so you have a spare command if you need it!

      1000 *SAVE S.AUTO/MAN
      1010 *--------------------------------
      1020        .OR $300
      1030 *      .TF AUTO/MAN TOGGLE
      1040 *--------------------------------
      1050 INCREMENT    .EQ $5A,5B
      1060 SYM.VALUE    .EQ $B8,B9
      1070 AUTO.FLAG    .EQ $E3
      1080
      1090 WARM.START   .EQ $D028
      1100 GET.VALUE    .EQ $D198
      1110 AUTO.CMD     .EQ $D40B
      1120 INSTALL.CHAR .EQ $DB9A
      1130 *--------------------------------
      1140 AUTO.MAN.CODE
      1150        TXA               check cursor posn.
      1160        BEQ .1            OK to output cmd.
      1170        CPX #7            line start?
      1180        BGE .2            ignore ESC-U.
      1190        LSR AUTO.FLAG     cancel auto-mode.
      1200        JMP WARM.START
      1210
      1220 .1     LDA AUTO.CMD,X    output cmd. name
      1230        JSR INSTALL.CHAR  put in buffer+scrn.
      1240        CPX #4            4 chars. output?
      1250        BNE .1            no.
      1260 .2     RTS               exit ESC-U routine
      1270 *-----------------------------
      1280 *  Point start of AUTO cmd. handler
      1290 *  to here for extended function.
      1300 *--------------------------------
      1310 NEW.AUTO.EXT
      1320        JSR GET.VALUE     get linenum if any.
      1330        JSR GET.VALUE     get inc. if any.
      1340        CPX #3            increment?
      1350        BLT .1            no
      1360        DEX               adjust for inc.
      1370        DEX                   do.
      1380        LDA SYM.VALUE     set inc. low byte
      1390        STA INCREMENT
      1400 *  (following 2 lines only needed
      1410 *   if you use increments of 255+!)
      1420 *      LDA SYM.VALUE+1   set inc. high byte
      1430 *      STA INCREMENT+1
      1440 .1     RTS               finish AUTO cmd.

Apple ProDOS: Advanced Features for Programmers a Review | Bill Morgan

Gary Little, the prolific author of Inside the Apple //e and Inside the Apple //c, has yet another new book out. This one is called Apple ProDOS: Advanced Features for Programmers. In this volume Little covers just about all you need to know to write assembly language programs under ProDOS, from simply passing commands to BASIC.SYSTEM, through great detail on all the MLI calls, to writing your own interrupt handlers and device drivers.

Here's a quick summary of the book's contents:

1. An Introduction to ProDOS -- Little starts out with the history of Apple's DOS's, a comparison of ProDOS and DOS 3.3, and a summary of important features of ProDOS.
2. Files and File Management -- Here he covers the directory structures, file structures, disk formatting, and gives us a READ.BLOCK program.
3. Loading and Installing ProDOS -- This chapter goes into the boot process, ProDOS' memory usage, and the Global Page.
4. The Machine Language Interface -- This is the information on using the MLI, its error codes, and complete details of all MLI calls.
5. System Programming Featuring BASIC.SYSTEM -- Here we have a discussion of system programs, the structure and commands of BASIC.SYSTEM, and assembly language programming under BASIC.SYSTEM.
6. Interrupts -- In this chapter Little covers interrupts in general, ProDOS interrupt handling, and programming the Apple mouse.
7. Disk Drivers -- Nearing the end, we go into identifying and handling foreign disk drivers, driver commands, the /RAM driver, and adding your own driver.
8. ProDOS Clock Drivers -- And finally we find out about using the built-in clock support, adding a clock driver, and reading the date and time from Applesoft.

An important strength of this book is the wealth of examples. In the chapter on the Machine Language Interface there is an example of the correct use of EVERY MLI call. The BASIC.SYSTEM chapter includes an ONLINE command, to identify all disk volumes currently on line. The chapter on interrupts contains a couple of examples of mouse programming. The Disk driver section has a listing of a simple /RAM driver for main memory. And this is just a sample of the useful code provided in Little's new book. A companion disk containing all of the book's programs and more is available for $25.00 from the author.

I hear some of you asking: How does Apple ProDOS: Advanced Features (APAF) compare to Beneath Apple ProDOS (BAP)? Well, the two books complement each other quite nicely. With all its examples, treatment of interrupt handlers and device drivers, and overall clarity, I'd say that APAF is the better book on programming under ProDOS. BAP has useful examples as well, and better detail about the internals of diskette formatting and how ProDOS works, especially with its 120+ page supplement describing the code on a line-by-line basis. So if you're concerned with understanding the inner workings of the operating system, or with modifying its behavior, BAP is the book to have. Otherwise, get APAF for the best information on programming using ProDOS. Personally, I'm glad to have both books on the shelf here, along with Apple's ProDOS Technical Reference Manual.

Apple ProDOS: Advanced Features for Programmers, by Gary B. Little. Brady Communications Co., 1985. 266+iv pp., Reference Card. $17.95. Available from S-C Software for $17 + shipping.

Adapting the Output Format of Rak-Ware DISASM | Bob Kovacs

This technical note describes the format table used within DISASM 2.2e, which can be modified to adapt the output text file format to other assemblers. Even if you never plan to modify DISASM, or even if you don't own a copy of DISASM, you can learn a lot about the use of configuration tables by studying what follows.

The current version of the disassembler provides three different output formats to support the DOS ToolKit, S-C, and LISA assemblers. The format table contains various attributes which are unique to each assembler. The table begins at location $1331 and is $3F bytes long. Let's first examine the table and then determine how to adapt it to other assembler formats.

     Item      ToolKit      S-C          LISA
    ---------  -----------  -----------  -----------

    comment    AA     *     AA     *     BB     ;
    firstchr   00     none  89     ^I    00     none
    tabchr1    A0     spc   89     ^I    A0     spc
    tabchr2    A0     spc   A0     spc   A0     spc
    opchr      C1     A     00     none  00     none
    pgzchr     C5D1D5 EQU   AEC5D1 .EQ   C5D0DA EPZ
    extchr     C5D1D5 EQU   AEC5D1 .EQ   C5D1D5 EQU
    hexchr     C4C6C2 DFB   AEC8D3 .HS   C8C5D8 HEX
    orgchr     CFD2C7 ORG   AECFD2 .OR   CFD2C7 ORG
    prechr     AA0000 *     000000 none  C9CED3 INS
    postchr    00     none  98     ^X    85     ^E

comment: the character used at the beginning of a line to signify a comment line.

firstchr: the character ouput at the beginning of each line.

tabchr1: the character used to tab to the opcode field.

tabchr2: the character used to tab to the operand field.

opchr: operand for impled accumulator instructions (ASL, LSR, ROR, ROL).

pgzchr: directive for page zero declarations.

extchr: directive for absolute declarations.

hexchr: directive for data tables.

orgchr: directive for setting the program origin.

prechr: preamble sequence for initialization of the assembler.

postchr: postamble character for termination of the assembler's loading operation.

You will find that it is relatively simple to modify the format table for other assemblers. First, determine which of the three existing formats is to be overwritten (just pick the one you think you'll need the least). Then determine the format data which is appropriate to your assembler. BLOAD DISASM, enter the monitor, and stuff the new values into the table. Finally BSAVE DISASM,A$800,L$D00.

Or, if you have purchased the source code of DISASM 2.2e (or created your own using DISASM!), you can merely edit the table with your assembler and re-assemble the program.

You might also need or want to change some other paramteters, which are not in the format table:

> Label Prefix: located at $132E, the current value is C9DAD8 (the letters "IZX"). These letters are used to indicate internal, pagezero, and external labels in the generated text file.

> Menu Table: located at $1300, this table contains the names of the three assemblers listed in the first menu. Each name is stored in ASCII, followed by a return ($0D) and a terminator ($00).

> Label Name Separator: A period ($AE) is output as the second character in every generated label name. This can be changed to any other character by editing the LDA #$AE instruction at location $0EA4.

I would be interested in hearing from any of you who have already modified DISASM. This kind of feedback can lead to new versions with even more powerful features.

DATE Command for ProDOS | Bill Morgan

One of the nice new features in ProDOS is the way the diskette catalog shows the date of creation and last modification for each file, IF you have a clock/calendar card installed in your Apple. Well I don't have such a card in either of the Apples I use regularly, at work or at home. And no //c has a clock! (Yet, at least. I'll bet someone will come up with a way...)

Anyway, I got tired of always seeing <NO DATE> and started figuring out how to set a date without a clock to do it for me. A look at Beneath Apple ProDOS informed me that the current date is transformed into the format YYYYYYYMMMMDDDDD and stored (in the usual 6502 low byte/high byte sequence) at $BF90-BF91 in the ProDOS Global Pages (the fixed locations of all of the accessible system variables). The first thing I did was manually convert the current date into that format and poke it in from the Monitor. That went like this:

                             $BF90      $BF91
    May =  $5 = 0101       MMM DDDDD  YYYYYYY M
     10 =  $A = 01010      101 01010  1010101 0
    '85 = $55 = 1010101       $AA        $AA

So, the values to poke into $BF90-91 were $AA and $AA. What better time than a four-A day to start such a project!

That experiment worked just fine: the next file I saved on the disk showed creation and modification dates of 10-MAY-85, just as I had hoped. With that success under my belt the next step had to be to come up with a program to read and/or set those date bytes. And, while I'm at it, why not take advantage of ProDOS' built-in hooks for installing new commands and add a DATE command to the operating system?

How do I go about adding a command? The ProDOS Technical Reference Manual is pretty sketchy on the subject, but two other books, Beneath Apple ProDOS and the new Apple ProDOS: Advanced Features for Programmers, have good descriptions and examples of the procedure. If you're going to do much assembly language programming under ProDOS you should have one or both of those books.

When ProDOS fails to recognize a command it does a JSR EXTRNCMD ($BE06) to find out if an external command processor will claim this one. What I have to do is install the address of DATE in $BE07-08, after moving the address that was already there into a JMP instruction. This way, if DATE doesn't recognize the command it can pass it along to any other processor that might have been there before.

Processing of an external command is normally divided into two phases, a parser and a handler. The parser section will scan the command name at the beginning of the line. If the command is not recognized, the parser should set the carry bit and JMP on to the address found in EXTRNCMD to see if another external processor will claim it.

If the command is recognized, the parser can set certain bits in PBITS ($BE54-55) to signify which parameters are permitted or required on the command line, and store the address of the handler in EXTRNADDR ($BE50-51). After storing the command length minus one in XLEN ($BE52) and a zero in XCNUM ($BE53), to signify that an external processor did claim the command, the parser then returns control to ProDOS to scan the rest of the line. If the line was syntactically correct, ProDOS will return the values of the parameters in a set of standard locations ($BE58-6F) and pass control back to the handler address specified.

Since DATE is a simple processor that uses a nonstandard parameter, I just set PBITS to zero, to indicate no parsing necessary, and store the address of an RTS instruction in EXTRNADDR. I then proceed to do all my processing before returning to ProDOS.

There is one additional wrinkle to using an external command with ProDOS: where do I put my code so ProDOS, Applesoft, and others don't stomp all over it? In the interest of simplicity I have ignored that problem here. The best procedure, as shown in the books mentioned above, is to call ProDOS to assign me a buffer and then relocate my code into that buffer. The examples in the books provide details of this process.

Now, let's take a look at the code:

Lines 1310-1400 install DATE by moving the current External Command address to my exit JMP instruction and storing DATE's address in the vector.

Lines 1440-1540 check the input buffer to see if this is a DATE command. If not we branch on down to that JMP instruction where we earlier put the address found in the External Command vector. This passes control either on to the next external command in the chain, or back to ProDOS for a SYNTAX ERROR.

If the command matched we go on to lines 1560-1650 to do the necessary housekeeping. This involves storing the command length-1 in the Global Page, setting a couple of flags to tell ProDOS not to parse the rest of the command line, and that an external command has taken over. Then we supply a handler address for the second half of ProDOS' processing, which in this case is just an RTS instruction. Finally we reach lines 1670-1690, where we check to see if the character following DATE is a Carriage Return. If so we branch forward to RETURN.DATE to display the existing date.

If there is more than just DATE on the command line, we must want to set a new date, so we fall into SET.DATE at line 1710. This routine makes heavy use of ACCUMULATE.DIGITS at line 2400, so we'll examine that code first. The first step is to zero the byte where we'll be accumulating the value typed in. Then we scan forward in the input buffer, looking for a nonblank character. When we find one we first check to see if it is a slash, which marks the end of a number, or a Carriage Return, which marks the end of the line. If it was either of those we exit, setting the Carry bit to indicate which one we found.

If the character found was not a delimiter we next check to see if it is a number. If not, we have a SYNTAX ERROR. When we do get a number, we strip off the high bits to convert the ASCII code to a binary value, and save that value. We then multiply the previous value in ACCUM by 10 and add in the new value. Then it's back to line 2440 to get another character. Lines 2710-2730 load the A-register with the value found and branch to the error exit if that value was zero.

Now, back to SET.DATE. That routine begins at line 1720 with a DEY to get ready for the INY at the beginning of ACCUMULATE.DIGITS. We then get the month, check for a legal value, and store it. Next we get the day, save the status, and check and save that value. Then it's time to check the status to see if the day was followed by a slash, or by a Carriage Return. If it was a slash then a year was specified, so we go get that value. If it was a Return no year was present, so we use 1985. (I guess that means we'll have to reassemble or patch this program every year. I think I can handle that.)

The last step in SET.DATE is to fold the year, month, and day together as described above and store the results in the Global Page. The comments in the listing illustrate how the bits are shuffled around to the correct format. After setting the date we fall into RETURN.DATE to display the result.

RETURN.DATE, at lines 2080-2290, is quite straightforward. It just gets the bytes from the Global Page, unfolds them, and calls DEC.OUT to translate them to decimal numbers and display those numbers. Again, the comments illustrate the bit manipulations involved in the unfolding process.

The final section of code is DEC.OUT, at lines 2750-2910. In lines 2760-2810 we use the Y-register to count how many times we can subtract 10 from the number passed in the A-register. Then lines 2830-2910 restore and save the A-register, make sure the tens count is non-zero, convert it to a character and print it. We then recover the units value and print that out.

      1000 *SAVE S.DATE
      1010 *--------------------------------
      1020 *
      1030 *      Program to read or set the
      1040 *      date bytes in the Global Page
      1050 *
      1060 *            by Bill Morgan
      1070 *
      1080 *--------------------------------
      1090 POINTER    .EQ $40,41
      1100 ACCUM      .EQ $42
      1110 MONTH      .EQ $43
      1120 DAY        .EQ $44
      1130 TEMP       .EQ $45
      1140
      1150 WBUF       .EQ $200
      1160
      1170 EXTRNCMD   .EQ $BE07
      1180 EXTRNADDR  .EQ $BE50,51
      1190 XLEN       .EQ $BE52
      1200 XCNUM      .EQ $BE53
      1210 PBITS      .EQ $BE54
      1220 GP.DATE    .EQ $BF90
      1230
      1240 PRAX       .EQ $F941
      1250 CROUT      .EQ $FD8E
      1260 COUT       .EQ $FDED
      1270 *--------------------------------
      1280        .OR $803
      1290 *      .TF B.DATE
      1300 *--------------------------------
      1310 INSTALL
      1320        LDA EXTRNCMD+1    exit to old
      1330        STA EXIT+2        user command
      1340        LDA EXTRNCMD
      1350        STA EXIT+1
      1360        LDA /DATE         become new
      1370        STA EXTRNCMD+1    user command
      1380        LDA #DATE
      1390        STA EXTRNCMD
      1400        RTS
      1410 *--------------------------------
      1420 COMMAND .AS /DATE/
      1430 *--------------------------------
      1440 DATE   LDY #0
      1450        STY POINTER       point to input buffer
      1460        LDA /WBUF
      1470        STA POINTER+1
      1480 .1     LDA (POINTER),Y   scan command
      1490        AND #%01111111
      1500        CMP COMMAND,Y
      1510        BNE ERR.BRIDGE    not mine
      1520        INY
      1530        CPY #4
      1540        BCC .1
      1550 *--- ProDOS bookkeeping ---------
      1560        DEY
      1570        STY XLEN          command length - 1
      1580        INY
      1590        LDA #0
      1600        STA PBITS         don't parse parms
      1610        STA XCNUM         external command
      1620        LDA #RTS1
      1630        STA EXTRNADDR     no execution after
      1640        LDA /RTS1         command parsing
      1650        STA EXTRNADDR+1
      1660 *--- set or display date? -------
      1670        LDA (POINTER),Y
      1680        CMP #$8D          DATE only?
      1690        BEQ RETURN.DATE   yes, return old date
      1700 *--------------------------------
      1710 SET.DATE
      1720        DEY
      1730        JSR ACCUMULATE.DIGITS  get month
      1740        CMP #13
      1750        BCS ERROR         >12 no good
      1760        STA MONTH
      1770        JSR ACCUMULATE.DIGITS  get day
      1780        PHP               save status
      1790        CMP #32
      1800        BCC GO.ON         <=31 ok
      1810
      1820        PLP
      1830 ERR.BRIDGE
      1840        BNE ERROR      ...always
      1850
      1860 GO.ON  STA DAY
      1870        PLP               recover status
      1880        BCC .1            .CC. if "/"
      1890        LDA #85           year defaults to '85
      1900        BNE .2         ...always
      1910 .1     JSR ACCUMULATE.DIGITS  get year
      1920        CMP #100
      1930        BCS ERROR         >99 no good
      1940 .2     PHA               save year
      1950        LDA MONTH         X 0000MMMM
      1960        LSR               M 00000MMM
      1970        ROR               M M00000MM
      1980        ROR               M MM00000M
      1990        ROR               M MMM00000
      2000        STA MONTH
      2010        PLA               M 0YYYYYYY
      2020        ROL               0 YYYYYYYM
      2030        STA GP.DATE+1
      2040        LDA MONTH           MMM00000
      2050        ORA DAY             MMMDDDDD
      2060        STA GP.DATE
      2070 *--------------------------------
      2080 RETURN.DATE
      2090        JSR CROUT
      2100        LDA GP.DATE+1     X YYYYYYYM
      2110        LSR               M 0YYYYYYY
      2120        PHA
      2130        LDA GP.DATE       M MMMDDDDD
      2140        PHA
      2150        ROR               X MMMMDDDD
      2160        LSR               X 0MMMMDDD
      2170        LSR               X 00MMMMDD
      2180        LSR               X 000MMMMD
      2190        LSR               X 0000MMMM
      2200        JSR DEC.OUT       display month
      2210        LDA #"/"          /
      2220        JSR COUT
      2230        PLA               X MMMDDDDD
      2240        AND #%00011111    X 000DDDDD
      2250        JSR DEC.OUT       display day
      2260        LDA #"/"          /
      2270        JSR COUT
      2280        PLA               X 0YYYYYYY
      2290        JSR DEC.OUT       display year
      2300 *--------------------------------
      2310 GOOD.EXIT
      2320        CLC               signal no error
      2330 RTS1   RTS
      2340 *--------------------------------
      2350 ERROR1 PLA               clean up
      2360        PLA               return addresses
      2370 ERROR  SEC               signal error
      2380 EXIT   JMP RTS1          INSTALL makes address
      2390 *--------------------------------
      2400 ACCUMULATE.DIGITS
      2410        LDA #0
      2420        STA ACCUM         zero accumulator
      2430
      2440 .1     INY               next character
      2450        LDA (POINTER),Y
      2460        AND #%01111111    hi-bit off
      2470        CMP #' '          space?
      2480        BEQ .1            back for another
      2490        CMP #'/'          slash?
      2500        BEQ .2            yes, exit .CC.
      2510        CMP #$0D          <CR>?
      2520        BEQ .3            yes, exit .CS.
      2530        CMP #'0'          too small?
      2540        BCC ERROR1        not digit
      2550        CMP #'9'+1        too big?
      2560        BCS ERROR1        not digit
      2570
      2580        AND #%00001111    isolate value
      2590        STA TEMP          stash it
      2600        LDA ACCUM
      2610        ASL               X 2
      2620        ASL               X 4
      2630        ADC ACCUM         X 5
      2640        ASL               X 10
      2650        ADC TEMP          add new digit
      2660        BCS ERROR1        too big
      2670        STA ACCUM
      2680        BCC .1         ...always
      2690
      2700 .2     CLC               .CC. if /
      2710 .3     LDA ACCUM         return value
      2720        BEQ ERROR1        0 no good
      2730        RTS
      2740 *--------------------------------
      2750 DEC.OUT
      2760        LDY #0            zero counter
      2770        SEC               get ready
      2780 .1     SBC #10           subtract 10
      2790        BCC .2            borrow?
      2800        INY               count a 10
      2810        BPL .1         ...always
      2820
      2830 .2     ADC #10           restore borrow
      2840        PHA               save units
      2850        TYA               print 10's count
      2860        BEQ .3            no leading zero
      2870        ORA #$B0          make character
      2880        JSR COUT          print it
      2890 .3     PLA               recover units
      2900        ORA #$B0          make character
      2910        JMP COUT          return through COUT

32-bit Values in Version 2.0 -- A Mixed Blessing | Bob Sander-Cederlof

In previous versions of the S-C assemblers, expressions were evaluated in 16 bits, and symbol values were kept in the table in 16-bit form. Version 2.0 works with 32-bit expressions and symbol values. We added this feature for your benefit, but it may sometimes be a mixed blessing.

For example, Bob Bernard had a problem with a program which assembled perfectly under Version 1.0, but gave countless BAD ADDRESS errors in version 2.0. We traced the problem to his origin statement, which was ".OR -31488". In older versions, -31488 is the same as $8500, but in version 2.0 it is $FFFF8500. The following code will not assemble:

           .OR -31488
      SSS  JMP SSS

Why? Because the value of SSS is also $FFFF8500, and it will not fit in a JMP instruction. In 65816 mode, using a JML instruction, it would be legal.

Two ways to fix come to mind. You normally work in hexadecimal when you are in assembly language, rather than decimal. Therefore, change the origin statement to ".OR $8500". Or, if you really want to use decimal, write ".OR 65536-31488".

Another owner of version 2.0 had a problem with a program that used many macros, and lots of private labels. Private labels are the ones used inside macro definitions, which are written with a colon and a one or two digit number. The private label table normally begins at $FFF and grows downward toward $800. His program assembled with no problems before, but under version 2.0 it got a MEM FULL error. Reason, again, the 32-bit symbol values. Each entry in the private label table now takes two more bytes, so he ran out of space sooner. His solution was to move the beginning of the label table higher.

Apple Assembly Line is published monthly by S-C SOFTWARE CORPORATION, P.O. Box 280300, Dallas, Texas 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 available for $1.80 each (other countries add $1 per back issue for postage).

All material herein is copyrighted by S-C SOFTWARE CORPORATION, all rights reserved. (Apple is a registered trademark of Apple Computer, Inc.)