!lm10
!rm76
Commented Listing of DOS 3.3 $B800-BCFF

As I promised last month, here are the innermost routines of DOS 3.3.  These are the ones which actually read and write  the hardware, and are the most significantly different routines between DOS 3.2.1 and DOS 3.3.

The major difference between the two versions of DOS is the way in which data bytes are coded on the disk.  DOS 3.2.1 maps 256 8-bit bytes into 410 5-bit "nybbles".  DOS 3.3 maps 256 8-bit bytes into 342 6-bit "nybbles".  (The term "nybble" usually means 4 bits, but Apple uses nybble to mean 5- and 6-bits also.)

The two routines PRE.NYBBLE and POST.NYBBLE convert between memory format and disk format.  The DOS 3.3 versions are much shorter and simpler than those of DOS 3.2.1, but they are still hard to visualize and explain.

To write a sector on the disk, RWTS calls PRE.NYBBLE and WRITE.SECTOR.  Here is what happens:
!lm15

1.  The most significant 6 bits of each byte in the buffer are copied into $BB00-BBFF and right-justified with two zero-bits on the left.

2.  The least significant 2 bits of each buffer byte are mapped into $BC00-BC55.

3.  Each 6-bit nybble is used as an index into the NYBBLE.TABLE to pick up a corresponding 8-bit disk code.  (The codes in NYBBLE.TABLE always have the first bit = 1, and never have more than two zero-bits in a row.)
!np
!lm10
To read a sector from the disk, RWTS calls READ.SECTOR and POST.NYBBLE.  Here is what happens:

!lm15
1.  Each disk byte is converted to a 6-bit nybble and copied into the buffer from $BB00 through $BC55.

2.  The nybbles in $BB00-BBFF become the most significant 6-bits of the buffer bytes.

3.  The nybbles in $BC00-BC55 supply the least significant 2-bits for each buffer byte.  This is the reverse of the process above.

!lm10
WRITE.ADDRESS is called from FORMAT, when you are initializing a 16-sector disk.  This subroutine was embedded inside FORMAT in DOS 3.2.1.  READ.ADDRESS, READ.SECTOR, and WRITE.SECTOR are almost identical to the DOS 3.2.1 versions.

Short as they are, I noticed that both PRE. and POST.NYBBLE can be written more efficiently.  Can you see how to save three bytes in PRE.NYBBLE, and two bytes in POST.NYBBLE?

!lm10
!rm76

 SECTOR BUFFER          RWTS.BUFFER.1
7 6 5 4 3 2 1 0        7 6 5 4 3 2 1 0
                00                      BB00
            A B

      G                      G


                55
                56
            C D




                AB
                AC
            E F




                FF                      BBFF


 RWTS.BUFFER.2
7 6 5 4 3 2 1 0
                BC00




    F E D C B A
                BC55


Another Way to Get 80-Columns

Those unpredictable Apple Parallel Interface ROMs!  I wonder if even Apple knows how many different versions they have made, and why!

Anyway, as you know if you have one, some of them make it very difficult to get 80-column printout when you are using the S-C Assembler II.  You should be able to type control-I and "80N", but the assembler sees control-I and does a tab.  Plus you get a syntax error, and the printer is un-hooked.

You can type "$I80N" (where "I" means control-I).  Or you can type "$579:50" (assuming slot 1).

Or, you can make the first line of your program do it.  Type in this line so it will be the first line in your program:
     0000 *I80N
Then type the "MEM" command.  It will tell you the memory address where your source program starts.  Using monitor commands, display about 8 bytes at the beginning of the source program.  Look for the pattern "49 38 30 4E".  Change the "49" to "09", which is ASCII for control-I.  When your program is LISTed or ASMed, the control-I will be caught by Apple's interface and put you into 80-column mode.

So, now you have at least three ways to make it work.  Don't you wish you had the ROM version which is in my Apple Parallel card?  It works right without ANY of the above!  Now if I could only make it work with my screen printing program....
