!pr1
Modifying ProDOS for Non-Standard ROMs...Bob Sander-Cederlof

We have published several times ways to defeat the ROM Checksummer that is executed during a ProDOS boot, so that owners of Franklin clones (or even real Apples with modified monitor ROMs) could use ProDOS-based software.  See AALs of March and June, 1984.

Both of these previous articles are out of date now, because they apply to older versions of ProDOS than are current.  What follows applies to Version 1.1.1 of ProDOS.

There are two problems with getting ProDOS to boot on a non-standard machine.  The first is the ROM Checksummer.  This subroutine starts at $267C in Version 1.1.1, and is only called from $25EE.  The code is purposely weird, designed to look like it is NOT checking the ROMs.  It also has apparently purposeful side effects.  Here is a listing of the subroutine:











<<<<listing of ROM.CHECKSUMMER>>>>












The pointer at $0A,0B was set up to point to $FB09 using very sneaky code at $248A.  Location $2674 initially contains a 0, and $2677 contains an 8.  Only the bytes from $FB09 through $FB10 are checksummed.  Truthfully, "checksummed" is not the correct word.

The wizards who put ProDOS together figured out a fancy function which changes the 64 bits from $FB09 through $FB10 into the value $75.  Their function does this whether your ROMs are the original monitor ROM from 1977-78, the Autostart ROM, the original //e ROM, or any other standard Apple ROM.  The values in $FB09-FB10 are not the same in all cases, but the function result is always $75.  However, a Franklin ROM does not produce $75.  Probably a BASIS also gives a different result, and other clones.  Once $75 is obtained, further slippery code changes the value to $00.

The original Apple II ROM has executable code at $FB09, and in hex it is this:  B0 A2 20 4A FF 38 B0 9E.  All other Apple monitor ROMs have an ASCII string at $FB09.  The string is either "APPLE ][" or "Apple ][".  Notice that the "AND #$DF" in the checksummer strips out the upper/lower case bit, making both ASCII strings the same.

I wrote a test program to print out all the intermediate values during the "Checksummer's" operation.  Here are the results, for both kinds of ROMs.

Original ROM           Later ROMs
LDA AND ADC STA ROL    LDA   AND ADC STA ROL
B0  90  00  90  20     C1    C1  00  C1  82
A2  82  20  A2  44     D0/F0 D0  82  52  A5
20  00  44  44  88     D0/F0 D0  A5  75  EB
4A  4A  88  D2  A4     CC/EC CC  EB  B7  6F
FF  DF  A4  83  07     C5/E5 C5  6F  34  69
38  18  07  1F  3E     A0    80  69  E9  D2
B0  90  3E  C3  9C     DD    DD  D2  AF  5F
9E  9E  9C  3A  75     DB    DB  5F  3A  75

I don't understand why this code gives the same result, but I see it does.  Now, dear readers, tell me how anyone ever figured out what sequence of operations would produce the same result using these two different sets of eight bytes, and yet produce a different result for clones!  If you understand it, please explain it to me!

By the way, here is a listing of my test program:







<<<<listing of test program>>>>
!np






































The checksummer can be defeated.  The best way, preserving the various side effects, is to change the byte at $269F from $03 to $00.  This changes the BNE to an effective no-operation, because it will branch to the next instruction regardless of the status.  Another way to get the same result is to store $EA at both $269E and $269F.  Still another way is to change the "LDA #0" at $26A3,4 to "LDA $0C" (A5 0C), so that either case gives the same result.

If it thinks it is in a valid Apple computer, the checksummer returns a value in the A-register which is non-zero, obtained from location $0C.  The value at $0C has been previously set by looking at other locations in the ROM, trying to tell which version is there.  Part of this code is at $2402 and following, and part is at $2047 and following.  The byte at $0C will eventually become the Machine ID byte at $BF98 in the System Global Page, so it also gets some bits telling how much RAM is available, and whether an 80-column card and a clock card are found.

If you have a non-standard Apple or a clone the bytes which are checked to determine which kind of ROM you have may give an illegal result.  The following table shows the bytes checked, and the resulting values for $0C.  The values in parentheses are not ever checked, but I included them for completeness.  The value in $0C will be further modified to indicate the amount of RAM found and the presence of a clock card.

   Version                FBB3  FB1E  FBC0  FBBF  $0C

   Original Apple II       38   (AD)  (60)  (2F)   00
   Autostart, II Plus      EA    AD   (EA)  (EA)   40
   Original //e            06   (AD)   EA   (C1)   80
   Enhanced //e            06   (AD)   E0   (00)   80
   DEBUG //e               06   (AD)   E1   (00)   80
   Original //c            06   (4C)   00    FF    88
   //c Unidisk 3.5         06   (4C)   00    00    88
   /// Emulating II        EA    8A   (??)  (??)   C0

By the way, ProDOS 1.1.1 will not allow booting by an Apple /// emulating a II Plus, possibly because the standard emulator only emulates a 48K machine.

I have no idea what a clone would have in those four locations, but chances are it would be different.  You should probably try to fool ProDOS into thinking you are in a II Plus, because most clones are II Plus clones.  This means you should somehow change the ID procedures so that the result in $0C is a value of $40.  One way to do this is change the code at $2402 and following like this:

      Standard                     Change to

2402- A9 00    LDA #0        2402- A9 40    LDA #$40
2404- 85 0C    STA $0C       2404- 4C 2E 24 JMP $242E
2406- A3 B3 FB LDX $FBB3

If your clone or modified ROM is a //e, change $2402 to LDA #$80 instead.

You may also need to modify the code at $2047 and following.  If you are trying to fool ProDOS into thinking you are an Apple II Plus or //e, and have already made the change described above, change $2047-9 like this:

      Standard                    Change to

2047- AE B3 FB LDX $FBB3    2047- 4C 6D 20 JMP $206D

No doubt future versions of ProDOS will make provision for clones and modified ROMs even more difficult.  And there are always the further problems encountered by usage of the ROMs from BASIC.SYSTEM and the ProDOS Kernel and whatever application program is running.

I am intrigued about seeing what the minimum amount of code is that can distinguish between the four legal varieties of ROM for ProDOS.  I notice from the table above that I can identify the four types and weed out the ///emulator by the following simple code at $2402:
!lm+5

       LDA $FBB3
       ORA $FB1E
       LDX #3
  .1   CMP TABLE.1,X
       BEQ .2
       DEX
       BPL .1
       SEC
       RTS
*
TABLE.1  .HS BD.EF.AF.4E
TABLE.2  .HS 00.40.80.88
*
  .2   LDA TABLE.2,X
       JMP $242E
!lm-5

With this code installed, all the code from $2047-$206C is not needed, and the JMP $206E should be installed at $2047.  The new code at $2402 fits in the existing space with room to spare.  Can you do it with even shorter code?
