What follows is a comp.sys.apple2 newsgroup discussion from July 8, 1995 by David Empson about an accidental buggy release of an Apple IIgs ROM 03 and analysis of the changes made before actual production. I have included the sections of the System 601 source code assembled by me which were referenced.
Please excuse the rough wordwrapping here. I can provide a cleaner document if someone wants it. I am open to suggestions of where else to post this stuff
- enjoy !!
Differences between the two versions of the ROMs in the ROM 3 IIgs
by David Empson (
dem...@actrix.gen.nz)
Apple released two sets of ROMs for the "Apple IIgs with 1 megabyte of
memory", popularly known as the "ROM 3 IIgs".
The original set of ROMs has the serial numbers 341-0728 and 341-0729.
These are very rare: I only know of one IIgs that has been confirmed
to have these ROMs. [Make that two now]
The revised ROMs have the serial numbers 341-0748 and 341-0737. These
are by far the most common.
I have done a byte-for-byte comparison on the old and new ROMs, and
have identified the following differences:
Banks $FC and $FD are identical. [This means that ROM 341-0728 is
identical to ROM 341-0737.]
Bank $FE has changes in the following locations:
$FE345F (branch destination) [1] offset 6CD (referenced below)
$FE3466 (branch destination) [2] offset 6D4 (referenced below)
$FE3475 to $FE349D (code changes) [3] offset 6E3 to 70B (referenced below)
Bank $FF has changes in the following locations:
$FF6232 (branch destination) [4] see F6232 referenced below
$FF623A (low byte of table address)[5] see F6239 referenced below
$FF623E (branch destination) [6] see F623D referenced below
$FF6242 to $FF6260 (code and data moved due to an inserted BRA instruction at $FF6242) [7] see F6242 referenced below
$FFFFF6 to $FFFFF7 (ROM checksum) [8] see FFFFF6 referenced below (I put in value $6250 from actual ROM 03 binary)
The Bank $FE Changes
====================
The changes in bank $FE are within an internal QuickDraw II routine
that calculates the memory address of a line, based on the current
LocInfo structure (i.e. pixel image base address, boundary rectangle
and row width in bytes).
The earlier version of the ROM 3 has a bug in this routine: if the row
width or line number is too large, the wrong address will be
calculated and QuickDraw will draw the object in the wrong place. With
the standard onscreen GrafPort (or an offscreen one of the same size),
this will not be a problem unless you try to draw past line 1023. With
a larger drawing area, as might be used by a high resolution printer
driver, for example, the line number limit is much lower.
For example, a driver printing at 300 dpi on paper 8 inches wide will
have 2400 pixels per line, requiring 600 bytes per line in 640 mode (2
bits per pixel). The bug in this routine will manifest itself if the
line number is 128 or higher (about a third of an inch down the page).
This routine is only used to calculate the start address of an object -
subsequent lines will be drawn relative to the first address. This
means that a printer driver running at high resolution will not hit
this bug if the object starts at the top of the page (or very close to
it), until it tries to print the second band pass, which will start
further down the page.
This bug was noticed by Paul Bauer (
pba...@mit.edu) when trying to
print a vertical line in the AppleWorks GS Page Layout module, using
the Harmonie Hewlett-Packard LaserJet II driver at 300 dpi. The first
part of the line was correct, but it had a break in it a certain
distance down the page and was drawn at the wrong horizontal position.
The problem was not evident on other ROM 3 machines, or if a lower
resolution was used. Paul had the older ROMs in his ROM 3.
The revised ROM 3 does not have this bug: it uses the Integer Math
toolset _Multiply routine, which can handle up to 65535 rows and 65535
bytes per row. The ROM 1 also uses _Multiply for this routine.
It looks like an attempt was made to do a much faster version of the
routine in the ROM 3 by doing the multiplication with a special case
routine, but it didn't allow for large enough images; Apple then went
back to the original code for the fixed version. There is also some
code in both ROM 3 versions to do a very quick calculation if the
pixel image width is 160 bytes and the line number is less than 400,
which will cover all onscreen drawing and a large proportion of
offscreen drawing as well.
The Bank $FF Changes
====================
The main group of changes appear to be part of the SmartPort code. The
routine that was modified is checking for a SmartPort INIT call, and
also checking for the presence of a ROMdisk. I haven't looked into
this one in detail, but I think the older version of the ROM 3 has a
bug that prevents it from using a ROMdisk at all (or in certain circumstances).
The other change is to the pair of bytes at $FFFFF6 and $FFFFF7. These
are in the middle of the interrupt vector table for the 65816, and are
defined as "reserved" in the 65816 data sheet (they would be the
emulation mode BRK vector, if it wasn't combined with IRQ at
$FFFFFE/F). The value in this location is meaningless and pretty
useless, so I suspect it contains a checksum of the ROM (or forces the
checksum of the ROM to add up to some magic number when every byte or
word is added, which is basically the same thing). The value is $67E9
for a ROM 1, $A751 for an old ROM 3, and $6250 for a new ROM 3. Part
of the patch to the QuickDraw routine involved replacing several
consecutive bytes with zeros, which may account for the "lower"
checksum in the new ROM.
Excerpt of System 601 source assembled file GSToolbox/QD/rects.asm :
*********************************************************************
*
* SetFirstDestRef
*
* History
* 8/4/87 GCP Installed patch version of this routine
*
* 2/25/89 Mensch
* Added a faster inline multiply just for grins. Speed this routine up
* quite a lot and seems to complement those new faster rectangles pretty
* well.
*********************************************************************
006B5 0000 SetFirstDestRef PROC EXPORT
006B5 0000 000000BC Mult1 equ DestRef
006B5 0000 000000BE Mult2 equ DestRef+2
006B5 0000
006B5 0000 F4 0000 5 pea 0 ;assume its positive
006B8 0003 A5 A6 4 lda Y1 ;now figure out where in the
006BA 0005 85 40 4 sta CurrentY ;pixel map this scan line
006BC 0007 38 2 sec ;is
006BD 0008 E5 14 4 sbc BoundsRect
006BF 000A
006BF 000A
006BF 000A 10 06 006C7 2 bpl ItsPositive
006C1 000C
006C1 000C 83 01 5 sta 1,s
006C3 000E 49 FFFF 3 eor #$FFFF
006C6 0011 1A 2 inc a
006C7 0012
006C7 0012 ItsPositive
006C7 0012 ; since we are resetting destref, lets have some fun and use it for a temp
006C7 0012 ; Coming into this loop <A> contains the scan line number
006C7 0012 ; so we first see if we rolled off the "Dave" limit
006C7 0012 85 BC 4 sta Mult1 ; lets save it for a sec as an operand.....
006C9 0014 C9 0190 3 cmp #400 ; see if we rolled over the top of the mult below
006CC 0017 B0 1B 006E9 2 bge @DoMultSlow [1] PROTOTYPE bug references here
006CE 0019 A5 12 4 lda <Width
006D0 001B C9 00A0 3 cmp #$00A0 ; is it scan line size???
006D3 001E D0 14 006E9 2 bne @DoMultSlow [2] PROTOTYPE bug references here
006D5 0020 A5 BC 4 lda Mult1 ; get our number back...
006D7 0022 0A 2 asl a ; multiply it by 32 first..
006D8 0023 0A 2 asl a
006D9 0024 0A 2 asl a
006DA 0025 0A 2 asl a
006DB 0026 0A 2 asl a
006DC 0027 85 BC 4 sta Mult1
006DE 0029 0A 2 asl a
006DF 002A 0A 2 asl a
006E0 002B 18 2 clc
[3] PROTOTYPE bug references this section (probably section rem'd out below)
006E1 002C 65 BC 4 adc Mult1
006E3 002E F4 0000 5 pea 0
006E6 0031 48 4 pha
006E7 0032 80 0D 006F6 3 bra @DoMultDone
006E9 0034 @DoMultSlow
006E9 0034 ;
006E9 0034 ; the damned fast multiply that I put in fails on enormous drawings (Damn)
MPW IIGS Assembler - Ver 1.2 QD Rects GS ROM 2.0 11-Apr-13 Page 158
Copyright Apple Computer, Inc. 1987-1990
Loc SLoc Object Code Addr T M Source Statement
006E9 0034 ; so, we put back the old multiply routine so we can ship the damned disk!
006E9 0034 ; Mensch 6/13/89
006E9 0034 48 4 pha
006EA 0035 48 4 pha
006EB 0036 D4 BC 6 pei Mult1
006ED 0038 D4 12 6 pei Width
006EF 003A _Multiply
006EF 003A A2 090B 3 1 ldx #$090B
006F2 003D 22 E10000 8 1 jsl $E10000
006F6 0041 ;
006F6 0041 ; Fast multiply routine, just in case I need it for something!
006F6 0041 ;
006F6 0041 ; ldx #0 ; init our carry over area
006F6 0041 ; lda #0
006F6 0041 ;@dm0010 lsr Mult1 ; shift for first test
006F6 0041 ; beq @dmLastOne ; handle the last multiply
006F6 0041 ; bcc @dm0020
006F6 0041 ; clc
006F6 0041 ; adc Mult2
006F6 0041 ; bcc @dm0020 ; if carry clear we didn't role the bank yet..
006F6 0041 ; inx ; if carry set, role the bank!
006F6 0041 ;@dm0020 asl Mult2
006F6 0041 ;
006F6 0041 ; Bug fix here...
006F6 0041 ; bcc @dm0010
006F6 0041 ; inx
006F6 0041 ; bra @dm0010
006F6 0041 ;@dmLastOne bcc @DoMultDone
006F6 0041 ; clc
006F6 0041 ; adc Mult2
006F6 0041 ; bcc @DoMultDone ; carry clear no bank role
006F6 0041 ; inx
006F6 0041 ;olddoMultDone phx ; push the high word
006F6 0041 ; pha ; and the low word
006F6 0041 @DoMultDone
006F6 0041
006F6 0041 A3 05 5 lda 5,s
006F8 0043 D0 0E 00708 2 bne MustSubtract
006FA 0045
006FA 0045 68 5 pla
006FB 0046 18 2 clc
006FC 0047 65 0E 4 adc ImageRef ; low word of image ref
006FE 0049 85 BC 4 sta DestRef ;goes into dest ref
00700 004B 68 5 pla
00701 004C 65 10 4 adc ImageRef+2 ;hi word of image ref
00703 004E 29 00FF 3 and #$00FF ;mask off higest byte for system wins
00706 0051 80 0D 00715 3 bra FinishKludge
00708 0053
00708 0053 MustSubtract ;
00708 0053 A5 0E 4 lda ImageRef ;subtract result from pointer to image
0070A 0055 38 2 sec
0070B 0056 E3 01 5 sbc 1,s
end of [3] PROTOTYPE section referenced above
0070D 0058 85 BC 4 sta DestRef
0070F 005A A5 10 4 lda ImageRef+2
00711 005C E3 03 5 sbc 3,s
00713 005E FA 5 plx
00714 005F FA 5 plx
00715 0060
00715 0060 85 BE 4 FinishKludge sta DestRef+2
00717 0062 68 5 pla
00718 0063
00718 0063 ;-------------------------------------------------------
00718 0063 ;
00718 0063 ; Now set data bank to bank containing this scan line
00718 0063 ;
00718 0063 D4 BD 6 pei DestRef+1
0071A 0065 AB 4 plb
0071B 0066 AB 4 plb
0071C 0067
0071C 0067
0071C 0067 60 6 rts
0071D 0068
0071D 0068
0071D 0068 ENDP
Excerpt of System 601 source assembled file GSToolbox/GSFirmware/SmartPort/SmartPort.aii :
F622B 622B TITLE 'Calling the ROMDISK'
F622B 622B ********************************************************
F622B 622B *
F622B 622B * This routine will search for the RomDisk
F622B 622B * driver on an INIT call only. All other
F622B 622B * calls will dispatch to the RomDisk driver.
F622B 622B *
F622B 622B ********************************************************
F622B 622B 00FF622B ROMDISK EQU *
F622B 622B A5 45 3 LDA CMDCode ; is it an init call?
F622D 622D 29 3F 2 AND #$3F
F622F 622F C9 05 2 CMP #InitCMD
F6231 6231 D0 11 F6244 2 BNE @20 ; no, then dont search [4] PROTOTYPE bug references this branch
F6233 6233 A2 05 2 LDX #5
F6235 6235 00FF6235 @10 EQU *
F6235 6235 BF F00000 5 LDA >$F00000,x ; get romdisk string
F6239 6239 DF FFFFFF 5 CMP >rdid,x ; and check it [5] PROTOTYPE bug references this table address
F623D 623D D0 16 F6255 2 BNE @40 ; if not same, bomb out [6] PROTOTYPE bug references this branch
F623F 623F CA 2 DEX
F6240 6240 10 F3 F6235 2 BPL @10
F6242 6242 ; The following line of code was the last change made to the Tenspeed FF ROM before Final
F6242 6242 80 06 F624A 3 BRA @25 ; THE VERY COSTLY MISSING BRA INSTRUCTION JOA MAY 89 [7] PROTOTYPE bug
F6244 6244 AF E10FBD 5 @20 LDA >ROMUnit ;does a ROMDisk exist?
F6248 6248 F0 0B F6255 2 BEQ @40 ;nope. so return NoDevice Connected!
F624A 624A 22 F00007 8 @25 JSL >RomDriver ; dispatch to romdisk
F624E 624E 18 2 CLC
F624F 624F A5 50 3 LDA statbyte
F6251 6251 F0 01 F6254 2 BEQ @30
F6253 6253 38 2 SEC
F6254 6254 00FF6254 @30 EQU *
F6254 6254 60 6 RTS
F6255 6255 00FF6255 @40 EQU *
F6255 6255 38 2 SEC ; flag error
F6256 6256 A9 28 2 LDA #$28
F6258 6258 85 50 3 STA StatByte
F625A 625A 60 6 RTS
F625B 625B MSB on
F625B 625B D2CFCDC4C9D3 RDID DC.B 'ROMDIS'
F6261 6261 *
F6261 6261 FillTo SPENDING ;fill my alloted space
F6400 6400 *
F6400 6400 ENDP
Excerpt of System 601 source assembled file GSToolbox/GSFirmware/Monitor/Autostart.aii :
FFFF4 FFF4 00FFFFF4 ECOP EQU * ;Maintained entry point $FFF4
FFFF4 FFF4 4A7B DC.W TOECOP ;Emulation COP interrupt vector
FFFF6 FFF6
FFFF6 FFF6 00FFFFF6 CHKSUMTWEAK EQU *
FFFF6 FFF6 6250 DC.W $6250 ;Modify to make bank FE/FF checksum=$1234 [8] PROTOTYPE reference
FFFF8 FFF8
FFFF8 FFF8 00FFFFF8 EABORT EQU * ;Maintained entry point $FFF8
FFFF8 FFF8 4A79 DC.W TOEABORT ;Emulation abort interrupt vector
FFFFA FFFA 00FFFFFA ENMI EQU * ;Maintained entry point $FFFA
FFFFA FFFA 03FB DC.W NMI ;Emulation non-maskable interrupt vector
FFFFC FFFC 00FFFFFC ERESET EQU * ;Maintained entry point $FFFC
FFFFC FFFC 8462 DC.W RESET ;Reset vector
FFFFE FFFE 00FFFFFE EBRKIRQ EQU * ;Maintained entry point $FFFE