Apple Assembly Line
Volume 2 -- Issue 12September 1982

In This Issue...

Current Advertising Rates

Sorry, it is going up again. For the October 1982 issue the price will be $75 for a full page, $40 for a half page. To be included, I must receive your camera-ready copy by September 20th.

What if you move?

We mail the Apple Assembly Line by bulk mail, unless you have paid for First Class or Overseas postage. If you move, the post office will NOT forward AAL to your new address. Please let us know your new address as soon as you find out what it will be, so you will not miss a single issue!

Quarterly Disks

As you no doubt know, every three months we gather all the source code printed during the quarter on one disk. You can save countless hours of typing and proofreading for only $15 per quarter. Some have elected to establish a standing order with their credit card, or even to prepay for a year at a time.


New Products

ES-CAPE: For really painless Applesoft programming, you need a complete line editor, global search and replace, automatic line numbers, and keyboard macros. At least. ES-CAPE gives you all these and more!

The retail price is $60, but AAL subscribers can get it for only $40 until the end of September. Hurry!

We wrote a nice little reference manual of about 22 pages, but ES-CAPE is so easy to use and remember that you won't need the book very long!

If you already purchased AED II (the earlier version of this editor), Bill Linn has an upgrade offer: Send him your disk plus $10, and you will get the new versions (both regular and language card), the manual, and the reference card.

68000 Macro Cross Assembler: Not content with producing only three cross assemblers based on the S-C Macro Assembler, Bobby Deen has now completed the biggest one of all! This one costs $50, and allows you to assemble Motorola 68000 source programs in your Apple, with all the friendly features of the S-C package.

SYNASSEMBLER: Synapse Software has just started marketing a conversion of the S-C Assembler II Version 4.0 for the Atari 800 or 400. You need 48K RAM and at least one disk drive. The conversion was done by Steve Hales, of Livermore, California. He added global replace and copy commands, so this version falls somewhere between the Apple version 4.0 and the new Macro version. It assembles at about 6500 lines per minute, which is from 50 to over 100 times faster than the Atari ASM/ED program.

Since the Atari does not have nice monitor commands built-in, like the Apple does, Steve added a complete set of monitor commands to SYNASSEMBLER. They look exactly like the Apple monitor commands, except that he added some new ones to allow reading and writing a range of disk sectors, delete the tape I/O commands, and included the old Step and Trace commands which were in Apples before the Autostart ROM.

The price is only $49.95 on disk. A ROM version is available by special order for $89.95. I will carry these, if you want to order from me.


Assembler DirectivesBob Sander-Cederlof

Of all the Apple assemblers on the market, it seems that no two have exactly the same list of assembler directives. Directives, also called "pseudo-ops", are used to control the assembly process and to define data in your programs. When you see a listing of an assembly language program in a magazine, or in this newsletter, or in a book on 6502 programming, you may have to translate the directives to fit the assembler you own.

All directives in the S-C Macro Assembler begin with a period. This helps to distinguish them visually from 6502 and SWEET-16 opcodes. This same convention is used by Carl Moser's (Eastern House Software) MAE assembler, by the MOS Technology and Rockwell assemblers, and some others. Most other assemblers use 3- or 4-character mnemonics beginning with a letter. Which combination of letters cause the assembler to perform a particular function is not standardized at all, but there are enough similarities to make programs readable once you learn the general techniques.

What follows is an alphabetical listing of all the directives I have encountered in various manuals and magazine-published programs. The assemblers represented are coded like this:

     B = Big Mac            SC= S-C Macro Assembler
     K = DOS Tool Kit       T = TED II
     L = Lisa               W = Weller's Assembler
     M = Merlin

In each case I have given a brief description of the directive, and tried to show how to do the same thing in the S-C Macro Assembler. I suggest looking up the S-C directives in the reference manual if you are not sure exactly how to use them.

ADR    ADdRess                 L
Stores the expression as an address, low-order byte first.
SC:  Use .DA directive

ASC    ASCii string definition L K T B M
SC:  Use .AS or .AT directives.

AST    ASTerisks               T B M
Prints the number of asterisks specified on the listing.  Used to 
save space in the source file.
SC: Not needed, because SC compresses repeated characters 
automatically.

BLK    BLinKing characters     L
Generates a string of characters in Apple's FLASH code.
SC: Not available, but a combination of .AS and .HS directives 
will do the job.

BYT    BYTe data               L
Define data value, storing low-order byte only.
SC:  Use .DA with "#" before value.

CHK    CHecKsum                B M
SC:  Not available

CHN    CHaiN to next source    K
SC:  Use .IN directive.

CHR    Set CHaR for REP directive  K
Used to create fancy comments with repeated strings; saves space 
in source file.
SC: Not necessary, because SC compresses repeated characters 
automatically.

.DA    DAta definition         L SC
Apparently Randy borrowed this one from me.  (See the reviews he 
wrote in Call APPLE some time ago.)

DA     Define Address          T B M
Defines a 16-bit value with low-byte first.
SC:  Use .DA directive.

DATA   DATA definition         W
Defines numeric and ASCII data bytes
SC:  Use .DA directive, preceding each value with "#".

DB     Data Byte               T
Defines a data value, only using the low byte of the expression.
SC:  Use .DA directive with "#" before the expression.

DBL    DouBLe precision data   W
Defines 16-bit data values.
SC:  Use .DA directive.

DBY    Double BYte data        L
Generates a 16-bit value and stores it high-byte first.
SC:  Not directly available, but use .DA as follows:
       .DA /expression,#expression

DCI    Define Characters Immed L K T B M
Stores string with sign bit of last byte opposite that of the 
rest of the bytes.
SC:  Use .AT directive.

DCM    DOS CoMmand             L
Issue a DOS command during assembly.  Usually used to BSAVE a 
section of the generated object code.
SC:  Use .TF directive

DDB    Define Double Byte      K B M
Defines a 16-bit value which is stored with the high-byte first.
SC:  Not directly available, but use .DA as follows:
       .DA /expression,#expression

DEND   Dummy END               K
Marks end of a dummy section (see DSECT).
SC:  Not available

DFB    DeFine Byte             K B M
Defines one or more bytes.
SC:  Use .DA, preceding each expression with "#".

DFC    DeFine Character        L (old version)
Data definition, byte expression list
SC:  Use .DA directive, preceding each expression with "#".

DFS    DeFine Storage          L
Reserve a block of bytes.  An optional second operand will cause 
the reserved bytes to be set to the specified value.
SC: Use .BS directive.  No option to set the reserved bytes to a 
specified value.

DO     DO                      K B M
Start a conditional assembly block.
SC:  Use .DO directive.

DPH    DePHase                 L
Terminates a PHS directive.
SC:  Not available.

DS     Data Storage            T K B M
Reserve a block of bytes.
SC:  Use .BS directive.

DSC    Data SeCtion            L (old version)
Not sure what this was for.

DSECT  Dummy SECTion           K
Starts a block in which the object code bytes are not written on 
the output file.
SC:  Not available.

DW     Define Word             K T
Defines a 16-bit value, with the low-byte stored first.
SC:  Use .DA directive.

.EL    ELse                    L SC
For conditional assembly.

ELSE   ELSE                    K B M
For conditional assembly, toggles the truth value from the DO 
directive.
SC:  Use .ELSE directive.

END    END of program          L T B M W
Most assemblers REQUIRE an "END" directive at the end of the 
source code.  S-C allows it but does not require it.
SC:  Use .EN directive.

ENTRY  ENTRY                   K
Indicates a symbol is to be made reference-able from other 
separately-assembled modules.  To be used by a linking loader 
program, which Apple does not provide.
SC:  Not available.

EOM    End Of Macro            B M
Marks end of a macro definition.
SC:  Use .EM directive.

EPZ    Equate Page Zero        L
label  EPZ expression
Defines the label to have the value of the expression, which must 
be from $00 to $FF.  When EPZ-defined labels are used in address 
fields, zero-page addressing mode will be used whenever possible.
SC: Use .EQ directive.  SC automatically uses page-zero mode 
whenever possible.

EQU    EQUate                  L T K B M W
label  EQU expression
Defines the label to have the value of the expression during the 
assembly process.
SC:  Use .EQ directive.

ESP    End ScratchPad          W
Works with SPD to bracket a data section.
SC:  Not needed.

EXP    EXPansion of macros     B M
Controls whether macro expansion code is printed or not on the 
output listing.
SC:  Use .LIST directive.

EXTRN  EXTeRNal                K
Indicates that a label is externally defined.  To be used with a 
linking loader program, which Apple does not provide.
SC:  Not available.

.FI    end of conditional      L SC

FIN    end of conditional      K B M
SC:  Use .FIN directive.

FLS    FLaSH                   B M
Define a string in flashing mode.
SC: Not available, but a combination of .AS and .HS directives 
will do the job.

GEN    GENerate code listing   L
Turns on listing of all object code bytes.
SC:  Not available, object code listing is always on.

HBY    High BYte               L
Define one-byte data value, storing only the high-byte of an 
expressions value.
SC:  Use .DA directive, writing "/" before the value.

HEX    HEXadecimal data        L T B M
label  HEX hexstring
SC:  Use .HS directive.

ICL    InCLude                 L
Really is a CHAIN to next source file.
SC:  Use .IN directive.

.IF    conditional assembly    L
SC:  Use .DO directive.

INV    INVerted characters     L B M
Generates a string of characters in Apple's INVERSE screen code.
SC: Not available, but you can convert to hexadecimal and use .HS 
directive.

LET    label reassignment      L
Same as EQU, except label can be redefined during assembly.
SC:  Not available.

LST    LiST option             L T K B M
Turn assembly listing on or off.
SC:  Use .LIST directive.

MAC    MACro definition        B M
Start a macro definition.
SC:  Use .MA directive.

MSB    Most Signficant Bit     K
Controls whether the ASC directive generates bytes with the first 
bit set or clear.
SC: Use .AS or .AT directives with or without the "-" before the 
first delimiter to indicate the MSB value.

NLS    No List option          L
Turn assembly listing off.
SC:  Use .LIST OFF directive.

NOG    NO Generate             L
Turns off listing of all but first three bytes of any particular 
source line.
SC:  Not available.

OBJ    OBJect address          L T B M
Set actual memory address for assembled object code to be stored 
in.
SC:  Use .TA directive.

ORG    ORiGin                  L T K B M
Set memory address program will execute at.
SC:  Use .OR directive.

PAG    PAGe eject on listing   L T B M
Sends control-L to listing device.
SC:  Use .PG directive.

PAGE   PAGE eject on listing   K
Sends control-L to listing device.
SC:  Use .PG directive.
!np
PAU    PAUse and force error   L B M
SC:  Not available.

PHS    PHaSe                   L
Allows setting ORG without changing OBJ.  Terminated with DPH.
SC:  Not available.

PMC    Present MaCro           B M
Opcode to call a macro.
SC:  Not needed, macros are called by their own names.

PR#    Select printer slot     T
SC: Select before assembly begins using DOS "PR#slot" command, or 
SC "PRT" command.

REL    RELocatable object      K
Causes assembler to generate a relocation dictionary at the end 
of the object file, for use by Apple's relocating loader.
SC:  Not available.

REM    REMark                  W
Used to indicate a comment line.
SC:  Use "*" in first column of label field.

REP    REPeated character      K
Generates a string of repetitions of the current CHR value on the 
output listing.  Used to save space in the source file.
SC: Not needed, because SC automatically compresses repeated 
characters.

SAV    SAVe object code        B M
SC:  Use .TF directive.

SBTL   SuBTitLe                K
Provides a title line for the top of each page of the output 
listing.
SC:  Use .TI directive.

SKP    SKiP lines              K B M
Leaves a specified number of blank lines in the output listing.
SC:  Not available.

SPD    ScratchPaD              W
Works with ESP to bracket a data section.
SC:  Not needed.

STR    STRing                  L
Similar to Lisa's ASC except the first byte output is the length 
of the string.
SC:  labela .DA #labelb
            .AS /string/
     labelb .EQ *-labela-1

SYM    SYMbols                 T
Produces a symbol cross-reference table at end of assembly.
SC:  Not available, but can use Rak-Ware's XREF utility program.

TITL   TITLe                   
TTL    TiTLe                   L
Generates title line at top of each page of listing.
SC:  Use .TI directive.

TR     TRuncate object listing B M
Limit listing of object code to 3 bytes per source line.
SC:  Not available.

USR    USeR directive          L
An extra entry in the directive table for the user to use as he 
sees fit.
SC:  Use .US directive.

;      comment indicator       L
SC: If ";" was in first column, use "*" instead.  If in later 
column, no special character is needed.

=      equate                  B M others
If written with label on left, this is the same as EQU and .EQ 
directives.  If written with "*" on the left, it is the same as 
ORG and .OR directives.

<<<                            B M
Alternate syntax for EOM.
SC:  Use .EM directive.

>>>                            B M
Alternate syntax for PMC.
SC: Not needed, because macros are called by their own names.

Directives in Roger Wagner's Book

If you have been trying to learn using the S-C Assembler with Roger's book "Assembly Lines: The Book", you may have been frustrated by his use of several assembler directives. He discusses directives on pages 16-18, and 55.

On page 16, the first example of the use of directives has two errors. Lines 6 and 7 are written:

     6  OBJ  EQU $300
     7  ORG  EQU $300

But they should be:

     6       OBJ $300
     7       ORG $300

That is, OBJ and ORG are directives, not labels. The top two lines on page 21 are also incorrect, in that the ORG and OBJ directives were typeset to look like labels; they should be moved over to the opcode column, and the "$300" values to the operand column.

In all, Roger uses only five directives in his book: OBJ, ORG, EQU, ASC, and HEX. To use his programs in the S-C assembler, change:

      From                    To
     ----------------        ----------------
     label EQU value         label .EQ value
     label HEX hexdigits     label .HS hexdigits
           HEX hexdigits           .HS hexdigits
     label ASC "characters"  label .AS -"characters"
           ASC "characters"        .AS -"characters"
           OBJ $300 or $302      omit this line
           ORG $300 or $302        .OR $300 or $302

Note that the normal translation of "OBJ" is ".TA"; however, when the address is the same as the ORG/.OR address, it is not necessary to use OBJ/.TA. Furthermore, in the S-C Assemblers you must put the ".OR" line BEFORE the ".TA" line. In Roger's examples these two lines are reversed.


Relocatable Ampersand-VectorSteve Mann

In recent issues of AAL there have been a variety of routines to produce relocatable code. The BSR, BRA and LEAX opcodes in the June issue and the run-anywhere subroutine calls in the July issue are two examples.

However, in making some of my code relocatable, I encountered a new problem with routines that interface with Applesoft programs through the & command. The problem is that the routine doesn't know what address to place in the & jump vector because that address may change with each run.

A rather inelegant solution is to derive the address from Applesoft's pointers, then POKE it into the & vector before calling it. What I wanted was a method to determine the correct address from within the code itself, in much the same way that a non-relocatable program sets up the vector:

     1000        LDA #$4C
     1010        STA AMPER.VECTOR
     1020        LDA #START
     1030        STA AMPER.VECTOR+1
     1040        LDA /START
     1050        STA AMPER.VECTOR+2
     1060 *
     1070 START   ...

I have written a short routine which will handle the initialization at the beginning of relocatable programs, as long as the program's entry point immediately follows, as in the sample program listed below.

The routine works by first jumping to the subroutine at $FF58, which is simply an RTS instruction. As Bob explained in the July AAL, this places the return address on the stack and then pops it back off again. The return address can then be found by reading the first two open bytes below the stack. The TSX instruction in line 1100 loads the offset to those two bytes into the X-register. Lines 1110-1130 load the bytes into the A- and Y-registers.

Now we have the address of the third byte of the JSR RETURN instruction - the MSB in Y and the LSB in A. What we need is the address of the program's entry point, which corresponds to the label START. To get that address, we must add in the length of the rest of the SETUP routine, that is, the difference between the address at START and the address in the Y- and A-registers.

This is handled in lines 1140-1170. Line 1150 adds the offset ($1B for this particular routine) to the low byte of the base address. The extra 1 in the ADC intruction is necessary because the address in Y and A is one less than the actual return address (corresponding to .1). Lines 1160-1170 check for a carry and adjust the high byte if necessary. The entry point address is then saved in the ampersand vector at $3F5-$3F7.

 1000  *--------------------------------
 1010  STACK        .EQ $100
 1020  AMPER.VECTOR .EQ $3F5
 1030  RETURN       .EQ $FF58
 1040  HOME   .EQ $FC58
 1050  *--------------------------------
 1060         .OR $300
 1070         .TF B.AMPEXAMPLE
 1080  *--------------------------------
 1090  SETUP  JSR RETURN        PUT CURRENT ADDR ON STACK
 1100  .1     TSX               GET STACK POINTER FOR OFFSET
 1110         LDY STACK,X       MSB OF ADDR ON STACK
 1120         DEX
 1130         LDA STACK,X       LSB
 1140         CLC
 1150         ADC #START-.1+1   OFFSET TO ENTRY POINT
 1160         BCC .2
 1170         INY               (Y) IS HI BYTE
 1180  .2     STA AMPER.VECTOR+1  LSB OF ENTRY ADDRESS
 1190         STY AMPER.VECTOR+2  MSB
 1200         LDA #$4C            JMP OPCODE
 1210         STA AMPER.VECTOR
 1220         RTS
 1230  *--------------------------------
 1240  START  JSR HOME     CLEAR SCREEN
 1250         NOP          DO WHATEVER
 1260         NOP          YOU LIKE
 1270         RTS

The same principle can be used to set up the monitor's control-Y vector at $3F8-$3FA. As a matter of fact, I usually use a macro with conditional assembly to set up whichever vector I need. Here's the macro:

          1000        .MA VECTOR
          1010        JSR $FF58
          1020 :1     TSX
          1030        LDY $100,X
          1040        DEX
          1050        LDA $100,X
          1060        CLC
          1070        ADC #:3-:1+1
          1080        BCC :2
          1090        INY
          1100 :2     .DO ']1='Y   CTRL-Y?
          1110        STA $3F9
          1120        STY $3FA
          1130        LDA #$4C
          1140        STA $3F8
          1150        .ELSE        OR &?
          1160        STA $3F6
          1170        STY $3F7
          1180        LDA #$4C
          1190        STA $3F5
          1200        .FIN
          1210        RTS
          1220 :3
          1230        .EM

Just include this definition at the beginning of your program. Then macro can then be called like this:

     2000        >VECTOR,Y
2010 START ...

to set the control-Y vector, or like this:

     2000        >VECTOR,&
     2010 START  ...

to set the ampersand vector. (Actually any character other than Y will result in setting the & vector.)

(Note: When I showed this macro to Bob I asked him if the .DO in line 1100 would really work. He looked at it for a minute and said, "yes, it sure will. The assembler's macros are even more powerful than I thought!"...Bill)


About Hardcore MagazineBob Sander-Cederlof

I have received several calls by subscribers who wonder about the ad from Hardcore magazine. The ad prices a subscription at $20, but does not say clearly what $20 buys.

To my knowledge, HARDCORE has published two issues so far: the first one about a year ago, and the second about six months ago.

Inside the front cover of the first issue you will find the following message:

"Attention Subscribers: Although presently only a quarterly magazine, HARDCORE Computing will go bimonthly and then monthly as soon as possible. Meanwhile, your one-year subscription is for the 4 quarterly issues plus 8 UPDATEs (printed on the other 8 months) and all ALERT Bulletins sent out whenever we feel information is too important to wait. The UPDATEs will be reprinted in part or in whole in the next magazine. The magazines, UPDATEs, and ALERT Bulletins comprise the subscription package."

I have talked with the publisher, Chuck Haight, several times on the phone. I believe he intends to fulfill every subscription, but he is having trouble getting the magazine out on a regular schedule. I asked him how often the magazine is published, and he answered "Very infrequently". He did re-assure me that a subscription buys four issues.

Note that Softkey Publishing is another company with the same people. Two callers indicated they are quite satisfied with the software they bought from Softkey.


No More Paddle InteractionMike Laumer

While working on the FLASH! Integer BASIC Compiler I ran into a nasty little problem because the compiled code ran too fast! That's right, too fast. The old problem with reading the game paddles too soon after one another rose to byte (punny huh!) me once again.

Basically the game paddle problem is that they are read with a variable time delay loop. Because one paddle may read significantly faster than another, and the paddles have only one trigger to fire all four of the paddles, you might process the data fast enough to be ready to read the next paddle before it has finished its previous time delay. This problem is real and occurs in many of the game programs to be found on the Apple. Even Raster Blaster has the problem in its jittery ball release thrust adjuster.

In the example below paddle 0 and 1 are triggered by the $C070 paddle I/O trigger address. But because paddle 0 has a smaller value, it finishes before paddle 1. If you read one paddle after another with little other processing then one paddle seems to affect the value of the other one. Many programmers have shown this problem to their dealer thinking that they have found a new bug in the Apple but the only problem (if one exists) is the lack of independent paddle triggers for each of the four paddles.

The problem appears if you use the following BASIC program and play with the paddle adjustments. Turn paddle 1 to the middle of its scale and paddle 0 to the low end of its scale and you will see changing paddle 0 affects the value read for paddle 1. You will find that paddle 1 will vary by 20-40 counts without even touching it.

   10 PRINT PDL(0),PDL(1) : GOTO 10

      +-------+
     -|       |-----------------     paddle 0

      +---------------+
     -|               |----------    paddle 1
     ^                ^
     :                : paddle expires
     :
     paddles are triggered at this time

So what can be done about the problem? What I did is design a routine that reads the paddle without triggering it and waits for the paddle to shut off. This is easily done by calling the monitor paddle read routine at $FB21, skipping the trigger instruction at $FB1E. This takes care of much of the problem, but I still found it necessary to add a tiny delay loop before triggering the paddle. The extra delay is probably due to the remaining charge in the internal capacitor in the timer chip.

The assembly language routine which follows is basically what I added to the FLASH! compiler runtime package to take care of its being too fast for its own good! This explains 14 of the 36,000 bytes of object code in the FLASH! Compiler system. There is also a DEMO program which reads both paddles and displays the values in hexadecimal so you can test the routine.

 1000  *--------------------------------
 1010  * READ PADDLES
 1020  * PADDLE NUMBER IN A REGISTER
 1030  * USES A,X,Y REGISTERS
 1040  * RETURNS PADDLE VALUE IN Y REGISTER
 1050  *--------------------------------
 1060  * THIS PADDLE READ ROUTINE
 1070  * WILL PREVENT ALMOST ALL PADDLE
 1080  * INTERACTION PROBLEMS DUE TO
 1090  * ONLY 1 PADDLE TRIGGER FOR
 1100  * ALL PADDLES.
 1110  *--------------------------------
 1120  MON.PREAD .EQ $FB1E
 1130  *--------------------------------
 1140  READP  AND #3           PDL 0 - 3
 1150         TAX
 1160         JSR MON.PREAD+3  MAKE SURE PADDLE IS READY
 1170         LDY #0
 1180  .1     DEY              KLUDGE DELAY FOR
 1190         BNE .1              CIRCUIT READY
 1200         JMP MON.PREAD    TRIGGER AND READ
 1210  * PADDLE RESULT IN Y REGISTER
 1220  *--------------------------------
 1230  DEMO   LDA #0       READ PADDLE 0
 1240         STA $24      HTAB COLUMN 1
 1250         JSR READP
 1255         TYA          VALUE TO A
 1260         JSR $FDDA    PRINT VALUE IN HEX
 1270         INC $24      LEAVE SPACE ON SCREEN
 1280         LDA #1       READ PADDLE 1
 1290         JSR READP
 1295         TYA          VALUE TO A
 1300         JSR $FDDA    PRINT VALUE IN HEX
 1310         JMP DEMO     AGAIN AND AGAIN...

An Apple BibliographyBob Sander-Cederlof

Bob Broedel has been keeping track of all the books, magazines, etc. that are of interest to Apple owners. The last time I saw the list (May 1982), it was ten pages, two columns. Each entry includes all the bibliographic data Bob knows, so that you can find the items you want.

This is the most complete list I have ever seen. If you want a copy, he will send you one for $2. Write to Bob Broedel, P. O. Box 20049, Tallahassee, FL 32304.


Some Fast Screen TricksBob Sander-Cederlof

Sometimes the standard Apple Monitor screen functions are too slow. No reflection on Steve Wozniak, because he wrote them to be general and compact rather than quick.

I am thinking particular of the screen clear (HOME to Applesoft users) and the screen scroll subroutines. They were both written to operate on a text window, not necessarily the whole screen. But most of the time you do want to clear or scroll the whole screen.

The primary text screen memory is mapped into the addresses from $400 through $7FF, but not in an obvious or straightforward way. This table shows the actual memory addresses for each screen line:

     Line Addresses     Line Addresses     Line Addresses
       0  $400-$427       8  $428-$44F      16  $450-$477
       1  $480-$4A7       9  $4A8-$4CF      17  $4D0-$4F7
       2  $500-$527      10  $528-$54F      18  $550-$577
       3  $580-$5A7      11  $5A8-$5CF      19  $5D0-$5F7
       4  $600-$627      12  $628-$64F      20  $650-$677
       5  $680-$6A7      13  $6A8-$6CF      21  $6D0-$6F7
       6  $700-$727      14  $728-$74F      22  $750-$777
       7  $780-$6A7      15  $7A8-$7CF      23  $7D0-$7F7

Note that 120 consecutive bytes are used for three text lines spaced at an 8-line interval. Then 8 bytes are not used. Then the next 120, and so on. Those 8 sets of 8 bytes that are not used by the screen mapping are used by peripheral cards and DOS for temporary storage. In the standard Apple Monitor subroutines, a subroutine named BASCALC at $FBC1 calculates the starting address for a specified line. Then the various screen functions use that address, which is kept up-to-date in BASL,BASH ($28,29).

In the listing that follows, I have included fast subroutines to clear the entire text screen (CLEAR); to set the entire text screen to whatever character is in the A-register (SET); to clear the entire Lo-Res Graphics screen (GCLEAR); and to scroll the entire text screen up one line. For demonstration purposes, I also wrote routines to set the entire screen to each value from $00 through $FF; to alternate the screen between solid black and solid white until a key is pressed; to scroll end-around, placing the old top line on the bottom of the screen while moving the rest of the lines up; and to continuously scroll end-around until a key is pressed.

For comparison, I counted that the Wozniak's screen clear takes 15537 microseconds; mine takes only 5410 microseconds. The fastest possible would be one LDA #$A0 followed by 960 "STA $xxx" and an RTS; that would take 3848 microseconds. (All these times round off the Apple's cycle time to one microsecond; actually it is a little faster.)

 1000  * S.SCREEN TRICKS
 1010  *--------------------------------
 1020  *   FAST SCREEN CLEAR SUBROUTINE
 1030  *--------------------------------
 1040  GCLEAR LDA #0
 1050         .HS 2C       SKIP OVER NEXT TWO BYTES
 1060  CLEAR  LDA #$A0
 1070  SET    LDY #119
 1080  .1     STA $400,Y   LINES:  0  8 16
 1090         STA $500,Y           2 10 18
 1100         STA $600,Y           4 12 20
 1110         STA $700,Y           6 14 22
 1120         STA $480,Y           1  9 17
 1130         STA $580,Y           3 11 19
 1140         STA $680,Y           5 13 21
 1150         STA $780,Y           7 15 23
 1160         DEY
 1170         BPL .1
 1180         RTS
 1190  *--------------------------------
 1200  *      SET SCREEN TO ALL VALUES
 1210  *--------------------------------
 1220  SETALL LDX #0
 1230  .1     TXA
 1240         JSR SET
 1250         INX
 1260         BNE .1
 1270         RTS
 1280  *--------------------------------
 1290  *   ALTERNATE SCREEN UNTIL KEY PRESSED
 1300  *--------------------------------
 1310  ALTER  LDA #$20     INVERSE BLANK
 1320         JSR SET
 1330         JSR CLEAR
 1340         LDA $C000
 1350         BPL ALTER
 1360         STA $C010
 1370         RTS
 1380  *--------------------------------
 1390  *   FAST SCROLL UP SUBROUTINE
 1400  *--------------------------------
 1410  SCROLL LDY #119
 1420  .1     LDA $400,Y   SAVE LINES: 0 8 16
 1430         PHA
 1440         LDA $480,Y   MOVE 1>0, 9>8, 17>16
 1450         STA $400,Y
 1460         LDA $500,Y   MOVE 2>1, 10>9, 18>17
 1470         STA $480,Y
 1480         LDA $580,Y   MOVE 3>2, 11>10, 19>18
 1490         STA $500,Y
 1500         LDA $600,Y   MOVE 4>3, 12>11, 20>19
 1510         STA $580,Y
 1520         LDA $680,Y        ET CETERA
 1530         STA $600,Y
 1540         LDA $700,Y
 1550         STA $680,Y
 1560         LDA $780,Y
 1570         STA $700,Y
 1580         PLA          MOVE 8>7, 16>15
 1590         CPY #40
 1600         BCC .2       DISCARD OLD LINE 0
 1610         STA $780-40,Y
 1620  .2     DEY
 1630         BPL .1
 1640         RTS
 1650  *--------------------------------
 1660  *   SCROLL AROUND, MOVING TOP LINE TO BOTTOM
 1670  *--------------------------------
 1680  SCR    LDY #39      SAVE TOP LINE ON STACK
 1690  .1     LDA $400,Y
 1700         PHA
 1710         DEY
 1720         BPL .1
 1730         JSR SCROLL   SCROLL SCREEN UP ONE LINE
 1740         LDY #0       STORE OLD TOP LINE
 1750  .2     PLA             ON BOTTOM OF SCREEN
 1760         STA $7D0,Y
 1770         INY
 1780         CPY #40
 1790         BCC .2
 1800         RTS
 1810  *--------------------------------
 1820  *   ROTATE SCREEN UNTIL KEY PRESSED
 1830  *--------------------------------
 1840  S      JSR SCR      SCROLL AROUND ONCE
 1850         LDA $C000    ANY KEY PRESSED?
 1860         BPL S        NO, SCROLL AGAIN
 1870         STA $C010    YES, CLEAR STROBE
 1880         RTS          ...AND RETURN

Right arrow for the VIDEX patchesMike Laumer

The VIDEX 80 column board patches for the S-C Macro Assembler in last months Apple Assembly Line was a welcome article for me. You see I bought a VIDEX board last November but have no software to run it. I've been planning to write a program development editor similar to the one I used at Texas Instruments, but so far I haven't had the time between the FLASH! compiler, MIKE'S MAGIC MATRIX and the American Heart association CPR Training system.

The patches were very usable, but a major problem still existed to prevent my use on a regular basis. The right arrow key would not copy characters from the VIDEX screen. Try to copy a file name from your catalog with that limitation!

I knew it could be done, because the VIDEX software in ROM has to do that function. Don Taylor mentioned last month that he didnt know the right routine to call and his ROM differed from the listing in the VIDEX manual. My listing was a little off also from my ROM, but I didn't care becase I wasn't going to call the ROM routines.

I used the VIDEX manual's listings to locate the section that performed the copy-character-from-screen function and used similar code in the RDKEY routine of last month's VIDEX patches for the Macro assembler. The 'BNE' to '.3' was changed to go to 'CTRLU' and the copy function coded to process the right arrow key for the VIDEX 80 column board.

I needed two temporary variables to save the X- and Y- registers, so I used the first two bytes of the normal Apple text screen at $400 and $401. Another temporary variable is at $402. Since the normal Apple text display is not operative while the VIDEX is enabled you can use it for temporary variable space without it affecting the screen display. If you try a trick like this some time, you must be careful because some of the monitor routines like HOME and SCROLL can easily zap your storage when you least expect it.

With this new capability of the right arrow key functioning as expected, I am able to use the VIDEX patches often in my software development work. But there are a few problems left yet to solve that I didn't get to look into before writing this article. They are:

  1. A RETURN key should clear to the end of line on line input, but not EDIT input.
  2. The control character display features are not handled very well by the VIDEX patches.
  3. The patches blow up on Reset. (I think.)
  4. The patches blow up on INT or FP commands.
  5. The patches don't work very well when you use MNTR command.
  6. All calls to $FC9C (the Monitor clear to end of line routine) should send $9D to the VIDEX board.
  7. Right arrow, left arrow, and any printing key cause the entire EDIT line to be redisplayed. The flicker is somewhat annoying.

The listing that follows should replace lines 4020 through 4420 of the listing on pages 21 and 22 of the August 1982 issue.

The source code on the AAL Quarterly Disk #8 will have these lines already merged with Don Taylor's patches.

4020 *--------------------------------
4025 V.BASEL .EQ $478+SLOTNUM
4030 V.BASEH .EQ $4F8+SLOTNUM
4035 V.CHORZ .EQ $578+SLOTNUM
4040 V.XSAV1 .EQ $402
4045 V.OLDCHAR .EQ $678
4050 *
4055 V.DEV0  .EQ SLOTNUM*16+$C080
4060 V.DISP0 .EQ $CC00
4065 V.DISP1 .EQ $CD00
4070 *--------------------------------
4075 *
4080 RDKEY  LDA KEYBOARD
4085        BPL RDKEY
4090        STA KEYSTROBE
4095        ORA #$80
4100        CMP #$81     Shift lock?
4105        BNE .1
4110        .DO LCVERSION
4115        JSR UNPROTECT.LC.RAM
4120        .FIN
4125        LSR SCM.SHIFT.FLAG
4130        BPL .2       Return with errant key
4135 .1     CMP #$9A     Shift unlock?
4140        BNE CTRLU    No, return with key
4145        .DO LCVERSION
4150        JSR UNPROTECT.LC.RAM
4155        .FIN
4160        SEC
4165        ROR SCM.SHIFT.FLAG
4170 .2     LDA #$96     Return with errant key
4175        .DO LCVERSION
4180        BIT $C080    Reprotect LC RAM
4185        RTS
4190 *
4195 UNPROTECT.LC.RAM
4200        BIT $C083    Enable Bank 2
4205        BIT $C083
4210        .FIN
4215        RTS
4220 *
4225 CTRLU  CMP #$95     CTRL-U COPY KEY
4230        BNE .3
4235        STX $400
4240        STY $401
4245        LDA V.CHORZ
4250        JSR PSNCALC
4255        BCS .1
4260        LDA V.DISP0,X
4265        BCC .2
4270 .1     LDA V.DISP1,X
4275 .2     ORA #$80
4280        STA V.OLDCHAR
4285        LDX $400
4290        LDY $401
4295 .3     RTS
4300 *
4305 PSNCALC CLC
4310        ADC V.BASEL
4315        STA V.XSAV1
4320        LDA #0
4325        ADC V.BASEH
4330        LSR
4335        PHP
4340        AND #3
4345        ASL
4350        ASL
4355        TAY
4360        LDA V.DEV0,Y
4365        PLP
4370        LDX V.XSAV1
4375        RTS
4380 *--------------------------------

Special Note: S-C Macro Cross Assembler
Motorola 6800/6801/6802 Version
Bob Sander-Cederlof

The 6801 microprocessor is an enhanced version of the 6800 cpu. It has 11 new opcodes, plus an additional addressing mode for the JSR instruction. Be sure not to use any of these new opcodes if you are assembling code which must execute in a 6800 system!

     JSR direct   (9d xx)
     ABX    Add B to X
     ADDD   Add M,M+1 to D
     ASLD   Arithmetic shift left D
     BRN    Branch Never
     LDD    Load D from M,M+1
     LSRD   Logical shift right D
     MUL    Multiply A * B into D
     PSHX   Push X
     PULX   Pull X
     STD    Store D at M,M+1
     SUBD   Subtract M,M+1 from D

All except "JSR direct" are easy to avoid when programming for a 6800 cpu: simply don't use them. But the assembler may generate the new "JSR direct" instruction automatically.

If you attempt to use "JSR addr" where "addr" is in page zero, the new direct addressing mode will be used. If you are programming for a 6800 cpu, that is not acceptable. To override the assembler's choice, use ".DA #$BD,addr". You can use a macro "JSR" if you have a lot of them.


A Note on the Underline CursorBob Sander-Cederlof

Bill Linn's "Blinking Underline Cursor" program generated a lot of interest. However, Allan Blackburn from Fort Worth had a problem with it:

"It works just fine, until you hit RESET or re-boot...then it must be BRUN again to get it back. You can't enter monitor and type 300G, or use CALL 768 from Applesoft. Why doesn't calling the routine reset KSWL and KSWH? It should, but I always end up with $9E81 there. Even though lines 1210-1250 store $09 in $38 and $03 in $39, it seems they never get there. Can you explain this? Please?

Sure, Allan. Line 1250 needs to be changed from RTS to JMP $3EA.

This is a common problem. I had it myself back when DOS first came out. For the first year or so we only had a tiny preliminary manual, and the subject wasn't covered. Now the DOS manual is so large we forget to read it or where to find the information. Look on pages 100-105 of the DOS manual and you will find a full explanation.

Briefly, here is what happens. Lines 1210-1250 DO store the address $309 into #38 and $39. But the next time you print a character, DOS gets control and stores its own input address right on top of yours. DOS's input address is $9E81.

The same thing happens in Applesoft programs if you use IN#1 (for example) instead of PRINT CHR$(4)"IN#1", and then print a character. Note 7b on page 105 tells about CALL 1002, which is $3EA.


Apple Assembly Line is published monthly by S-C SOFTWARE, P. O. Box 280300, Dallas, TX 75228. Phone (214) 324-2050 Subscription rate is $15 per year, in the USA, sent Second Class Mail; $18 per year sent First Class Mail in USA, Canada, and Mexico; $28 per year sent Air Mail to other countries. Back issues are available for $1.50 each (other countries add $1 per back issue for postage).

All material herein is copyrighted by S-C SOFTWARE, all rights reserved. Unless otherwise indicated, all material herein is authored by Bob Sander-Cederlof. (Apple is a registered trademark of Apple Computer, Inc.)