supermario/base/SuperMarioProj.1994-02-09/Patches/PatchIIciROM.a

9813 lines
378 KiB
Plaintext
Raw Normal View History

2019-06-29 15:17:50 +00:00
;
; File: PatchIIciROM.a
;
; Contains: patches for the ROMs first shipped in a Macintosh IIci ($067C)
;
; Copyright: © 1985-1991 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <146> 12/2/91 SAM Using official boxflag equates now.
; <145> 12/2/91 pvh Added cache flushing to fixup patch table code.
; <144> 10/28/91 SAM/KSM Rolled in Regatta Changes.
;
; Regatta Change History:
;
; <15> 8/30/91 SAM Added a check for Tim boxFlag to the code that changes boxFlag
; from boxTim to BoxTimLC. This prevents non-Tim/TimLC machines
; using the TERROR ROM with power mgrs and no-FPU being identified
; as a TimLC.
; <14> 8/30/91 SAM Added a check for an FPU in the previous backpatch patch so it
; will not install on machines without one.
; <13> 8/29/91 SAM Added a check for Zydeco to the "should we remove (ie override)
; the PACK 4 & 5 SANE rsrcs in ROM" check. (CCH) Added a patch to
; _FP68k for 030 TERROR machines that will not allow _FP68k calls
; made from ROM to be backpatched.
; <12> 8/15/91 SAM (RMP) Added v32SetHandleSize patch. SetHandleSize calls the same
; common routine that v32SetPtrSize calls, a32SetSize. SetPtrSize
; was patched earlier to fix a bug in a32SetSize <121> but
; SetHandleSize was never patched.
; <11> 8/9/91 SAM Moved the disposal of the Gestalt tables made by ROM to after
; the reinstallation of Gestalt from disk. This prevents crashes
; caused by someone calling gestalt after the old tables have been
; trashed prior to the new table's creation.
; <10> 8/8/91 SAM (eva) patch level 4 autovector pointed to by vbr, not just the
; zero-offset cuz when VM is running VBR ≠ 0.This routine is a
; patch to the _VM trap. It fixes a bug in the Terror ROM which
; occurs when the page the stack is marked uncacheable in the MMU
; tables, then a subsequent PFLUSH'd is executed with data still
; in the cache.
; <9> 8/7/91 SAM Moved the boxFlag slam before Gestalt. Brainfade.
; <8> 8/6/91 SAM Added a check for TIM LC that will stuff the correct boxFlag
; into BoxFlag if we're running on a TIm LC. Gestalt's private
; storage allocated by the ROM version is disposed of prior to
; reinstalling gestalt from the disk.
; <7> 8/5/91 SAM (eva) fix patch <6>: Port B dispatcher fixed to call serial
; service routines and to have same number of bytes before the rts
; so that async serial driver Rx and SCx patches (which fiddle
; with return address on stack) return to the proper place.
; <6> 7/30/91 SAM (eva) fix the Farallon MacRecorder bug by modifing patch to test
; for port A RxChar and loop back only if we are servicing a channel
; A interrupt. For port B we just jump to service routine like ROM
; code.
; <5> 7/29/91 SAM (eva) patched SCx interrupt handler to fix the StyleWriter bug.
; On faster machines we are able to send out a byte fast enough
; after the TBE bit in RR0 gets set that the byte gets written
; before the TBE interrupt is generated. Instead of just not
; generating the interrupt, the SCC goes ahead and generates it,
; but changes the interrupt source code to read 'no interrupt'
; instead of 'TBE'. This 'no interrupt' code is identical to the
; 'Special Condition on port B' code, which was the source of our
; problem. Fix is to just exit SCIntHnd if no special condition
; bits are set.
; <4> 7/17/91 SAM (EH) Added Lvl4 irq patch to improve serial performance.
; <3> 6/30/91 SAM Conditionalizing the SCSI Chaining Bus Error handler for non
; C96.
; <2> 6/14/91 SAM Removed the GestaltHardware patch in favor of the real code in
; GestaltFunction.a. Fixed a check for an unallocated Palette Mgr
; handle in the InitPalettes Patch. (RMP) Added the IIfx IOP irq
; MPW fix to the set of Eclipse fixes. (bg) Changed the Egret
; "CheckPacket()" patch to allow the full
; range check of possible pseudo-commands.
; <1> 5/15/91 SAM Split off from 7.0 GM sources. Added code to use PACK 4 & 5 from
; disk on IIciROM machines that are not TERROR A7 or newer. Do
; not save Gestalts old Logical mem size across PtchInst 5
; (which is Gestalt) cuz the old number is wrong.
; 7.0 Change History:
;
; <143> 9/18/91 JSM Cleanup header, dont include InternalOnlyEqu.a (already in dump
; file).
; <142> 8/30/91 DTY Define isUniversal here since its no longer defined in
; BBSStartup. This file used to use {Defs32}, so isUniversal is
; defined to be 1.
; <141> 6/12/91 LN added #include 'ROMPrivateEqu.a'
; <140> 6/12/91 LN removed #include 'HardwareEqu.a'
; <139> 4/12/91 dba ewa: add magic signature to Time Manager task used to implement
; VBLs; the signature will prevent VM from deferring the task
; <138> 4/8/91 eh Fixed bug in iop serial driver that was causing bad printing to
; Imagewriter. Actually, it was two bugs. CTS interrupt disable
; code had a bad branch and the IOP timer never got kickstarted.
; <137> 4/5/91 eh Fix to Serial driver SerSetbuf call. Missed one place in <135>
; that sign extended a register.
; <136> 3/28/91 SAM As per Darins request, I have added a TestFor SCSI96_1Exists
; before the Quantum 7.9 ROM fix from the Regatta deltas (without
; forRegattaCPUs).
; <135> 3/17/91 eh Serial driver status calls 9 and $8000 now return hardcoded
; driver version instead of getting it from DCE. This obviates the
; need for the linked patch to _Open to patch the version number
; in the DCE, a fix which was causing FileShare to crash. Also
; fixed bug in IOP SerSetBuff (control 9) call -- was sign
; extending a register unintentionally.
; <134> 3/8/91 DFH VL,WS#DFH-910308a: Fixed SetEntries patch to not chew on a2.
; This led to crashes, such as in AfterDark.
; <133> 3/4/91 dba dty: get rid of SysVers checks
; <132> 2/26/91 DFH csd,WS#910226a: Fixed bug in ptchPMgrExit where it assumed that
; graphics has been initialized. Bug introduced by change <124>.
; <131> 2/25/91 gbm csd, #83338: Fix the fix to Gestalt. Save the original Gestalt
; globals pointer, and put some important (but hard to figure out)
; data back in it after the RAM copy installs
; <130> 2/21/91 gbm csd, #83338: Start including the Gestalt ptch even on ci ROMs.
; <129> 2/21/91 eh (djw) Fixed bug in serial driver that was preventing use of one
; port when Nike was printing on the other.
; <128> 2/19/91 gbm csd, #Go5 approved: Make sure _MemoryDispatch is NOT implemented
; on machines without PMMUs.
; <127> 1/29/91 eh (djw) Fixed a bug in the External Status interrupt handler. On
; port A we crashed on receiving a break if a read was pending
; because we weren't getting the .Ain DCE ptr properly. Now we get
; the DCE ptr directly from the Unit table, just like for port B.
; <126> 1/25/91 eh Fix iop serial driver to: time out an waiting for all-sent in
; the close, and to disable HWHS properly when external clocking
; is set.
; <125> 1/19/91 eh (djw) Patch async serial bypass driver headers to insert
; signature longword used by linked patch to Open in Serial
; Patches.a . Added signature longword before already patch IOP
; driver headers.
; <124> 1/18/91 dvb Don't restore color environment if it hasn't been changed.
; Modify SetEntries to mark flag in QDSpare.
; <123> 1/14/91 eh (djw) Added external clocking support for the NIke printer to
; the Async Serial Driver.
; <122> 12/19/90 djw (ewa) Patch ROM SCSIDispatch to the ROM SCSIDispatch to resolve
; a VM patch conflict.
; <121> 12/19/90 TL Fixed an old bug in setptrsize for old time sake, in calls
; between relocRel, the tag is restored in the old block, instead
; of the new block location. And also discard flag when two block
; sizes are identical.
; <120> 12/19/90 dvb Don't draw windowframes after InitGDevice. Removed some
; duplicate code between PatchIIciROM.a and PaletteMgr.a.
; <119> 12/15/90 djw (jwk) Add SCSI Mgr support for Quantum 7.9 ROM problem by
; replacing blind write routine
; <118> 12/14/90 dnf (jsm) Turn all patches on ExtFSHook off for 7.0 since they have
; been moved to LaterFileMgrPatches.a
; <117> 12/14/90 SMC Patched DisposeAppPalettes via PMgrExit to use ApplZone->bklim
; instead of HeapEnd to determine if palette is in the application
; heap. Also, patched PMgrExit to only throw away palettes if app
; is front process. With DFH.
; <116> 12/14/90 dba <JDR> get rid of VMCalls.a
; <115> 12/6/90 BBM (dba) Protect the Come-from patches. Eleminate TextFont patch to
; the MDEF, as the MDEF in ROM is not used anymore, RomOverride at
; its best.
; <114> 11/15/90 JSM <bbm> Move come-from patch on _OpenCPort inside NewGWorld to
; QuickDrawPatches.a.
; <113> 10/31/90 dba & csd; kill 8•24 GC loading code for 7.0 (StartSystem.a does it
; now)
; <112> 10/22/90 JJ Rex V8: Change VISAChipBit to V8ChipBit.
; <111> 10/22/90 JJ Rex V8: Change all box flag references to use boxMacLC. Get rid
; of boxElsie and boxElsieV8.
; <110> 10/9/90 SAM Updated the AppleTalk _Open patch so that it stuffs PortNotCf
; into ioResult if SPConfig >= 2.
; <109> 9/26/90 SAM Redoing the patch to Open that fixes the .MPP crash.
; <108> 9/25/90 KIP Change Sound Mgr. to a linked patch.
; <107> 9/18/90 SAM Added changes from SixPack code review (search for <107>).
; Removed EclipseNOPs (as per BGs request). Fixed the last of the
; build warnings for this file (rah).
; <106> 9/15/90 DC added GetGray
; <105> 9/15/90 GMR Fixed Gestalt parity routine to set good parity before testing
; the byte with bad parity, so the RPU interrupt would not cause
; bad data to be stacked.
; <104> 9/5/90 EH Removed duplicate declarations for PollProc, Pollstack, and
; HiIntMask from EgretMgr patch <101>.
; <103> 8/31/90 SAM Adding fix to ReallocHandle patch that checks to see if SysZone
; = AppZone and if so it only checks the current heap then jumps
; back to ROM. Added a patch to open so that it clears out the low
; nibble of SPConfig when the .MPP driver is opened. Made
; GestaltHardwareAttr recognize Visa/V8.
; <102> 8/29/90 GMR Fixed Gestalt parity check on FX so it does not destroy A4 (this
; reg needs to be preserved throughout patches and inits!)
; <101> 8/22/90 SAM Adding a series of REgret patches & a SANE ptch (search for
; <101> for more explicit descriptions).
; <100> 8/20/90 dvb Remove "DrawGrayishText"
; <99> 8/19/90 SAM Adding changes to make sound (MACE) work on ci ROMs
; <98> 8/18/90 dba get rid of ptchInst 7 and 8 (Sony Format and Eject patches) as
; they are now linked patches
; <97> 8/17/90 gbm start loading soundmgr patch 23 on erickson and elsie, cause
; BigBang don't work otherwise
; <96> 8/14/90 DTY Removed TextEditPatchIIciROM since its a linked patch now. (For
; real this time.) Also deleted an INIT 18 patch for Darin.
; <95> 8/13/90 JWK NEEDED FOR SIXPACK: Added NuBus and Serial Gestalt selectors.
; <94> 8/11/90 PKE NEEDED FOR SIXPACK: Fixed bug in previous revision - (per KIP)
; ptch 3 must load before ptch 23 so SoundMgr globals are
; initialized!! Was causing ci & fx to hang during boot.
; <93> 8/10/90 SAM Made ptch 3 (7.0 Sound Mgr) load on all IIciROM machines. It
; used to *not* load on Erickson/Elsie.
; <92> 8/8/90 SAM Changing DispatchHelper & ProcHelper into an old style ptch.
; •••--> Temporary <--••• Remove when the Sound ptch get converted
; into an Lptch.
; <91> 8/7/90 PKE Fixed the SixPack build by adding an eclipseDebug conditional
; around a BRA.S. Build was broken because BG changed BBSStartup
; to turn on eclipseDebug for Mac32 (which applies to this file),
; so EclipseNOPs are expanded and a branch went out of range.
; Also, altered the previous comment to say needed for SixPack.
; <90> 8/5/90 PKE NEEDED FOR SIXPACK: Moved installation of Script Mgr ptch 39 and
; 27 to Mac and A/UX section of install code (was formerly for Mac
; OS only). Search for <90> to see changes.
; <89> 7/30/90 SAM Added Egret TickHandler patch so it doesnt loose time while IRQs
; are off.
; <88> 7/30/90 dnf Remove installation of ptch 18 (File Manager) and ptch 6 (Btree
; Manager), now linked patches
; <87> 7/23/90 dba get rid of ptch 25 for 7.0; it is covered by DialogMgrPatches;
; get rid of extraneous pre-6.0.6 SysVers conditionals; removed
; ptchInst 16 since PrGlue is a linked patch
; <86> 7/21/90 BG Added EclipseNOPs for flakey 040s.
; <85> 7/20/90 CSL Needed for SIXPACK: Totally replaced Memory manager routine
; a32SetSize, patch <68> only replaced part of a32SetSize and is
; not sufficient.
; <84> 7/20/90 DTY Removed Bass patches since its a linked patch now.
; <83> 7/20/90 gbm Get rid of some warnings
; <82> 7/19/90 CCH NEEDED FOR SIXPACK: Removed HwPriv patch since it is now a
; linked patch.
; <81> 7/19/90 EH Add VM support for async.a, SetSerBuf control call
; <80> 7/19/90 GMR Install ptch 7 to change eject track from 79 to 40.
; <79> 7/18/90 DDG NEEDED FOR SIXPACK: Fixed previous comment.
; <78> 7/18/90 DDG NEEDED FOR SIXPACK: clean up lomem $B50 after the netbooting socket
; listener.
; <77> 7/17/90 DVB Fix DrawGrayishText, and include PaletteMgr.a
; <76> 7/14/90 DVB Add in new PMgr dispatches
; <75> 7/11/90 gbm get rid of a few duplicate symbols
; <74> 7/11/90 DDG NEEDED FOR SIXPACK: Fixed a bug in our new ReadDateTime call. We
; now return an error code of zero, instead of garbage.
; <73> 7/2/90 DTY Remove ptchInst 21 since Resource Manager extensions are now in
; a linked patch.
; <72> 6/28/90 DDG NEEDED FOR SIXPACK: Put in a fix for egret. Now the
; _ReadDateTime call does not actually call the clock chip. It
; simply reads the low mem global (Time) and returns that. This is
; OK, since Time is automatically updated. This fix only happens
; on Elsie and Erickson.
; <71> 6/25/90 DTY Removed ptchInst 9.
; <70> 6/25/90 KON Remove rSwapMMUMode macro 'cause it's in QDHooks.
; <69> 6/19/90 VL Remove ptchinst 29 since MiscPatches is a linked patch now.
; <68> 6/14/90 CSL Needed for Six-Pack. Fixed _setptrsize problem in memory
; mananger for 32 bit mode only. It will not de-reference from
; address $0 now.
; <67> 6/12/90 JSM Remove PtchInst 33 since PPC Toolbox is a linked patch now.
; <66> 6/7/90 EMT Remove PtchInst 17 since Layer Manager is a linked patch now.
; <65> 6/7/90 VL Remove PtchInst 28 since HelpMgr is a linked patch now.
; <64> 5/31/90 DDG Adding a special system error for machines that dont have an
; FPU.
; <63> 5/31/90 DDG Added the extFS patch from the PatchIIROM.a file. This will fix
; a strange bug where the wrong error code is being returned from
; the MountVol call.
; <62> 5/29/90 DDG NEEDED FOR SIXPACK: Changed all the sixpack conditionals from
; six-point-oh-seven to six-point-oh-six.
; <61> 5/17/90 KON Clear high word of d3 and d4 so compare is done as a word in
; ResizePalette.
; <60> 5/10/90 JSM AliasMgr now a linked patch, don't install it here anymore.
; <59> 5/2/90 CCH Fixed bug in parity routine for pre-IIci machines with IIci
; ROMs.
; <58> 5/1/90 CCH Added Scrolling throttle and Square menus to misc selector.
; <57> 4/22/90 csd commented out the installation of SCSI DMA so we stop trashing
; hard disks on the IIfx.
; <56> 4/19/90 NB Add PrGlue to the PtchInst list (#16). It's already on all other
; machines
; <55> 4/18/90 DDG Rolling in the ReallocHandle patches from the sys6 sources.
; <54> 4/16/90 DDG Rolled over changes from the split off sources including: a
; patch to hwPriv, an IOP serial driver fix, SCSI DMA is now
; disabled on the IIfx due to bugs, added an init (18) to fix the
; comm toolbox, added the patch for tiburon video cards, added
; patch 25 (generic system fixes), and finally changed the equate
; for spline fonts to use the build variable hasSplineFonts.
; <53> 4/11/90 dba move PPC after B-Tree Manager; get rid of old AppleShare patch
; for 7.0
; <52> 3/30/90 DVB Add "WhatPal" PmgrDispatch
; <51> 3/27/90 PKE Deleted import (currently conditionalized out) of NewSwapIcon,
; which no longer exists in this PTCH.
; <50> 3/26/90 PKE Moved definition of symbols that control Script Mgr patch and
; 'ptch' installation into ScriptPriv.a. Renamed symbols and added
; some.
; <49> 3/23/90 NC Added ptch 43 for System 6.0.6 on up. This is for Sound.
; <48> 3/20/90 DDG Added code to not install patch 3 on Ericksons and above for
; Sys607 and above.
; <47> 3/12/90 DVB Fix PMgrExit so that ExitToShell doesn't crash!
; <46> 3/8/90 JAL Took out include of QuickEqu.a because it is already in
; StandardEqu.d.
; <45> 3/4/90 PKE Changed _UprText to _UpperText to match new Traps.a.
; <44> 3/1/90 GMR Fixed bug in Gestalt parity check for Zone-5, where longword was
; not being written back with good parity after each SIMM check.
; <43> 2/28/90 GMR Added include of EgretEqu.a to fix system disk build.
; <42> 2/28/90 PKE For 7.0, moved Script Mgr ROM patches into ptch 39: patches to
; _Pack6 and _GetIndADB, fixes to String2Date/InitDateCache,
; installation of some new vectors, and the change to SwapIcon.
; For all of these except the SwapIcon change, the code is still
; here but conditionalized differently (in case we need it for
; 6.1).
; <41> 2/26/90 EH Rewrote <8.7> to use patch macros. Added on patch for 68000 IOP
; Serial Driver read bug.
; <40> 2/23/90 DVB PMgrExit no longer clears the windowlist.
; <39> 2/22/90 PKE Replaced obsolete _LwrStringToUpr opword with _UprText. Removed
; setting of temporary sVectFixSpExtra vector (see <12>); we no
; longer need it.
; <38> 2/21/90 JS NEEDED FOR 6.0.5: SetDepth also takes a mode
; <37> 2/16/90 EH Fixed CTS status bug and low baud rate bug in IOP Serial Driver.
; Fixed <27> to use the patch macros properly.
; <36> 2/15/90 EMT Moved <1.9> before <1.2> - both patch SetWinColor, SetCtlColor.
; <35> 2/15/90 DVB Change SetDepth's return to OSErr
; <34> 2/14/90 DVB Fix SetDepth's register trashage
; <33> 2/14/90 EH NEEDED FOR 6.0.5: 'Come from' patched IOPMoveData trap to fix
; IOP Serial Driver DMA hang bug.
; <32> 2/14/90 CCH NEEDED FOR 6.0.5 - Made sure external cache on Zone 5 does not
; interfere with the check to see if parity RAM is installed.
; <31> 2/13/90 SMB NEEDED for 6.0.5 - Added installation code for ptchGetLRPosition
; and ptchPixelWidths for TextEdit.
; <30> 2/9/90 EH NEEDED FOR 6.0.5: Patched Level4SccIopInt to set flags such that
; all the IOP completion routines be called immediately from the
; IOP Manager, rather than be run as deferred tasks. This, so we
; don't break Timbuktu/Remote.
; <29> 2/2/90 JWK NEEDED FOR 6.0.5: Changed SCSI Mgr bus error handler to allow
; chaining to previously installed handler if a non-SCSI bus error
; occurs.
; <28> 2/2/90 GGD NEEDED FOR 6.0.5: Modified the Deferred Task Manager to enable
; interrupts when returning just so QuickMail servers will
; continue to work (their bug, but we'll fix them for now).
; <27> 1/31/90 EH NEEDED FOR 6.0.5: 'Come from' patched IOPMsgRequest trap to fix
; IOP serial driver control call bug
; <26> 1/30/90 CCH NEEDED FOR 6.0.5: Modified gestaltHardwareAttr patch to set
; gestaltHasSCC bit in result if in IOP bypass mode.
; <25> 1/29/90 GGD NEEDED FOR 6.0.5, Adding a temporary patch to make cmd-period
; not hang the MPW shell on Zone-5, until the shell can be reved
; to fix the real problem.
; <24> 1/29/90 DVB NEEDED FOR 605 - Add PMgrVersion call
; <23> 1/25/90 KON NEEDED FOR 6.0.5: QDversion is offscreenVersion + $100, not
; $200.
; <22> 1/23/90 KON NEEDED FOR 6.0.5: Gestalt now gets the Quickdraw version from
; GWorld Offscreen version and adds 200.
; <21> 1/23/90 DVB NEEDED FOR 6.0.5 - Add HasDepth and SetDepth PMgr Dispatches
; <20> 1/22/90 CCH NEEDED FOR 6.0.5 - Added notification mgr selector.
; <19> 1/19/90 JWK NEEDED FOR 6.0.5 - Turn on SCSI DMA code in Zone5 final ROM's.
; <18> 1/18/90 DVB Include PalettePriv.a
; <17> 1/17/90 CCH NEEDED FOR 6.0.5: moved restoration of cache register in parity
; check routine.
; <16> 1/16/90 SMB NEEDED FOR 6.0.5: added install code for TENew and
; TEStylNew patch and included TextEditPriv.a.
; <15> 1/16/90 CCH NEEDED FOR 6.0.5: Turn off cache when checking RPU for parity.
; <14> 1/16/90 KON NEEDED FOR 6.0.5: Added ptch 26
; <13> 1/12/90 CCH Added include of “HardwarePrivateEqu.a”.
; <12> 1/11/90 PKE Initialize Script Manager's new sVectFixSpExtra vector.
; <11> 1/11/90 DVB Remove _Zaplinks macro.
; <10> 1/8/90 CCH Added gestaltMiscAttr selector.
; <9> 1/5/90 GMR Added ptchInst 8; Sony Format patch is now in it's own patch
; file (FormatPatch.a).
; <8> 1/5/90 CCH NEEDED FOR 6.0.5. Added parity support for Zone 5, removed base
; address selectors.
; <7> 1/4/90 BBM NEEDED FOR 6.0.5. Make the new sound manager patch out the rom
; on all machines.
; <6> 1/4/90 PKE NEEDED FOR 6.0.5 (smb's changes from SS-6.0.4b23 to SS-6.0.4f1):
; • Add install code for TEFindLine patch. ALSO: Updated
; conditionals so SS-6.0.4 changes go in 6.0.5 as well as 7.0.
; Cleaned up the BBS header and eliminated the EASE header.
; <5> 1/3/90 BAL NEEDED FOR 6.0.5: Fixed Zero width character problem in
; drawtext.
; <4> 12/19/89 EH REALLY fix the pound signs!
; <3> 12/19/89 EH try to fix the pound signs!
; <2> 12/19/89 EH NEEDED FOR 6.0.5: Fix bug in 7.1 async patch; switched registers
; <1> 12/17/89 CCH Adding for the first time into BBS.
; <8.8> 12/14/89 SWC NEEDED FOR 6.0.5: Added RecoverHandle patch to also check if the
; pointer points to a ROM resource. Removed the NewSCSI trap
; initialization since async SCSI will not be in Zone 5 until 7.0
; or later.
; <8.7> 12/14/89 EVA NEEDED FOR 6.0.5 Fix SerialDriver.a patch to check SCCIOPFlag
; instead of PRAM to see which driver to load
; <8.6> 12/11/89 smb NEEDED FOR Scripts 604 AND (6.0.5 <= SysVers < 7.0): added
; installation code for TE routines CaretInsideRun,
; InvrtRectangle, SetKeyboard2Font.
; <8.5> 12/8/89 PKE NEEDED FOR Scripts604 AND FOR (6.0.5 <= SysVers < 7.0): Patch
; LwrString to handle 2-byte chars via Transliterate (yuck). For
; 7.0, we do this elsewhere.
; <8.4> 11/29/89 GGD NEEDED FOR 6.0.5: Re-Enabled the SANE optimization to bypass the
; Package Manager which never made it into 6.0.4. Fixed bug
; StripAddress that caused it to sometimes not strip when in a
; interrupt handler. Modified ADB auto/srq polling to not poll
; device addresses that are not in the device table. On OSS based
; machines, install a time manager task to simulate a 60.15Hz
; pseudo VBL because the OSS generates a 60.00Hz interrupt which
; is the wrong frequency.
; <8.3> 11/28/89 dvb Fixed bug in PMgr Zaplinks by working over pmgrDispatch. Also
; fixed bug in dispatch.
; <8.2> 11/22/89 EMT NEEDED FOR 6.0.5: Added humane scrolling.
; <8.1> 11/21/89 smb Added installation code for TE routines ptchGetWidth and
; ptchGetRLPosition.
; <8.0> 11/17/89 PKE Tail patch on _GetIndADB to fix Script Mgr SwapKybd routine,
; which cleared ADB keyboard driver dead state as a word: should
; be a long.
; <7.9> 11/10/89 KON PTCH'ed GetNewCWindow so when a palette with the same ID as the
; window exists in the resource file, the palette is attached to
; the window.
; <7.8> 11/6/89 PKE NEEDED FOR 6.0.5!! Bug fixes for InitDateCache and String2Date
; needed for HyperCard. InitDateCache: Fixed CopyArray to use
; correct register (A4) for source pointer, and to initialize all
; relevant bytes of length register (D0). String2Date: if first
; relevant (i.e., day or month name) alpha token is a month name,
; we now search the day name list if we find another alpha token
; (fixes BRC #54946). Rearranged Cache structure to fix invalid
; use of month/day name index.
; <7.7> 10/12/89 smb Moved TextEdit patches to TextEditPatchIIciROM.a. Fixed bug in
; old highlighting code that I introduced accidently (changed
; move.w -> move.l).
; <7.6> 10/11/89 CCH Added INCLUDE of "MMUEqu.a"
; <7.5> 10/11/89 CCH Set up MMUType if not already initialized.
; <7.4> 10/6/89 JSM Removed SnarfMan 'ptch', now PACK 13.
; <7.3> 10/5/89 CCH Changed an ORI to a BSET in gestaltAddressingModeAttr patch, and
; added installation of it.
; <7.2> 10/5/89 smb Added old highlighting code for TextEdit for HyperCard
; outlining.
; <7.1> 10/5/89 EVA NEEDED FOR 6.0.5!!! Fixed bug in async serial driver Ext/Stat
; int handler
; <7.0> 10/4/89 smb Fixed 6.0.4 build by moving around some of my conditionals due
; to dependencies! Fixed TEInit to set TEDoText like it used to.
; Cleaned up TEOutlineHilite. Fixed caret display for outline
; highlighting.
; <6.9> 9/29/89 CCH Added patch for gestaltAddressingModeAttr selector to add
; gestalt32BitCapable attribute. (version 6.8 breaks 6.0.4 builds,
; so I just tested on bigbang - because alpha 0 is in two days,
; thats why)
; <6.8> 9/29/89 smb Added patches for TextEdit for TEFeatureFlag, SetFont2Keyboard,
; and fixed CursorMovement for double-byte characters.
; <6.7> 9/27/89 EMT Fixed 6.2 to use Lea rather than LeaROM for RAM address.
; <6.6> 9/26/89 CVC Added PPC Toolbox as a 'ptch'.
; <6.5> 9/25/89 EMT Added ptchs 18, 6, 29.
; <6.4> 9/19/89 RLC Add Balloon Help (ptch 28) to this file.
; <6.3> 9/18/89 BBM Install resource manager extensions, ptch 21
; <6.2> 9/18/89 PKE For 7.0, patch Script Manager internal routine SwapIcon to use
; new 'kscn' resource type instead of 'SICN'.
; <6.1> 9/17/89 PKE Decided to patch out GetScript/SetScript entirely in ptch 27, so
; we no longer patch them here (see 5.9). Also, for 7.0 we now
; install the Script Manager's Gestalt function in ptch 27 instead
; of here (see 2.5).
; <6.0> 9/12/89 EMT PaintOne patch (3.7) nukes the layer manager. Only use on pre
; 7.0 systems.
; <5.9> 9/6/89 PKE Patch Script Manager GetScript/SetScript routines to support
; additional font info verbs for 7.0, and set up this font info in
; Roman ScriptRecord. Set new sVectCallInterface vector. Redo
; Script Manager version setup, using new smgrVersPTCHRom equate.
; <5.8> 9/5/89 jwk NEEDED FOR 6.0.5: Turn on NewSCSI in ROM if on F19.
; <5.7> 9/4/89 PKE Install Script Manager 7.0 extensions, ptch 27. Set Script Mgr
; version for 7.0.
; <5.6> 8/31/89 JSM Added SnarfMan support.
; <5.5> 8/30/89 smb NEEDED FOR Scripts604 and Big Bang! Bug fix in ptchTEFindWord
; (fixed word dragging bug and now uses old FindWord code when
; RecalLines calls. Also added ptchMeasureWidth to fix a
; hilighting bug at line ends when the line direction is RL on a
; system that is normally LR (ie - Roman, Kanji, etc.)
; <5.4> 8/28/89 PKE For 7.0, initialize additional Script Mgr vectors for
; SMgrCalcRect and SMgrInitFonts.
; <5.3> 8/27/89 PKE NEEDED FOR Scripts604, 6.0.5: Bump Script Manager version for
; Scripts604 or SysVers > $604, since IntlForce bug fix (4.5) is
; installed.
; <5.2> 8/22/89 PKE NEEDED FOR 6.0.4: (really dba) Tail patch to TextFont which
; fixes an MDEF bug in calculating the icon height. Replaces
; GetResource patch in 3.7 which attempted to fix the same
; problem.
; <5.1> 8/21/89 PKE NEEDED FOR 6.0.4: Really put in 4.1, which was only present as a
; comment until now (although it existed on Fiction sources).
; <5.0> 8/21/89 PKE NEEDED FOR 6.0.4: (really CSD) Fixed MDEF 3.7 patch (again. Last
; time, right?) to load #$00200020 into D1 when appropriate
; instead of jumping back into ROM at the same place for both
; cases cicn found and cicn not found.
; <4.9> 8/21/89 PKE NEEDED FOR 6.0.4: (really dba) Changed MDEF patch 3.7 to load A0
; with the right value instead of preserving its value.
; <4.8> 8/21/89 PKE NEEDED FOR 6.0.4: (Per CSD) Correct ROMNoColor address in MDEF
; patch (part of 3.7).
; <4.7> 8/21/89 PKE NEEDED FOR 6.0.4:
; • (per dba) Only re-load the standard clut into QDColors if
; QDColors exists; this is so that A/UX will work
; • Conditionalize 4.5 for Scripts604 OR (SysVers > $604)
; <4.6> 8/21/89 PKE NEEDED FOR 6.0.4!: Patch RelString,UprString,CmpString to
; re-introduce the bug in which "`" is converted to uppercase as
; "a". This is necessary to prevent HFS problems, since existing
; disk catalogs use the old, buggy sorting. Also remove SANE
; optimization (2.0); breaks Excel.
; <4.5> 8/21/89 PKE NEEDED FOR 6.0.4 SCRIPTS BUILD, 6.0.5: Extend Pack6 patch to fix
; a problem in LwrString,CharType,Transliterate,FindWord. These
; routines should save the IntlForce flags then clear them before
; the IUGetIntl call, restoring the flags afterward. This is so we
; get the itl2 tables for the correct script (instead of the
; tables for the system script).
; <4.4> 8/21/89 PKE NEEDED FOR 6.0.4!: Fixed accidental deletion of INCLUDE
; 'VideoPatch.a' in (4.3).
; <4.3> 8/21/89 PKE NEEDED FOR 6.0.4!!: Patch Pack6 to fix me-too problem with
; pointer to unlocked handle in Transliterate; affects Roman
; system (this problem looks familiar; did I dream that I already
; fixed this one?).
; <4.2> 8/18/89 smb NEEDED FOR 6.0.4: Another unlocked handle problem!
; AAAARRRRRGGGGHHHHHH! (See ptchOnSameLine below)
; <4.1> 8/18/89 DAF FOR 6.0.4 BUILD - Fixed a bug on non-CLUT devices in the
; SaveEntries trap on Aurora
; <4.0> 8/16/89 dba NEEDED FOR 6.0.4: InitProcMenu bug fixed: MBDF ID was not put in
; MenuList if MenuList was already allocated (InitMenus already
; called)
; <3.9> 8/15/89 prp Added Alias Manager and Folder Manager support.
; <3.8> 8/15/89 smb NEEDED FOR 6.0.4: Fixed some problems in my patch code for the
; bad pointer bug.
; <3.7> 8/15/89 dba NEEDED FOR 6.0.4:
; • Shortened the SetWin/CtlColor patch by returning to ROM earlier.
; • Patch PaintOne to do nothing if WWExist is non-0.
; • Patch OpenCPort so that the current port is saved across
; NewGWorld.
; • Patch GetResource so that GetIconSize in MDEF does not trash A0.
; • Moved VideoPatch.a so that it does not happen on A/UX.
; • Re-load the standard clut into QDColors so that the green channel
; is fixed
; <3.6> 8/14/89 djw NEEDED FOR 6.0.4: Fixed bug in slot mgr in pInitEntry routine.
; When calling _InsertSRTRec, and the sRsrc has a refnum
; associated with it, _sFindDevBase has bad spId.
; <3.5> 8/13/89 BAL NEEDED FOR 6.0.4: Added tail patch to InitPalettes to defeat
; spurious ExitToShell patching code (leftover from JP builds).
; (dvb really)
; <3.4> 8/11/89 smb Finally rolled in patches for a bad pointer bug (#51602) and an
; up & down arrow keys bug (#51961). See comments below.
; <3.3> 8/11/89 djw NEEDED FOR 6.0.4: Cleaned up file by deleting old comments,
; adding new comments, laying out patches in a "prettier" and more
; orderly format. Added A/UX runtime conditional check for
; Mac-only patches. Moved patches <2.4> and <2.7> to Mac OS only.
; Modified slot manager calls in patche <2.1> as per code review.
; <3.2> 8/9/89 CCH NEEDED FOR 6.0.4: Added patch to gestaltQuickdrawVersion to
; return two digit versions.
; <3.1> 8/8/89 smb NEEDED FOR 6.0.4: Reverted TEFindWord patch since the previous
; patch introduces an uglier bug that won't be fixed now. Also
; added gestalt function for TE.
; <•3.0> 8/8/89 dba Realitys hard disk was full! Try submitting again.
; <3.0> 8/8/89 dba NEEDED FOR 6.0.4: added Menu Manager patches; InitProcMenu patch
; because it simply didnt work; MenuSelect patch to reinstate
; WaitMouseUp check
; <2.9> 8/8/89 PKE NEEDED FOR 6.0.4: In gestaltScriptMgr function, if gestalt
; selector is undefined, just leave gestalt result alone.
; <2.8> 8/8/89 smb NEEDED FOR 604: Added more TE patches for Aurora!
; <2.7> 8/7/89 GGD Changed SIntInstall again, to leave $FF as highest priority, but
; reverse handling of equal priorities. Modified to use less
; space. Changed GetBoardROM from <2.4> to be a ROM Offset,
; instead of absolute ROM address.
; <2.6> 8/6/89 DAF FOR 6.0.4 BUILD - Added TFB video card driver override for boot
; screen. This is the same code as is included in PatchIIROM.a
; (VideoPatch.a)
; <2.5> 8/5/89 PKE NEEDED FOR 6.0.4: Add Gestalt function for Script Manager,
; install corresponding Gestalt selectors.
; <2.4> 8/4/89 djw NEEDED FOR 6.0.4: Deleted patch <1.3> (no longer needed). Added
; code to re-init board id's in slot pram (fixes a bug in Aurora
; in InitPRAMRecs).
; <2.3> 8/2/89 EVA (forgot to) include hardwareEqu.a and SlotMgrEqu.a
; <2.2> 8/2/89 EVA FOR 6.0.4 (and above) Patched _SIntInstall to reverse slot
; interrupt queueing order
; <2.1> 8/1/89 CSD FOR 6.0.4: Added patch to suppress appleshare arrows on 32-bit
; video cards.
; <2.0> 7/26/89 GGD NEEDED FOR 6.0.4 Added SANE optimization to bypass the package
; manager
; <1.9> 7/25/89 DAF FOR 6.0.4 BUILD - Fixes for SetWinColor, SetCtlColor in 32-bit
; mode
; <1.8> 7/25/89 smb NEEDED FOR 6.0.4: Added TextEdit patches for Aurora.
; <1.7> 7/3/89 NJC Sound Manager Extensions (ptch 23) rolled in for real.
; <1.6> 6/21/89 NJC Added a ptchinst 3 to if it wasn't already there and added in a
; commented-out ptchinst 23 for the sound dispatcher,DJ, and S.M.
; enhancements.
; <1.5> 5/31/89 CEL Only defined Spline_Font variable if it is undefined - makes it
; easier to build test 6.0.4 systems
; <1.4> 5/22/89 AG Fixed my mistake in gettrapaddress call
; <1.3> 5/21/89 AG Remove NEW SCSI manager trap (A089)
; <1.2> 5/13/89 EMT Added Window Manager extensions (Layers).
; <1.1> 5/3/89 CEL Rolling in Bass for the first time into EASE…
; <1.0> 3/6/89 CCH Adding to EASE for first time.
;___________________________________________________________________________________________________
; To Do:
;
;___________________________________________________________________________________________________
IF (&TYPE('SPLINE_FONT') = 'UNDEFINED') THEN
SPLINE_FONT EQU hasSplineFonts ;<1.1-4april89-CEL> <DDG>
ENDIF
IF (&TYPE('Scripts604') = 'UNDEFINED') THEN
Scripts604 EQU 0 ;<4.7><08/21/89 pke>
ENDIF
if (&type('isUniversal') = 'UNDEFINED') then
isUniversal: equ 1 ; <142> Define isUniversal here instead of BBSStartup
endif
BLANKS ON
STRING ASIS
MACHINE MC68020 ; changed from MC68000 to MC68020 <24July89smb>
MC68881
LOAD 'StandardEqu.d' ;
INCLUDE 'PatchMacros.a'
INCLUDE 'SlotMgrEqu.a' ;<2.3>
INCLUDE 'HardwarePrivateEqu.a'
INCLUDE 'UniversalEqu.a' ;<7.1>
INCLUDE 'VideoEqu.a'
INCLUDE 'ROMEqu.a'
INCLUDE 'MMUEqu.a' ;<7.6>
Include 'ScriptPriv.a' ;
INCLUDE 'GestaltEqu.a' ;
INCLUDE 'GestaltPrivateEqu.a' ;
INCLUDE 'TextEditPriv.a' ; <1/16/90smb> <16>
INCLUDE 'PackMacs.a' ;
INCLUDE 'InternalMacros.a' ; <54>
INCLUDE 'PaletteEqu.a' ;
INCLUDE 'PalettePriv.a'
INCLUDE 'ApplDeskBus.a' ; <8.0>
INCLUDE 'EgretEqu.a' ; <43>
INCLUDE 'IOPEqu.a' ; <8.4>
INCLUDE 'AppleDeskBusPriv.a' ; <8.4>
INCLUDE 'SCSIEqu.a' ; <19>
INCLUDE 'SCSIPriv.a' ; <19>
include 'ColorEqu.a'
INCLUDE 'QDHooks.a'
TERRORmajorVers EQU $067C ; TERROR major ROM version
TERRORminorVers EQU $15 ; TERROR ROM minor version number
ZYDECOminorVers EQU $17 ; Zydeco ROM minor version number
; The following symbols are defined in ScriptPriv.a. They control whether <50>
; various Script Mgr patches are resident and installed here (since many
; are also included in 'ptch' 39 or 27), and also control installation of
; Script Mgr 'ptch' resources.
;
; doScriptMgrGestalt ; in ptch 27
; doScriptMgrPack6Fix ; in ptch 39
; doScriptMgrStr2DatFix ; in ptch 39
; doScriptMgrRstKCHRFix ; in ptch 39
; doScriptMgrLwrString2 ; in ptch 27
; doScriptMgrSetROMVers ; in ptch 39
; doScriptMgrNewVectors ; in ptch 39
; installScriptMgrPtch27
; installScriptMgrPtch39
;
;-------------------------------------------------------------------------------
ROM67CFix PROC EXPORT
IMPORT PatchInit
EXPORT StartPatch,CutBack
; Cut back Code:
;
; StartPatch is the entry point for ROM67CFix. Upon entry D1.L contains our handle.
;
StartPatch
Bra PatchInit ; Carry out the patches <1.1-4april89-CEL>
DC.B 'PTCH' ; resource type
DC.W $67C ; patch ID $67C.
DC.W 1 ; current version number.
; cut back the ram-based system code to exclude this initialization code
; d0 = size to cut patch down to (EndOfPatch - StartPatch)
; a0 = handle to this PTCH resource (passed into StartPatch in D1 from SysPatch)
CutBack
_SetHandleSize ; adjust our size <1.1-4april89-CEL>
MOVEQ #$7F,D0 ; a soon to be large number
SWAP D0
_CompactMem ,SYS ; of course there must be a comma!
RTS ; all done
ENDPROC ; <24July89smb>
;=========================================================================================
;=========================================================================================
;= =
;= RESIDENT PATCH INSTALL CODE IS BELOW THIS POINT =
;= =
;= Add patch code which remains resident in the system in the following section. The =
;= installation code for the resident patches are further down in the file. Please =
;= begin your patch code with a header which serves to delimit your code from the =
;= previous person's patch code. Use another patches header as an example. Leave at =
;= least 2 or 3 blank lines between your code and the next code. Be sure to be careful =
;= about your conditionals. The safest thing to do is to make your code self-contained =
;= and not depend on someone elses conditionals encompassing your code. =
;= =
;= To find a place to insert your resident patch code, search for 'EndOfPatch' =
;= =
;= Please be neat and follow the format =
;= Drive safely =
;= =
;=========================================================================================
;=========================================================================================
;————————————————————————————————————————————————————————————————————————————————————————————————————————————
;********************** PaletteMgr Patches Start Here ************************
;————————————————————————————————————————————————————————————————————————————————————————————————————————————
INCLUDE 'paletteMgr.a'
ptchInitPalettes PROC EXPORT
RomInitPalettes EQU $3E1F0
; <dvb 8 August 1989> 3.5
; This neutralizes some spurious code in InitPalettes that patches ExitToShell
; the first time [InitPalettes is called and MultiFinder is active]. We depend
; on getting at least one InitPalettes before MultiFinder (from INIT 31).
JSRRom RomInitPalettes ; Call the old one.
MOVE.L PMgrHandle,A0 ; A0 = handle to pm globals
MOVE.L A0,D0 ; Are we a pmgr?
BEQ.S ptchIPEnd ; No=>bye.
CMPI.L #-1,D0 ; Is it -1? <2>
BEQ.S ptchIPEnd ; -> Yes, bail out. <2>
MOVE.L (A0),A0 ; A0->pm globals
TST.L OldExitToShell(A0) ; Has it been patched yet?
BNE.S ptchIPEnd ; Yes => do nothing
MOVE #1,OldExitToShell(A0) ; Put something there; pretend its patched
ptchIPEnd RTS
ENDPROC
;-------------- Start of PMgrDispatch patch added by dvb 28Nov89 <8.3> --------------------
PROC
EXPORT ptchPMgrDispatch,pMgrProcs,pMgrProcsEnd
IMPORT SetDepth,HasDepth,PMgrVersion
IMPORT SetPaletteUpdates,GetPaletteUpdates,CheckColors
IMPORT GetGray
RomEntry2Index EQU $3E8C0
RomIndex2Entries EQU $3E9A0
RomDeltaRGB EQU $3CBF0
RomNewHiliteColor EQU $3F8D0
RomPMgrExit EQU $3DAA0
RomSaveFore EQU $3F910
RomSaveBack EQU $3F914
RomRestoreFore EQU $3F970
RomRestoreBack EQU $3F98E
RomReinstantiateColors EQU $3F9B0 ;this routine should do something heh heh
RomReleaseList EQU $3F9C0
RomPMgrDispatch EQU $3FA36
RomPMgrFinalError EQU $3FA4A
RomRestoreDeviceClut EQU $3F8A0
RomResizePaletteplusEight EQU $3F818
RomFindLink EQU $3E460
RomUnhookAfterZapLinks EQU $3F61E
RomUnhookGoHome EQU $3F642
RomZapLinksAtA EQU $3F70A
;ctReserveBit EQU 6
ptchResizePalette
;---------------------------------------------------
;
; PROCEDURE ResizePalette(srcPalette:PaletteHandle; dstSize:INTEGER); AAA2/3;
;
; Set the number of entries in the palette, and properly dispose of some
; of them if the palette is shrinking.
;ResizePalette PROC EXPORT
RPVars RECORD {A6Link},DECREMENT
result DS.B 0 ; Result: none
srcPal DS.B 4 ; input: palette handle
dstSize DS.B 2 ; input: new size for palette
return DS.B 4
A6Link DS.B 4 ; old contents of A6
linkSize DS.B 0 ;linky number
ENDR
WITH RPVars
LINK A6,#linkSize
MOVEM.L A2/D3-D4,-(SP) ; save 'em.
moveq #0,d3 ;<KON 17May90>
move.l d3,d4 ;<KON 17May90>
JMPRom RomResizePaletteplusEight
ptchZapLinks
; Following code is spliced out of CQD:PaletteMgr.a <dvb>
; ROM67C: Zaplinks bug is that it doesn't clear the ctReserve bit if its
; not on the main screen. Zaplinks is called by Pillage, UnreserveDevices,
; and ReleaseList. Pillage and UnreserveDevices end up clearing the bit
; themselves, so only ReleaseList must be patched here.
;
ZLVars RECORD {A6Link},DECREMENT
result DS.B 0 ;Result length: none
myIndex DS.B 2 ;Input: device number and index to unlink
return DS.B 4
A6Link DS.B 4 ;old contents of A6
linkSize DS.B 0 ;linky number
ENDR
WITH ZLVars
LINK A6,#linkSize
MOVEM.L A0-A2/D0-D4,-(SP)
MOVE.L PMgrHandle,A1
MOVE.L (A1),A1 ; A1->PMgrData
LEA LinkTabs(A1),A0 ; A0->Link Tables
MOVE.L PListHandle(A1),A2 ; A2 = palette list handle
MOVE.L (A2),A2 ; A2 -> palette info list
MOVE myIndex(A6),D0 ; D0 = tricky link
AND #$1FFF,D0 ; clear key bits
MOVE D0,D1
LSR #8,D1 ; D1 = device number
MOVE.L DevHandles(A1,D1*8),A1 ; A1 = device handle
MOVE.L (A1),A1 ; A1->device
MOVE.L gdPMap(A1),A1 ; A1 = pixmap handle
MOVE.L (A1),A1 ; A1->pixmap
MOVE.L pmTable(A1),D1 ; D0 = color table for this device
BEQ.S @a ; Skip this if none
MOVE.L D1,A1 ; A1 = color table handle
MOVE.L (A1),A1 ; A1 -> color table
CLR D1
MOVE.B D0,D1 ; We need to clear the upper bits
CMP ctSize(A1),D1 ; Index in range? <fixed>
BHI.S @a ; No=>skip this
BCLR #ctReserveBit,ctTable+value(A1,D1*8) ; unreserve!
@a JMPRom RomZapLinksAtA ; return to ROM code
;---------------------------------------------------
;
; PROCEDURE PMgrExit; AAA2/12;
;
; Someone should call here when an application quits. Please.
;
ptchPMgrExit
PXVars RECORD {A6Link},DECREMENT
result DS.B 0 ;Result: nothing
return DS.B 4
A6Link DS.B 4 ; old contents of A6
frontPSN DS.B 8 ; a 64-bit process serial number
myPSN DS.B 8 ; likewise
inFront DS.B 2 ; a boolean
linkSize DS.B 0 ; linky number
ENDR
ROMINTOPMGREXIT EQU $3DAB2
WITH PXVars
MOVE.L WindowList,-(SP) ; Save the windowlist value
LINK A6,#linkSize
TST.B QDExist ; if InitGraf has not been called yet…
BNE.S @doNothing ; (a5) not valid and there is nothing to do
CMP.L #PMgrNil,PMgrHandle ; If the palette manager doesnt exist...
BEQ.S @doNothing
CLR.L AppPalette
BSR.S DisposeAppPalettes
MOVE.L (A5),A0 ; < 124 >
BTST #3,QDSpare0(A0) ; Any change to color env? < 124 >
BEQ.S @doNothing ; < 124 >
BSR.S CheckForProcessMgr
BEQ.S @front ; if no process mgr, assume we're in front
MOVE #$0100,inFront(A6) ; default inFront to true
SUBQ #2,SP ; space for result
PEA frontPSN(A6)
_GetFrontProcess
TST (SP)+ ; problem getting front psn?
BNE.S @front ; YES => just zap the cluts
CLR.L myPSN(A6)
MOVE.L #kCurrentProcess,myPSN+4(A6)
SUBQ #2,SP ; space for OSErr result
PEA frontPSN(A6)
PEA myPSN(A6)
PEA inFront(A6)
_SameProcess ; are we the front process?
ADDQ #2,SP ; OSErr leaves inFront true from above
TST inFront(A6)
BEQ.S @doNothing
@front
JSRROM ROMINTOPMGREXIT
; JSR CheckAllDeviceCluts ; A pretty simple patch, really.
; CLR -(SP) ; No Setentries on Scatter
; JSR ScatterDevices
; BSR.S CheckForJuggler ; Is Jugglertm active?
; BNE.S @doNothing ; No=>WMgr is void, next line dangerous
; JSR UpdateDevices
; MOVE.L mainDevice,theGDevice
@doNothing
UNLK A6
MOVE.L (SP)+,WindowList
RTS
;---------------------------------------------------
;
; FUNCTION CheckForProcessMgr:Boolean;
;
; Determine if the process mgr is present using Gestalt.
; (we assume that gestaltLaunchControl iff processMgr is here)
; Affect only A0/D0, since Gestalt is an OS trap.
; return Z-flag Clear if the process mgr is here (BNE ProcMgrTrue)
CheckForProcessMgr
MOVE.L #'os ',D0 ; type of question
_Gestalt
TST D0 ; OSErr from Gestalt?
BEQ.S @a ; No=>test result
SUBA A0,A0 ; Yes=>assume there's no procMgr
@a
MOVE.L A0,D0
BTST #gestaltLaunchControl,D0 ; clear the Z-flag if procmgr here
RTS
;---------------------------------------------------
;
; PROCEDURE DisposeAppPalettes();
;
; Look through the palette list and dispose of any in the current App heap.
DisposeAppPalettes
MOVEM.L A0-A3/D0-D3,-(SP) ; save all registers
MOVE.L PMgrHandle,A2 ; get paletteMgr handle
CMP.L MinusOne,A2 ; is it there?
BEQ GoHome ; => no, just return
MOVE.L (A2),A1 ; point to data structure
MOVE.L PListHandle(A1),A0 ; get handle to palette list
_HLock ; and lock it down
MOVE.L (A0),A3 ; point to palette list
Move APalettes(A1),D3 ; get number of active handles
Beq.s NoPals ; no friends => go home
Add FreeSpaces(A1),D3 ; calculate total number of entries
;<13> Clr.L WindowList ; clear the list of windows for FrontWindow AWC.PB506
BRA.S FindEnd ; => check for no entries
FindLoop Move.L PaletteRef(A3),D1 ; get first entry
BEQ.S FindNext ; => no palette in entry
MOVE.L ApplZone,A0 ; get application heap zone <117>
CMP.L A0,D1 ; Are we before the heap zone? <117>
BLO.S FindNext ; Yes => not in app heap
CMP.L bklim(A0),D1 ; Are we past the heap zone <117>
BHS.S FindNext ; => not in app heap
MOVE.L D1,-(SP) ; push palette handle
_DisposePalette ; and dispose it in place
FindNext AddQ #PLstEntrySz,A3 ; bump to the next entry
FindEnd DBra D3,FindLoop ; repeat for all spaces
NoPals MOVE.L (A2),A1 ; point to palette stuff
MOVE.L PListHandle(A1),A0 ; get handle to palette list
_HUnlock ; and unlock it
GoHome Clr.L AppPalette ; set us up for the next guy AWC.PB508
MOVEM.L (SP)+,A0-A3/D0-D3
RTS
; This is the Palette Manager's dispatch table. ROM routines
; which work are included with DcRom to give absolute
; addresses. New routines are offsets from the table base, with
; the low bit set, just for clarity.
ptchPMgrError JMPRom RomPMgrFinalError
pMgrProcs
switch00 DcRom RomEntry2Index
switch01 DcRom RomIndex2Entries
switch02 DC.L RestoreDeviceClut-pMgrProcs+1
switch03 DC.L ptchResizePalette-pMgrProcs+1
switch04 DC.L ptchZapLinks-pMgrProcs+1
switch05 DC.L WhatPal-pMgrProcs+1
switch06 DC.L ptchPMgrError-pMgrProcs+1 ; Some unused dispatchs
switch07 DC.L ptchPMgrError-pMgrProcs+1
switch08 DC.L ptchPMgrError-pMgrProcs+1
switch09 DC.L ptchPMgrError-pMgrProcs+1
switch10 DcRom RomDeltaRGB
switch11 DcRom RomNewHiliteColor
switch12 DC.L ptchPMgrExit-pMgrProcs+1
switch13 DcRom RomSaveFore
switch14 DcRom RomSaveBack
switch15 DcRom RomRestoreFore
switch16 DcRom RomRestoreBack
switch17 DcRom RomReinstantiateColors
switch18 DC.L ReleaseList-pMgrProcs+1
switch19 DC.L SetDepth-pMgrProcs+1
switch20 DC.L HasDepth-pMgrProcs+1
switch21 DC.L PMgrVersion-pMgrProcs+1
switch22 DC.L SetPaletteUpdates-pMgrProcs+1
switch23 DC.L GetPaletteUpdates-pMgrProcs+1
switch24 DC.L CheckColors-pMgrProcs+1
switch25 DC.L GetGray-pMgrProcs+1
pMgrProcsEnd
ptchPMgrDispatch
CMP.B #(PMgrProcsEnd-PMgrProcs)/4,D0
BHS.S ptchPMgrError ; Too high a dispatch
MOVE.L A0,-(SP) ; Preserve A0
LEA pMgrProcs,A0 ; A0->absolute table of dispatchs
AND #$00FF,D0 ; Kill arg count from dispatch
MOVE.L (A0,D0*4),-(SP) ; Push target as return address
MOVE.L 4(SP),A0 ; Restore A0
RTD #4 ; And go to routine.
ENDPROC ; <107>
;--- This equate must be kept outside of code/data modules --- ; <107>
pMgrProcsSize EQU pMgrProcsEnd-pMgrProcs ; <107>
;-------------- Start of GetNewCWindow patch added by KON 10Nov89 --------------------
ptchGetNewCWindow PROC EXPORT
RomGetNewCWindow EQU $21c90
;
; First we call the existing routine to get a CWindow. Then we add a palette if one
; with the same ID exists in the resource file.
;
result EQU 18 ; parameter equates
winID EQU 16
wStor EQU 12
behind EQU 8
link a6, #0 ;no local parameters <10Nov89 KON>
clr.l -(sp) ;room for result from ROM GetNewCWindow <10Nov89 KON>
move.w winID(a6),-(sp) ;do same call as requested <10Nov89 KON>
move.l wStor(a6),-(sp)
move.l behind(a6),-(sp)
JSRRom RomGetNewCWindow ;call the old one <10Nov89 KON>
move.l (sp)+,result(a6) ;return result <10Nov89 KON>
;
; Check if palette with same ID as window exists (taken from getmgr.a)
;
clr.l -(sp) ; make room for palette handle <erich>
move winID(a6),-(SP) ; push window ID <erich>
_GetNewPalette ; fetchez la palette <erich>
move.l (sp)+,d0 ; well? <erich>
beq.s NoWindowPltt ; sorry, no automatic palette today AWC.PB459
move.l D0,A0 ; get the palette AWC.PB459
move.l (A0),A0 ; dereference it AWC.PB459
move PmPrivate(A0),D1 ; grab the update bits AWC.PB459
lsr #1,D1 ; put them in position AWC.PB459
bset #NNewBit,D1 ; use the new CUpdates format AWC.PB459
bset #DisposeBit,PmPrivate(A0) ; set for automatic disposal AWC.PB459
move.l result(a6),-(sp) ; push the window <10Nov89 KON>
move.l d0,-(sp) ; push the palette <erich>
move D1,-(sp) ; push cUpdates AWC.PB459
_SetPalette ; <erich>
NoWindowPltt ; AWC.PB459
unlk a6
move.l (sp)+,a0 ;return address
add #10,sp ;strip parameters, leave result
jmp (a0)
ENDPROC
;-------------- End of GetNewCWindow patch added by KON 10Nov89 ----------------------
;————————————————————————————————————————————————————————————————————————————————————————————————————————————
;********************** End Of PaletteMgr Patches? ************************
;————————————————————————————————————————————————————————————————————————————————————————————————————————————
;____________________________________________________________________________ DAF <2.6>
; Window manager patch
;
; This patch corrects a bug in SetWin/CtlColor in 32-bit addressing mode. These routines
; (which operate on identical data structures) can accept a colortable whose ctSize=-1
; which allows an application to specify that the wcTable be set to the default color
; set (via a copy of the color table handle). In 32-bit mode it is important that there
; be exactly one auxWinRec per window. This routine has a bug where -1 color tables can
; cause extra auxWinRecs to be allocated in 32-bit mode.
;
;
; procedure SetWinColor ( theWindow:windowPtr; newColorTable:CTabHandle );
;
; This procedure changes the awCTable field of the theWindow's auxWinRec.
; If newColorTable is equal to the default record's CTabHandle, then
; the auxWinRec is deallocated. If this window does not have an
; auxWinRec, then one is allocated at the head of the list. If theWindow
; is NIL, then the default colors are changed. If a record gets deallocated,
; it's colorTable is disposed unless it has it's resource bit set (then the
; app must take responsibility)
;
; Most of this code is shared with the control manager. Since the auxRec
; offsets are the same for both types of auxrecs, the code should be OK,
; even though the code uses the auxWinRec names.
;
NewSetWinColor PROC EXPORT
EXPORT NewSetCtlColor
ROMSetWinColorAfterSetGutsCall EQU $19744
ROMSetCtlColorAfterSetGutsCall EQU $1979C
ROMGetAuxGuts EQU $19888 ; GetAuxGuts in Aurora ROM
ROMSetGutsAfterSpecAlloc32Call EQU $197F6
ROMDeAlAux EQU $1983A
ROMSpecAlloc EQU $1981A
ROMSWCDone EQU $19816
MOVEM.L A2/A3,-(SP) ;get some address registers
MOVE.L AuxWinHead,A2 ;get the list head
LEA AuxWinHead,A3 ;in case we need to deallocate
BSR.S SetGuts ;bsr so that we can redraw on return
JMPROM ROMSetWinColorAfterSetGutsCall
NewSetCtlColor
MOVEM.L A2/A3,-(SP) ;get some address registers
MOVE.L AuxCtlHead,A2 ;get the list head
LEA AuxCtlHead,A3 ;in case we need to deallocate
BSR.S SetGuts ;
JMPROM ROMSetCtlColorAfterSetGutsCall
SetGuts
tWind EQU $18 ;some equates for parameters
nCTab EQU $14 ; after LINK (don't forget the movem above!)
LINK A6,#0 ;no globals
CLR.L -(SP) ;return AuxWinHandle here
CLR.W -(SP) ;function return here
CLR.L -(SP) ;NIL for default
PEA 6(SP) ;pointer to the placeholder
MOVE.L A2,A1 ;set up list head for GetAuxGuts
JSRROM ROMGetAuxGuts ;get the default record
ADDQ #2,SP ;ignore boolean result
MOVE.L (SP)+,A0 ;get the default handle
MOVE.L (A0),A0 ;get a pointer
MOVE.L awCTable(A0),A0 ;get the cTabHandle
CMP.L nCTab(A6),A0 ;if the same then deallocate
BEQ DeAlAux ;
CMP.L #-1,nCTab(A6) ;if -1, then allocate a rec with default table
BEQ.S SpecAlloc ;
MOVE.L A0,-(SP) ;save a reg (yuck, but registers are tight!)
MOVE.L nCTab(A6),A0 ;get the new color table handle
MOVE.L (A0),A0 ;get a pointer
CMP.W #-1,ctSize(A0) ;is ctSize -1?
MOVE.L (SP)+,A0 ;get the register back (don't change flags)
BEQ.S SpecAlloc32 ;If so, alloc a rec with default table
JMPROM ROMSetGutsAfterSpecAlloc32Call
DeAlAux JMPROM ROMDeAlAux
SpecAlloc JMPROM ROMSpecAlloc
; if this routine is called in 24-bit mode, then it falls through to SpecAlloc and makes
; a new auxWinRec with a copy of the default colortable. If it is called in 32-bit
; mode, then it finds the window's pre-existing auxWinRec (one is always guaranteed to
; exist) and sets it's colortable to be a copy of the default colortable handle.
SpecAlloc32
TST.B MMU32Bit ; are we in 32-bit mode?
BEQ.S SpecAlloc ; no, so allocate a new record with a copy of the default colors
MOVE.L A0,nCTab(A6) ; stick the default colors in the stack frame
CLR.L -(SP) ; return AuxWinHandle here
CLR.W -(SP) ; leave room for return value here
MOVE.L tWind(A6),-(SP) ; find this window
PEA 6(SP) ; point to placeholder
MOVE.L A2,A1 ; set up list head for GetAuxGuts (windows or controls)
JSRROM ROMGetAuxGuts ; get it (it will always be here in 32-bit mode)
ADDQ #2,SP ; the result should have always returned true
MOVE.L (SP)+,A0 ; get the win/ctl rec handle>
MOVE.L (A0),A0 ; get a pointer
MOVE.L nCTab(A6),awCTable(A0) ;and set the default colortable (in nCTab) field
JMPROM ROMSWCDone
;____________________________________________________________________________ GGD <2.7>
; Slot interrupt patch for _sIntInstall
;
; <2.2/2.7> Slot Interrupt patch: patches _SIntInstall, and reverses Slot
; interrupt queue order
;
; Change the treatment of Equal Priorities to match the Mac II, which ran the most
; recently installed element soonest when priorities were equal. This code matches
; Inside Mac Vol 5, and treats $FF as highest priority. The Mac II has a bug and
; treats $FF as LOWEST priority within the slot, but as HIGHEST priority across slots.
; Most cards seemed to beleive the documentation, and none have multiple handlers per slot,
; One developer figured out that the Mac II was backwards within the slot, and wanted to
; insert an element ahead of a priority zero (highest with Mac II bug) element. To do
; this, he took advantage of the was that equal priorities were treated on the Mac II,
; which is why we are now patching this to match.
;
SIntCorePtch proc export
WITH SlotIntQElement,slotIntGlobals
EXPORT SIntINSTALL
ROMGetSlotIntQHead equ $00006E30 ; offset to GetSlotIntQHead
;_______________________________________________________________________
;
; Routine: SIntINSTALL
;
; Arguments: D0 (input) : slot number for routine ($0..$E possible)
; A0 (input) : ptr to queue element
; D0 (output): error code - 0 no error
;
; Function: Installs a slot interrupt poll routine which is called when
; a slot interrupt occurs. The queue element is installed in
; in priority order, $FF highest (first), $00 lowest (last).
;
; When elements with EQUAL priorities exist, the most recently
; installed one is run sooner.
;
; <2.7> changes the treatment of Equal priorities to match Mac II.
;
; Only low byte of priority word is used (0-255 range).
; Priorities 200-255 are reserved by Apple.]
;
; The Mac II used to maintain priority across slots, which was
; used when multiple slots interrupted AT THE SAME TIME.
; We no longer support this, and prioritize by slot number instead.
; This will be removed from the Mac II in system 7.0
;
; The Mac II had a bug in SIntInstall, which had $FF as the highest
; priority across slots, but had $FF as the lowest within a slot.
; Most cards used the priority order as documented, ($FF highest), so
; we will retain that ordering.
; This will be fixed in the Mac II in System 7.0.
;
; Registers Used: D0,D1,D2,A0,A1
;_______________________________________________________________________
SIntINSTALL JsrROM ROMGetSlotIntQHead ; a1 := pointer to qheader
move.b SQPrio+1(a0),d0 ; get the priority (low byte of word)
move.w sr,-(sp) ; save interrupt level
ori.w #HiIntMask,sr ; disable interrupts
@PrioritySearch
move.l SQLink(a1),d1 ; get next queue element to check
beq.s @insert ; if end of list, insert before this
exg.l a1,d1 ; swap previous and current pointers
cmp.b SQPrio+1(a1),d0 ; compare priorities
blo.s @PrioritySearch ; loop until lower priority found (was BLS.S) <2.7>
; if equal, insert newer in front of older <2.7>
exg.l d1,a1 ; a1 points to previous, d1 points to current
@insert ; insert before the lower priority element
move.l d1,SQLink(a0) ; remainder of queue goes after new element
move.l a0,SQLink(a1) ; new element goes after previous element
move.w (sp)+,sr ; restore interrupt level
moveq.l #noErr,d0 ; return success
rts ; all done
ENDP
;____________________________________________________________________________ <20>
; Patches to Gestalt Functions
;____________________________________________________________________________
; The following gestalt selectors are patched or added in this file:
; - gestaltHardwareAttr
; - gestaltParityAttr
; - gestaltMiscAttr
; - gestaltVersion
; - gesaltNotificationMgrAttr
; - gestaltQuickdrawVersion
; - gestaltAddressingModeAttr
; - gestaltNuBusConnectors <95>
; - gestaltSerialAttr <95>
;
; The following gestalt selectors are removed in this file:
; - gestaltRBVAddr
; - gestaltSCCReadAddr
; - gestaltSCCWriteAddr
; - gestaltVIA1Addr
; - gestaltVIA2Addr
; - gestaltSlotAttr <95>
; - gestaltFirstSlot <95>
; - gestaltSlotCount <95>
;
;-----------------------------------------------------------------------------------------
;
; Record to describe gestalt function parameters
;
;-----------------------------------------------------------------------------------------
gestaltParmFrame record {oldA6},decrement
result ds.w 1 ; OSErr
argSize equ *-8
gestaltSelector ds.l 1 ; packed array [1..4] of char
gestaltResult ds.l 1 ; addr of longint result
return ds.l 1
oldA6 ds.l 1
localFrame equ *
endR
;____________________________________________________________________________ CCH <8>
; Gestalt function to effectively remove a selector
;
; The following is a gestalt function that will return an error as if the
; selector were undefined.
;
; Routine gestaltUndef (
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
; VAR gestaltResult: Longint;
; ): OSErr; = Integer;
;
gestaltUndef PROC EXPORT
with gestaltParmFrame
link a6,#localFrame
move.w #gestaltUndefSelectorErr,result(a6) ; return an error
unlk a6
move.l (sp)+,a0 ; get return value
add.l #argSize,sp ; restore stack pointer
jmp (a0) ; return
ENDP
;____________________________________________________________________________ CCH <10>
; Gestalt function for gestaltMiscAttr
;
; The following is a patch to the gestaltMiscAttr selector. It returns
; miscellaneous information about things.
;
; Routine gestaltMisc (
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
; VAR gestaltResult: Longint;
; ): OSErr; = Integer;
;
UserDelayTrap EQU $A84C ; user delay trap <17>
gestaltMisc PROC EXPORT
with gestaltParmFrame
link a6,#localFrame
clr.l d3 ; clear result
@hasBootGlobs bset #gestaltBootGlobals,d3 ; we have boot globals
@userDelay move.w #UnimplementedTrap,D0 ; get loc of unimplemented trap <58>
_GetTrapAddress ,newTool ; get the address into A0
Move.l A0,D2 ; save it for a sec
Move.l #UserDelayTrap,D0 ; trap ID to check for scrolling throttle
_GetTrapAddress ,newTool ; get the address of it
cmp.l a0,d2 ; is it unimplemented?
beq.s @squareMenus ; nope.. <58>
bset #gestaltScrollingThrottle,d3 ; <58>
@squareMenus move.b NTSC,d0 ; get a copy of the NTSC byte <58>
andi.b #$0F,d0 ; only look at bottom nibble <58>
bne.s @next ; if it's non-zero, menus aren't square <58>
bset #gestaltSquareMenuBar,d3 ; otherwise, it is! <58>
@next
move.l d3,d0 ; put result into d0 <58>
move.l gestaltResult(a6),a0 ; get address to place result
move.l d0,(a0) ;
move.w #noErr,result(a6) ; return no error
unlk a6
move.l (sp)+,a0 ; get return value
add.l #argSize,sp ; restore stack pointer
jmp (a0) ; return
ENDP
;____________________________________________________________________________ CCH <20>
; Gestalt function for gestaltNotificationMgrAttr
;
; The following is a patch to the gestaltNotificationMgrAttr selector.
; It indicates existence of the notification manager trap.
;
; Routine gestaltNMgr (
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
; VAR gestaltResult: Longint;
; ): OSErr; = Integer;
;
NMInstallTrap EQU $A05E ; notification manager install trap <20>
gestaltNMgr PROC EXPORT
with gestaltParmFrame
link a6,#localFrame
clr.l d0 ; clear result
Move.w #UnimplementedTrap,D0 ; get loc of unimplemented trap
_GetTrapAddress ,newTool ; get the address into A0
Move.l A0,D2 ; save it for a sec
Move.l #NMInstallTrap,D0 ; trap ID to check for notification mgr
_GetTrapAddress ,newTool ; get the address of it
Cmp.l A0,D2 ; is it unimplemented?
Beq.s @noNMgr ; it is?!
bset #gestaltNotificationPresent,d0 ; otherwise it exists
@noNMgr move.l gestaltResult(a6),a0 ; get address to place result
move.l d0,(a0) ;
move.w #noErr,result(a6) ; return no error
unlk a6
move.l (sp)+,a0 ; get return value
add.l #argSize,sp ; restore stack pointer
jmp (a0) ; return
ENDP
;____________________________________________________________________________ CCH <8>
; Gestalt function for gestaltVersion
;
; The following is a patch to the gestaltVersion selector. It returns the
; correct version number.
;
; Routine getGestaltVers (
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
; VAR gestaltResult: Longint;
; ): OSErr; = Integer;
;
getGestaltVers PROC EXPORT
with gestaltParmFrame
link a6,#localFrame
move.l gestaltResult(a6),a0 ; get address to place result
move.l #1,(a0) ; return response determined at install time
move.w #noErr,result(a6) ; return no error
unlk a6
move.l (sp)+,a0 ; get return value
add.l #argSize,sp ; restore stack pointer
jmp (a0) ; return
ENDP
;____________________________________________________________________________ jwk <95>
; Gestalt function for gestaltNuBusConnectors
;
; The following returns a bitmap of slots with NuBus connectors.
;
gestaltNBCon PROC EXPORT
MaxSlots EQU 16 ; max number of slots possible
with gestaltParmFrame, NuBusInfo, ProductInfo
link a6,#localFrame
movea.l UnivInfoPtr,a0 ; get universal info ptr
adda.l NuBusInfoPtr(a0),a0 ; add in offset to NuBus info
clr.l d0 ; clear index
clr.l d1 ; clear bitmap of NuBus connectors
@slotLoop btst #hasConnector,(a0,d0.w) ; does this slot have a connector?
beq.s @next ; if not, go look at next slot
bset.l d0,d1 ; note that this slot has a NuBus connector
@next addq #1,d0 ; bump up to next slot
cmpi.l #MaxSlots,d0 ; have we gone through all slots?
bne.s @slotLoop ; if not, keep going
move.l gestaltResult(a6),a0 ; get address to place result
move.l d1,(a0) ; return the bitmap of NuBus connectors
move.w #noErr,result(a6) ; return no error
unlk a6
move.l (sp)+,a0 ; get return value
add.l #argSize,sp ; restore stack pointer
jmp (a0) ; return
ENDP
;____________________________________________________________________________ EH <95>
; Gestalt function for gestaltSerialAttr
;
; The following is a patch to the gestaltSerialAttr selector.
; It indicates existence of serial attributes on the machine.
;
gestaltSerial PROC EXPORT
with gestaltParmFrame,ExpandMemRec,GestaltGlobals
link a6,#localFrame
movea.l ExpandMem,a0 ; get ptr to expandmem rec
movea.l emGestalt(a0),a0 ; get gestalt global ptr
moveq.l #0,d0 ; assume no GPI connections
cmpi.w #gestaltMacLC,machType(a0) ; <107> use real machine name now...
beq.s @noGPI
; IIci and IIsi have GPI connected
moveq.l #(1<<gestaltHasGPIaToDCDa)|\ ; GPIa connected to DCDa
(1<<gestaltHasGPIaToRTxCa)|\ ; GPIa connected to RTxCa clock input)
(1<<gestaltHasGPIbToDCDb),d0 ; GPIb connected to DCDb
@noGPI move.l gestaltResult(a6),a0 ; get address to place result
move.l d0,(a0) ;
move.w #noErr,result(a6) ; return no error
unlk a6
move.l (sp)+,a0 ; get return value
add.l #argSize,sp ; restore stack pointer
jmp (a0) ; return
ENDP
;____________________________________________________________________________ CCH <8>
; Gestalt function for gestaltParityAttr
;
; The following is a patch to the gestaltParityAttr selector. It correctly
; handles parity on Zone 5, as well as the IIci.
;
; Routine gestaltParity (
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
; VAR gestaltResult: Longint;
; ): OSErr; = Integer;
;
gestaltParity PROC EXPORT
EXPORT parityValue
with gestaltParmFrame
link a6,#localFrame
move.l gestaltResult(a6),a0 ; get address to place result
move.l parityValue,(a0) ; return response determined at install time
move.w #noErr,result(a6) ; return no error
unlk a6
move.l (sp)+,a0 ; get return value
add.l #argSize,sp ; restore stack pointer
jmp (a0) ; return
parityValue dc.l 0 ; response for parity selector
ENDP
;____________________________________________________________________________ CCH <3.2>
; Gestalt function for gestaltQuickdrawVersion
;
; The following is a patch to the gestaltQuickdrawVersion selector.
;
; Routine gestaltQDVers (
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
; VAR gestaltResult: Longint;
; ): OSErr; = Integer;
;
gestaltQDVers PROC EXPORT
with gestaltParmFrame
link a6,#localFrame
clr.l -(sp) ;make room for result
_OffScreenVersion
move.l gestaltResult(a6),a0 ; get address to place result
move.l (sp)+, d0 ; get QD version from GWorld
add.w #$100, d0
move.l d0, (a0) ; return version number for ci
move.w #noErr,result(a6) ; return no error
unlk a6
move.l (sp)+,a0 ; get return value
add.l #argSize,sp ; restore stack pointer
jmp (a0) ; return
ENDP
;____________________________________________________________________________ CCH <6.9>
; Gestalt function for gestaltAddressingModeAttr
;
; The following is a patch to the gestaltAddressingModeAttr selector to add the
; gestalt32BitCapable bit to this selector.
;
; Routine gestaltAddrMode (
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
; VAR gestaltResult: Longint;
; ): OSErr; = Integer;
;
gestaltAddrMode PROC EXPORT
with gestaltParmFrame
link a6,#localFrame
clr.l d0 ; clear result value <6.9>
move.b SystemInfo,d0 ; get status byte into d1 <6.9>
not.b d0 ; invert status bits <6.9>
and.l #3,d0 ; only want bit 0 and bit 1 <6.9>
bset #gestalt32BitCapable,d0 ; return that ROM is 32-bit clean <6.9>
move.l gestaltResult(a6),a0 ; get address to place result
move.l d0,(a0) ; save result <6.9>
move.w #noErr,result(a6) ; return no error
unlk a6
move.l (sp)+,a0 ; get return value
add.l #argSize,sp ; restore stack pointer
jmp (a0) ; return
ENDP
IF doScriptMgrGestalt AND (NOT installScriptMgrPtch27) THEN ; <6.1><50>
;____________________________________________________________________________ pke <2.5>
; Gestalt function for Script Mgr <08/05/89 pke>
;
; The following Gestalt Function is an interface between the Gestalt mechanism
; and the Script Manager's GetEnvirons routine. Currently, it only supports two
; Gestalt selectors: gestaltScriptMgrVersion and gestaltScriptCount.
;
; Routine gestaltScriptMgr (
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
; VAR gestaltResult: Longint;
; ): OSErr; = Integer;
;
; <08/05/89 pke> New today
;
gestaltScriptMgr proc export
export gestaltSMgrTable ; table for installation <8/05/89 pke>
with gestaltParmFrame ; <3.2>
link a6,#localFrame
; initialize loop, set up default return values
move.l gestaltSelector(a6),d0 ; selector value
;; move.l gestaltResult(a6),a0 ; addr for result
;; clr.l (a0) ; initially set result to 0
move.l #gestaltUndefSelectorErr,result(a6) ; assume unknown selector
lea gestaltSMgrTable,a1
; loop to find Gestalt selector in table
@gestaltLoop
move.l (a1)+,d1 ; get next table entry
beq.s @gestaltDone ; end of list, quit
move.w (a1)+,d2 ; now get GetEnvirons verb
cmp.l d0,d1 ; is selector correct?
bne.s @gestaltLoop ; no, get next one
; ok, we found the Gestalt selector. Now call GetEnvirons with correct verb
clr.l -(sp) ; space for result
move.w d2,-(sp) ; push verb
_GetEnvirons
move.l gestaltResult(a6),a0 ; addr for result
move.l (sp)+,(a0) ; pop result into Gestalt
move.w #noErr,result(a6) ; return no error
; all done
@gestaltDone
unlk a6
move.l (sp)+,a0
add.l #argSize,sp
jmp (a0)
endWith
; Table for converting between gestalt selectors and GetEnvirons verbs. Each pair
; consists of a long with the gestalt selector, followed by a word with the
; GetEnvirons verb. This table and the equate files where the Gestalt selectors
; are defined are the only things that need to change to add new Gestalt selectors
; for the Script Manager.
gestaltSMgrTable
dc.l gestaltScriptMgrVersion
dc.w smVersion
dc.l gestaltScriptCount
dc.w smEnabled
dc.l 0 ; terminator
endProc
ENDIF ; <6.1>
IF NOT SPLINE_FONT THEN ; <6.0.5>
;____________________________________________________________________________ CEL <5>
; NewRSect (fixes DrawText)
;
; DrText had a check to see if the advance width of a character was zero. If so,
; it would skip the character. This was bad since International uses zero width
; characters to lay out certain kanji or vertical text. only one line needed to
; be taken out. The patch is big but the change is small.
;
NewRSect proc export
;-------------------------------------------
;
; KERNED STRIKE FONT FORMAT OFFSETS:
;
FORMAT EQU 0 ;WORD
MINCHAR EQU 2 ;WORD
MAXCHAR EQU 4 ;WORD
MAXWD EQU 6 ;WORD
FBBOX EQU 8 ;WORD fKernMax
FBBOY EQU 10 ;WORD save as nDescent; unused except as high owTLoc
FBBDX EQU 12 ;WORD fRectWidth
FBBDY EQU 14 ;WORD fRectHeight
LENGTH EQU 16 ;WORD owTLoc
locASCENT EQU 18 ;WORD Conflict with other Ascent and Descent defines
locDESCENT EQU 20 ;WORD
XOFFSET EQU 22 ;WORD leading
RASTER EQU 24 ;WORD rowWords
;------------------------------------------------------
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE EQU 14 ;SIZE OF PARAMETERS
COUNT EQU PARAMSIZE+8-2 ;WORD
TEXTADDR EQU COUNT-4 ;LONG
NUMER EQU TEXTADDR-4 ;LONG, POINT
DENOM EQU NUMER-4 ;LONG, POINT
;-----------------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
SAVESTK EQU -4 ;long stack before allocating buffers
TEXTRECT EQU SAVESTK-8 ;RECT original bounding rect
TEXTR2 EQU TEXTRECT-8 ;RECT copy of textRext used by maprect
SRCRECT EQU TEXTR2-8 ;RECT original shadow bounding rect
DSTRECT EQU SRCRECT-8 ;RECT copy of srcRect used by maprect
MINRECT EQU DSTRECT-8 ;RECT minimum rect for clipping
BUFEND EQU MINRECT-4 ;LONG where the offscreen buffer ends
BUFSIZE EQU BUFEND-2 ;WORD the size of the offscreen buffer
BUFROW EQU BUFSIZE-2 ;WORD the rowBytes for the offscreen buffer
BUF2START EQU BUFROW-4 ;LONG second buffer used for shadow
BUF2END EQU BUF2START-4 ;LONG where shadow buffer ends
BUFLEFT EQU BUF2END-2 ;WORD output left edge
HEIGHT EQU BUFLEFT-2 ;WORD font fRectHeight copy
SRCPTR EQU HEIGHT-4 ;LONG used only in wide character case as temp
DSTPTR EQU SRCPTR-4 ;LONG used only in wide character case as temp
BUFSTART EQU DSTPTR-4 ;LONG \ start of bits buffer
SRCADDR EQU BUFSTART-4 ;LONG >- these 3 grouped: address of font bits
SRCROW EQU SRCADDR-4 ;LONG / rowbytes of font bits
maskStart EQU SRCROW-4 ;LONG \ start of mask buffer
maskAddr EQU maskStart-4 ;LONG >- these 3 grouped: address of mask bits
mSrcRow EQU maskAddr-4 ;LONG / rowbytes of mask bits
FROMRECT EQU mSrcRow-8 ;RECT mapRect parameter
TORECT EQU FROMRECT-8 ;RECT mapRect parameter
PENLOC EQU TORECT-4 ;POINT copy of original pnLoc
SPWIDTH EQU PENLOC-4 ;FIXED POINT width of space
CHARLOC EQU SPWIDTH-4 ;FIXED POINT fractional pen position
HEIGHTAB EQU CHARLOC-4 ;LONG pointer to font height table
WIDTAB EQU HEIGHTAB-4 ;LONG pointer to font offset/width table
LOCTAB EQU WIDTAB-4 ;LONG pointer to font location table
SAVEA5 EQU LOCTAB-4 ;LONG register saved so can be reused
characterExtra EQU SAVEA5-4 ;LONG fixed point extra added to each character
maskBitsPtr EQU characterExtra-4 ;LONG pointer to maskBits, sourcePix, or 0
bkCol EQU maskBitsPtr-4 ;LONG full of the background color
leftBack EQU bkCol-4 ;LONG bkCol masked to the left part of the character
rightBack EQU leftBack-4 ;LONG bkCol masked to the right part of the character
REALBOUNDS EQU rightBack-4 ;LONG USED FOR SHIELDCURSOR
leftOffset EQU REALBOUNDS-8 ;2 LONGs offset used by bit field instructions in charblt
maskSize EQU leftOffset-2 ;WORD size of mask buffer
mBufRow EQU maskSize-2 ;WORD \ these 2 mask buffer row size
maskBlts EQU mBufRow-6 ;3 WORDS / grouped: saved state for mask blit
FAKERGN EQU maskBlts-10 ;RECTANGULAR REGION
FAKEPTR EQU FAKERGN-4 ;LONG, FAKE MASTER POINTER
INFO EQU FAKEPTR-8 ;4 WORDS font info record returned by txMeasure (unused)
NUMER2 EQU INFO-4 ;Point copy of numer for iterative case
DENOM2 EQU NUMER2-4 ;Point copy of denom for iterative case
charsRemain EQU DENOM2-2 ;word remaining characters to draw in iterative case
SRCBITS EQU charsRemain-14 ;bitMap input to shadow stretchBits, bitsToPix
SRCPIX EQU SRCBITS-(PMREC+CTREC+20) ;pixMap input to normal stretchbits
maskBits EQU SRCPIX-14 ;bitMap input to bitsToPix for font mask
DSTPIX EQU maskBits-(PMREC+CTREC+20) ;pixMap destination
FASTFLAG EQU DSTPIX-1 ;BYTE flag set if source ORing to screen is OK
maskFont EQU FASTFLAG-1 ;byte flag set if a maskFont is available + requested
STRETCH EQU maskFont-1 ;BOOLEAN flag set if numerator not equal denominator
HEIGHTFLAG EQU STRETCH-1 ;byte flag set if font has a height table
TOPHT EQU HEIGHTFLAG-2 ;word character top & height from font or clip
MAXMIN EQU TOPHT-2 ;word number of characters in font
MINCH EQU MAXMIN-2 ;word first character in font
bitDepth EQU MINCH-2 ;word \ These two bits per pixel in font
bkCol1 EQU bitDepth-2 ;word / grouped. 1 pixel worth of background color
italicSlop EQU bkCol1-2 ;word extra width due to italic, bold, outline, shadow
kernAdjust EQU italicSlop-2 ;word left kerning due to kerning and italic
penLocHFrac EQU kernAdjust-2 ;word fractional pen position for recursive calls
longCount EQU penLocHFrac-2 ;word loop counter for doMove
charWidth EQU longCount-2 ;word width in pixels of current character blt
stackOffset EQU charWidth-2 ;word 2 if stack was word aligned before link
countCopy EQU stackOffset-2 ;word copy of character count, decremented as drawn
CRSRFLAG EQU countCopy-1 ;BYTE set if crsr is shielded (to screen)
MMUSave EQU CRSRFLAG-1 ;BYTE MMU mode on entry to drawText
locMode EQU MMUSave-2 ;word copy of text mode, adjusted if arith. + 1 bit
bitShift EQU locMode-2 ;word how far to shift to multiply by bitDepth
orNotOK EQU bitShift-1 ;Boolean true if bit extract/insert must be used instead
notMaskPass EQU orNotOK-1 ;Boolean true if blit is not creating font mask
textCopyMode EQU notMaskPass-1 ;Boolean true if blit must use extract/insert
orMode EQU textCopyMode-1 ;Boolean true if mode is srcOr & forecolor is black
colorSource EQU orMode-1 ;Boolean true if font contains colors (nonblack/white)
saveHilite EQU colorSource-1 ;byte saved hilite flag for iterative state
run32bit EQU saveHilite-1 ;byte flag to run 32 bit
VARSIZE EQU (((run32bit+1)/4)-1)*4 ;SIZE OF VARIABLES long aligned
FromDrText EQU $28468
ROMRSect EQU $2C6D4
RomIterate EQU $281AA
cmpRA FromDrText,(sp) ; is this called from DrText?
beq.s @doDrTextPatch ; yes, go fix the patch
jmpROM ROMRSect ; call back to the ROM
@doDrTextPatch
ADDQ #4, sp ; Pop off return addr and come back here
jsrROM ROMRSect ; call back to the ROM
;---------------------------------------------------------------------------------------
; < BELOW COPIED VERBATIM FROM THE ROM UNTIL FURTHER NOTICE >
;
BEQ GOHOME ;QUIT IF NO INTERSECTION
MOVE (SP)+,textR2+right(A6) ;restore text right
;
; Test to see if spline:
; If spline set up clipping variables
;
;
; Set up srcAddr, srcRow, and height
;
LEA 26(A2),a0 ;GET START OF FONT BITMAP
MOVE.L a0,SRCADDR(A6) ;SAVE FOR LATER
MOVEQ #0,D1 ;zero high word
MOVE RASTER(A2),D1 ;GET WORDS PER ROW IN FONT
MOVE bitShift(A6),D0
LSL.L D0,D1 ;scale up font rowWords
ADD.L D1,D1 ;DOUBLE FOR BYTES PER ROW
MOVE.L D1,SRCROW(A6) ;REMEMBER FOR LATER
MOVE FBBDY(A2),HEIGHT(A6) ;SETUP HEIGHT FOR LATER
;
; Test for fast case:
; not stretched, no color mapping, txMode = srcOr, same bits per pixel
; not bold, italic, underlined, outlined or shadowed,
; visRgn and clipRgn both rectangular.
;
TST.B fmOutItalic(A4) ;TEST BOLD $$$
BNE NOTFAST ;NOT FAST UNLESS BOTH ZERO
TST.B fmOutBold(A4) ;TEST BOLD
BNE NOTFAST ;NOT FAST
TST.B orMode(A6) ;IS TEXT MODE SRCOR ? (or srcCopy + mask, see above)
BEQ NOTFAST ;NO, NOT FAST
TST.W 10(A4) ;TEST ULTHICK AND SHADOW
BNE NOTFAST ;NOT FAST UNLESS BOTH ZERO
TST.B STRETCH(A6) ;IS TEXT STRETCHED ?
BNE NOTFAST ;YES, NOT FAST
MOVE.L ([CLIPRGN,A3]),A0 ;GET CLIPRGN HANDLE, dereferenced
MOVEQ #10,D0
CMP RGNSIZE(A0),D0 ;IS CLIPRGN RECTANGULAR ?
BNE NOTFAST ;NO, NOT FAST
MOVEQ #1,D0
MOVE bitShift(A6),D1 ;get the depth of the source map
LSL D1,D0 ;turn into 1 … 8
CMP DSTPIX+PIXELSIZE(A6),D0 ;same depth per pixel?
BNE NOTFAST ;=>NOPE
cmp #16,dstPix+pixelType(A6) ;is it a direct device? @@@@ BAL 16Jun88
bne.s @modeok
seq textCopyMode(a6) ;yes, can't go fast for now @@@@ BAL 16Jun88
clr locmode(a6) ;this essentially alters mode to srcCopy
bra NotFast
@modeok MOVE.L VISRGN(A3),A1 ;GET VISRGN HANDLE
MOVE.L (A1),A0 ;DE-REFERENCE IT
CMP #10,RGNSIZE(A0) ;IS VISRGN RECTANGULAR ?
BEQ.S FAST ;YES, TAKE FAST OPTIMIZATION
;
; All systems go except for VisRgn not rectangular.
; Check if visRgn sect minRect is rectangular.
; IF TrimRect(visRgn,minRect) THEN take the fast way.
;
MOVE.L A1,-(SP) ;PUSH VISRGN
PEA MINRECT(A6) ;PUSH MINRECT
MOVE.W #-1,-(SP) ;pass Trim = True
_TRIMRECT ;CALL TRIMRECT
BLT GOHOME ;quit if intersection empty
BGT NOTFAST ;continue if non-rectangular
;
; Fast case, go directly to screen.
; If text is clipped vertically, then clear heightflag and update TOPHT
;
FAST
ST FASTFLAG(A6) ;REMEMBER WE'RE GOING FAST
CLR.B maskFont(A6) ;no need for second mask pass in fast case
CLR.L bkCol(A6) ;zero out back color long
MOVE MINRECT+TOP(A6),D0 ;GET MINRECT.TOP
MOVE MINRECT+BOTTOM(A6),D1 ;GET MINRECT.BOTTOM
SUB TEXTRECT+TOP(A6),D0 ;was top clipped ?
BNE.S VCLIP ;yes, handle clip
CMP TEXTRECT+BOTTOM(A6),D1 ;was bottom clipped ?
BEQ.S VCLIPOK ;no, continue
VCLIP CLR.B HEIGHTFLAG(A6) ;can't use height table
MOVE.B D0,TOPHT(A6) ;use adjusted top
SUB MINRECT+TOP(A6),D1 ;calc clipped height
MOVE.B D1,TOPHT+1(A6) ;replace TOPHT
VCLIPOK MOVE TEXTRECT+TOP(A6),D0 ;GET DST TOP
SUB DSTPIX+BOUNDS+TOP(A6),D0 ;CONVERT TO GLOBAL COORDINATES
MOVE DSTPIX+ROWBYTES(A6),D1 ;GET ROWBYTES
AND #nuRBMask,D1 ;CLEAR OFF FLAG BITS
MULS D1,D0 ;MULT BY ROWBYTES
ADD.L DSTPIX+BASEADDR(A6),D0 ;ADD START OF DST BITMAP
MOVE.L D0,BUFSTART(A6) ;SET UP BUFSTART FOR LATER
MOVE D1,BUFROW(A6) ;SET UP BUFROW FOR LATER
MOVE DSTPIX+BOUNDS+LEFT(A6),BUFLEFT(A6) ;REMEMBER BUFLEFT
TST.B CRSRFLAG(A6) ;IS DST TO A SCREEN? <BAL 19Sep88>
BEQ GETPTRS ;=>NO
PEA MINRECT(A6) ;PUSH SHIELD RECT
MOVE.L REALBOUNDS(A6),-(SP) ;PUSH DELTA FOR GLOBAL
_SHIELDCURSOR ;HIDE CURSOR IF IT INTERSECTS
;-----------------------------------------------------------
;
; Clean pointers and then
; Switch to 32 bit addressing mode
;
MOVE.L SRCADDR(A6),d0 ;get 24 bit base addr
_Translate24To32 ;mask off high byte BAL/MCF 03Dec88
MOVE.L d0,SRCADDR(A6) ;SAVE FOR LATER
move.l a2,d0 ;get FontPtr
_Translate24To32 ;mask off high byte BAL/MCF 03Dec88
move.l d0,a2 ;clean font ptr
@setMMUMode
MOVE stackOffset(A6),D1
MOVE.L TEXTADDR(A6,D1),D0 ;GET TEXTPTR
_Translate24To32 ;mask off high byte BAL/MCF 03Dec88
MOVE.L d0,TEXTADDR(A6,D1) ;SAVE FOR LATER
moveq #true32b,d0 ;switch to 32 bit addressing
move.l a2,-(sp) ;save FontPtr
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
move.l (sp)+,a2 ;restore FontPtr
move.b d0,MMUsave(a6) ;save previous state for later
MOVE.B #1, run32bit(A6) ; Set flag to state running 32 bit clean
BRA GETPTRS
NOTSCREEN
;
; Slow case: Setup for an off-screen buffer.
;
; Calc bufLeft: (LONG-align to avoid shift)
;
NOTFAST SF FASTFLAG(A6) ;NOT GOING DIRECTLY TO SCREEN
SF CRSRFLAG(A6) ;CRSR HAS NOT BEEN SHIELDED <BAL 19Sep88>
MOVE TEXTRECT+LEFT(A6),D0 ;GET TEXTRECT LEFT
SUB DSTPIX+BOUNDS+LEFT(A6),D0 ;CONVERT TO GLOBAL
AND #$FFE0,D0 ;TRUNC TO LONG BOUND
ADD DSTPIX+BOUNDS+LEFT(A6),D0 ;RETURN TO LOCAL COORDS
MOVE D0,BUFLEFT(A6) ;REMEMBER FOR LATER
;
; Calculate buffer size
;
MOVEQ #0,D1 ;clear high word
MOVE TEXTRECT+RIGHT(A6),D1 ;BUFRIGHT := TEXTRECT RIGHT
SUB D0,D1 ;WIDTH:=BUFRIGHT-BUFLEFT
MOVE D1,D2 ;mask depth as well
MOVE bitShift(A6),D4 ;convenient constant
LSL.L D4,D1 ;scale up by pixel size + 1 for mask
LSR.L #5,D1 ;CONVERT DOTS TO LONGS
ADD #2,D1 ;ROUND UP PLUS EXTRA LONG
MOVE HEIGHT(A6),D3 ;GET HEIGHT
MULU D1,D3 ;BUFSIZE:=HEIGHT*BUFROW LONGS
; if the intermediate result is too big, stop before going any further
CMP.L #$1C00,D3 ;is it bigger than 28K? (unit is longs)
BGT.S DoSubDivide ;if so, draw fewer characters at a time
MOVE D3,BUFSIZE(A6) ;SAVE FOR LATER
ADD D1,D3 ;add for stretch srcBuf
LSL #2,D1 ;QUAD BUFROW FOR BYTES
MOVE D1,BUFROW(A6) ;SAVE FOR LATER
MOVE TEXTR2+RIGHT(A6),D5
SUB TEXTR2+LEFT(A6),D5
LSR #5,D5 ;convert to longs
ADDQ #2,D5 ;account for slop
MOVE D5,D0
ADD D0,D3 ;in case clip is nonrectangular
ADD D0,D3 ;in case vis is nonrectangular
LSL D4,D0 ;scale up by source depth
ADD D0,D3 ;add stretch destination buffer size
MULU dstPix+pixelSize(A6),D5 ;size of composite mask
ADD D5,D3 ;include it
;if srcDepth not equal to dstDepth, add stretch dest. buf. again
ADD D5,D3 ;include space for scale buffer
;set up maskSize, maskRow
TST.B maskFont(A6) ;do we need a mask to pass to stretchBits?
BEQ.S @noMask
LSR #5,D2 ;CONVERT DOTS TO LONGS
ADD #2,D2 ;ROUND UP PLUS EXTRA LONG
ADD D2,D1 ;total number of longs
MOVE HEIGHT(A6),D0 ;GET HEIGHT
MULU D2,D0 ;BUFSIZE:=HEIGHT*BUFROW LONGS
MOVE D0,maskSize(A6) ;SAVE FOR LATER
LSL #2,D2 ;QUAD BUFROW FOR BYTES
MOVE D2,mBufRow(A6) ;SAVE FOR LATER
ADD D0,D3 ;add for stack check calculation
ADD D2,D3 ;add for stretch srcMaskBuf
MOVE TEXTR2+RIGHT(A6),D0
SUB TEXTR2+LEFT(A6),D0
LSR #5,D0 ;convert from dots to longs
ADD D0,D3 ;add stretch mask destination buffer size
@noMask
;
; Calculate total stack requirements for off-screen buffers.
;
TST.B 11(A4) ;ARE WE SHADOWING ?
BEQ.S @1 ;NO, CONTINUE
ADD bufSize(A6),D3 ;YES, CALC 2*BUFSIZE
ADD D1,D3 ;add in 4 * source rows for shadow
@1 LSL.L #2,D3 ;CALC TOTAL STACK BYTES NEEDED
; how much slop? size of scale table (256 bytes maximum)
; size of stretch stack frame (750 bytes for parameters, local stack frame, saved regs),
; and about 1K for interrupts.
ADD.L #2048,D3 ;ADD 2 KBYTE SLOP
;
; If stack is too small to allocate buffer(s), then draw half as many characters at a time.
;
_StackAvail ;Get StackAvail IN D0
CMP.L D0,D3 ;IS stackNeeded > stackAvail ?
BLE.S StackAlmost ;NO, CONTINUE
DoSubDivide
MOVE stackOffset(A6),D6 ;2 if stack was not aligned, otherwise, 0
MOVE count(A6,D6),D0 ;how many characters to draw
MOVE D0,D7 ;figure half
LSR #1,D7
BNE.S @subDivide ;if more than 1 left, can subdivide problem
SUBQ #1,charsRemain(A6) ;pretend the one character was drawn
BRA GoHome ;if only 1 character, punt
@subDivide
; *** look for space character? Could adjust D7 to coincide with a space if any, making
; *** drawing look better (for italics, kerns)
TST charsRemain(A6) ;if zero, this is the first time through
BNE.S @notFirst
MOVE.B HiliteMode,saveHilite(A6) ;save original in case stretch is called multiple times
MOVE D0,charsRemain(A6) ;initialize partial count drawing location
@notFirst
MOVE.L PENLOC(A6),PNLOC(A3) ;RESTORE PNLOC TO ORIGINAL
TST PORTBITS+ROWBYTES(A3) ; is it a new port?
BPL.S @useOld ; no, no fraction to restore
MOVE PenLocHFrac(A6),pnLocHFrac(A3) ;restore fraction if applicable
@useOld
MOVE D7,count(A6,D6) ;reset count to draw
doIterate
MOVE.L grafGlobals(A5),A4 ;set up grafGlobals pointer for getting real width
MOVE.L numer2(A6),numer(A6,D6) ;restore numerator
MOVE.L denom2(A6),denom(A6,D6) ;restore denominator
MOVE.B saveHilite(A6),HiliteMode ;restore hilite bit
;
; < ABOVE COPIED VERBATIM FROM THE ROM >
;---------------------------------------------------------------------------------------
; JMP Iterate ;draw first half of string
JMPRom RomIterate ;
;---------------------------------------------------------------------------------------
; < BELOW COPIED VERBATIM FROM THE ROM >
;
; draw the second half of the string, but drawing no more characters than could be successfully
; drawn by the first half.
secondHalf
MOVEQ #0,D7 ;zero high word
MOVE stackOffset(A6),D6 ;2 if stack was not aligned, otherwise, 0
MOVE count(A6,D6),D7 ;number of characters drawn last
MOVE charsRemain(A6),D0 ;how many characters remain?
CMP D0,D7 ;dont try to draw more than worked last
BLE.S @ok
MOVE D0,count(A6,D6) ;draw what remains for the second half
@ok
ADD.L D7,textAddr(A6,D6) ;bump source address by half already drawn
BRA.S doIterate
; ————————————————————————————————————————————————————————————————————————————————————————————
;
; Allocate and clear an off-screen buffer
;
; If the source font is only 1 bit deep, clear the screen to white. Also, if the transfer
; mode is xor, bic, or, clear the screen to white. If an arithmetic mode or copy and
; source is multibits deep, assume depth of source font is equal to destination depth.
; Also assume that background of buffer must be colored the same as the port background color.
StackAlmost
MOVEQ #0,D0 ;get a long of white
TST bitShift(A6) ;is source 1 bit?
BEQ.S @whiteBackCol
CMP #srcXor,locMode(A6) ;srcXor?
BEQ.S @whiteBackCol ;even if font contains colors, leave background white
TST.B colorSource(A6) ;font contains color?
BNE.S @useBackCol ;if so, must color the buffer
CMP #$32,locMode(A6) ;hilite?
BEQ.S @whiteBackCol ;leave background white if so
BTST #5,locMode+1(A6) ;arithmetic?
BEQ.S @whiteBackCol ;if copy, or leave background white
@useBackCol
SUBQ #6,SP ;allocate VAR RGBColor
MOVE.L SP,-(SP) ;point to VAR RGBColor
_GetBackColor ;ask for the background color
CLR.L -(SP) ;make room for function result
PEA 4(SP) ;point to VAR RGBColor
_Color2Index
MOVEQ #0,D0
MOVEQ #32,D1 ;
MOVE bitDepth(A6),D2 ;get destination bits per pixel
@nxtPixel
ASL.L D2,D0
OR.l (SP),D0 ;or in result of color2Index <BAL 04July88>
SUB D2,D1
BGT.S @nxtPixel
ADD #10,SP ;strip RGBColor and long result
@whiteBackCol
MOVE.L D0,bkCol(A6) ;save for comparing with background, later
STACKOK MOVE bufSize(A6),D3
SUBQ #1,D3 ;INIT DBRA LOOP COUNT
MOVE.L D0,-(SP) ;PAD BUFFER WITH AN EXTRA ZERO
MOVE.L SP,BUFEND(A6) ;REMEMBER WHERE BUFFER ENDS
CLRLOOP MOVE.L D0,-(SP)
DBRA D3,CLRLOOP ;ALLOCATE AND CLEAR BUFFER
MOVE.L SP,BUFSTART(A6) ;REMEMBER START OF BUFFER
MOVE.L D0,-(SP) ;PAD BUFFER WITH AN EXTRA ZERO
TST.B maskFont(A6)
BEQ.S @noMask
MOVE maskSize(A6),D3
SUBQ #1,D3
CLR.L -(SP)
@clrMask
CLR.L -(SP)
DBRA D3,@clrMask
MOVE.L SP,maskStart(A6)
@noMask
CLR.L -(SP)
;
; Get pointers to location table, width table, and height table in font
;
GETPTRS
LEA 26(A2),A0 ;GET START OF FONT BITMAP
MOVEQ #0,D0 ;zero high word
MOVE FBBDY(A2),D0 ;GET HEIGHT OF FONT BITMAP
MULU.L SRCROW(A6),D0 ;CALC TOTAL SIZE OF STRIKE
ADD.L D0,A0 ;A1 := START OF LOC TABLE
MOVE.L A0,LOCTAB(A6) ;SAVE FOR LATER
; *** could test bitShift first and only check fNDescent if bitDepth > 1 …
MOVE.W fNDescent(A2),D0 ;possibly the high word of owTLoc
SWAP D0 ;put it in the high word
BPL.S @notNegative
MOVEQ #0,D0 ;old fonts have negative of ascent here
@notNegative
MOVE LENGTH(A2),D0 ;HOW MANY WORDS IN STRIKE BODY
LEA 16(A2,D0.L*2),A1 ;GET START OF WIDTH TABLE
MOVE.L A1,WIDTAB(A6) ;SAVE FOR LATER
MOVE MAXCHAR(A2),D0 ;GET MAXCHAR
MOVE MINCHAR(A2),D1 ;GET MINCHAR
MOVE D1,MINCH(A6) ;STASH MINCHAR FOR LATER
SUB D1,D0 ;CALC MAXCHAR-MINCHAR
MOVE D0,MAXMIN(A6) ;SAVE FOR LATER
ADD #3,D0 ;CALC MAXMIN+3
BTST #1,1(A2) ;DOES FONT HAVE WIDTH TABLE ?
BEQ.S NOWID ;NO, CONTINUE
ADD D0,D0 ;SKIP WIDTH TABLE
NOWID LEA 0(A1,D0*2),A0 ;POINT TO HEIGHT TABLE
MOVE.L A0,HEIGHTAB(A6) ;SAVE FOR LATER
;
; Set up space width
;
MOVE.L widthTabHandle,A0 ;point to width table
MOVE.L (A0),A0
MOVE.L 128(A0),SPWIDTH(A6) ;get width of the space char
;
; Setup misc stuff in registers for speed
;
MOVE BUFLEFT(A6),D1 ;GET BUFLEFT
MOVE PENLOC+H(A6),D0 ;GET PEN LOCATION
ADD kernAdjust(A6),D0 ;ADJUST FOR KERNING
SUB D1,D0 ;MAKE CHARLOC RELATIVE TO BUFLEFT
MOVE.W D0,CHARLOC(A6) ;INIT INT PART OF CHARLOC
TST PORTBITS+ROWBYTES(A3) ;is it a new port?
BPL.S @useOld ;no, set fraction to 1/2
MOVE penLocHFrac(A6),CHARLOC+2(A6) ;set up fractional part <PB362> BAL
BRA.S @goOn
@useOld
MOVE #$8000,CHARLOC+2(A6)
@goOn
SUB D1,MINRECT+LEFT(A6) ;MAKE MINRECT.LEFT AND
SUB D1,MINRECT+RIGHT(A6) ;MINRECT.RIGHT BUFFER RELATIVE
MOVE stackOffset(A6),D0
MOVE.L TEXTADDR(A6,D0),A1 ;GET TEXTPTR
BRA.S NEXTCH ;GO TO LOOP START
;---------------------------------------------------
;
; Here's the main character drawing loop:
;
MISSING
MOVE MAXMIN(A6),D0 ;NO, USE MISSING SYMBOL
ADD #1,D0 ;WHICH IS ONE PAST MAXCHAR
MOVE.L WIDTAB(A6),A0 ;POINT TO WIDTH TABLE
MOVE 0(A0,D0*2),D3 ;GET OFFSET AND WIDTH BYTES
CMP #-1,D3 ;missing?
BNE NOTMISS ;IS MISSING CHAR MISSING ?
BRA.S NEXTCH ;YES, SKIP THIS CHAR
SPACECH MOVE.L SPWIDTH(A6),D1 ;GET SPACE WIDTH
ADD.L D1,CHARLOC(A6) ;BUMP CHARLOC
SKIPCH SUB #1,charsRemain(A6) ;decrement total character count
SUB #1,countCopy(A6) ;decrement partial draw character count
BLE STRDONE ;QUIT IF CHARCOUNT <= 0
NEXTCH CLR D0 ;get ready for byte
MOVE.B (A1)+,D0 ;GET NEXT CHAR
CMP.B #32,D0 ;IS IT A SPACE ?
BEQ.S SPACECH ;YES, HANDLE IT
MOVE.L WidthTabHandle,A0 ;POINT TO WIDTH TABLE
MOVE.L (A0),A0
MOVE D0,D4 ;COPY CHARACTER
MOVE.L 0(A0,D4*4),D4 ;GET FIXED POINT WIDTH
ADD.L characterExtra(A6),D4 ;add in character extra, if any
;
; < ABOVE COPIED VERBATIM FROM THE ROM >
;
;---------------------------------------------------------------------------------------
;
; BLE.S SKIPCH ;SKIP CharBlt if Advance width <= 0 <1.6-11april89-CEL>
;
;---------------------------------------------------------------------------------------
;
; < BELOW COPIED VERBATIM FROM THE ROM UNTIL FURTHER NOTICE >
;
SUB MINCH(A6),D0 ;SUBTRACT SAVED MINCHAR
CMP MAXMIN(A6),D0 ;IS CH BETWEEN MINCHAR AND MAXCHAR ?
BHI MISSING ;Missing so skip it
OKCHAR MOVE.L WIDTAB(A6),A0 ;POINT TO WIDTH TABLE
MOVE 0(A0,D0*2),D3 ;GET OFFSET AND WIDTH BYTES
CMP #-1,D3 ;missing?
BEQ MISSING ;OFFSET NEG = MISSING CHAR
NOTMISS LSR #8,D3 ;GET OFFSET BYTE
ADD.W CHARLOC(A6),D3 ;DSTLEFT := CHARLOC.INT + OFFSET
ADD.L D4,CHARLOC(A6) ;ADD FIXED POINT WIDTH TO CHARLOC
MOVE.L LOCTAB(A6),A0 ;POINT TO LOCATION TABLE
MOVEQ #0,D1 ; *** clear top word
MOVE 0(A0,D0*2),D1 ;GET SRCLEFT
MOVE 2(A0,D0*2),D2 ;GET SRCRIGHT
SUB D1,D2 ;CALC WIDTH OF BITS
BLE SKIPCH ;SKIP CHARBLT IF WIDTH <= 0
MOVE D2,charWidth(A6) ;save for later
ADD D3,D2 ;DSTRIGHT := DSTLEFT + WIDTH
TST.B HEIGHTFLAG(A6) ;does font have height table ?
BEQ.S NOHEIGHT ;no, continue
MOVE.L HEIGHTAB(A6),A0 ;get height table
MOVE 0(A0,D0*2),TOPHT(A6) ;get this char's top and height
NOHEIGHT
;-----------------------------------------------------------------------
;
; Horizontal clip only if FastFlag: (else stretch,outline,shadow,italic die)
;
; skip if hidden on left, string done if hidden on right.
;
; at this point: D1: srcLeft
; D2: dstRight
; D3: dstLeft
;
TST.B FastFlag(A6) ;ARE WE GOING FAST ?
BEQ.S HORIZOK ;NO, DON'T CLIP
CMP MINRECT+LEFT(A6),D3 ;IS DSTLEFT < MINRECT.LEFT ?
BGE.S LEFTOK ;NO, CONTINUE
CMP MINRECT+LEFT(A6),D2 ;IS DSTRIGHT <= MINRECT.LEFT ?
BLE SKIPCH ;YES, SKIP THIS CHAR
TRIMLFT MOVE MINRECT+LEFT(A6),D0 ;NO, GET MINRECT.LEFT
SUB D3,D0 ;DISCARD:=MINRECT.LEFT-DSTLEFT
ADD D0,D1 ;SRCLEFT:=SRCLEFT+DISCARD
ADD D0,D3 ;DSTLEFT:=DSTLEFT+DISCARD
CMP MINRECT+RIGHT(A6),D2 ;IS DSTRIGHT > MINRECT.RIGHT ?
BLE.S fixCharWidth ;NO, CONTINUE
BRA.S TRIMRT ;YES, TRIM RIGHT
LEFTOK CMP MINRECT+RIGHT(A6),D2 ;IS DSTRIGHT <= MINRECT.RIGHT ?
BLE.S HORIZOK ;YES, CONTINUE
CMP MINRECT+RIGHT(A6),D3 ;IS DSTLEFT >= MINRECT.RIGHT ?
BGE STRDONE ;YES, IGNORE REST OF STRING
TRIMRT MOVE MINRECT+RIGHT(A6),D2 ;NO, TRIM DSTRIGHT
fixCharWidth
MOVE D2,D0 ;char width has been trimmed left, right, or both
SUB D3,D0 ;so recalculate char width to draw
MOVE D0,charWidth(A6) ;and save this tidbit of info. for later
HORIZOK
;--------------------------------------------------------------
;
; Inputs to local block CharBlt:
;
; srcAddr(A6)
; srcRow(A6)
; bufStart(A6) = dstAddr
; bufRow(A6) = dstRow
; D1 = srcLeft
; D2 = dstRight relative to buffer, > dstLeft
; D3 = dstLeft relative to buffer
; TOPHT(A6) top and height
;
; CLOBBERS: D0,D1,D2,D3,D4,D5,D6,D7,A0,A2,A3,A4,A5
; PRESERVES: A1,A6,A7
;
;
; Setup shift count in D5 (relative shift between src and dst)
;
MOVEM D1-D3,maskBlts(A6)
MOVE.B textCopyMode(A6),orNotOK(A6) ;if copy or if mask mode, do bit moves instead of OR
ST notMaskPass(A6) ;use the bitDepth this pass
MOVE bitShift(A6),D0 ;get font scale factor
LSL D0,D1
LSL D0,D2
LSL D0,D3 ;scale up all three
MOVE BUFROW(A6),A3
MOVEM.L SRCROW(A6),A2/A4-A5 ;srcRow, srcAddr (src bitmap), bufStart (dst bitmap)
maskBlt
;
; Get char height into D7
;
MOVE.W #255,D7 ;GET -1 BYTE, CLEAR HI BYTE
ADD.B TOPHT+1(A6),D7 ;CALC HEIGHT-1 FOR DBRA LOOP
BMI SKIPCH ;OOPS HEIGHT WAS ZERO !
;
; Adjust srcPtr and dstPtr for charTop
;
MOVEQ #0,D0 ;get ready for byte
MOVE.B TOPHT(A6),D0 ;get char top
MOVE.L A2,D4 ;get srcRow in D-reg
MULU.L D0,D4 ;calc charTop * srcRow
ADD.L D4,A4 ;add to srcPtr
MOVE A3,D4 ;get dstRow in D-reg
MULU D0,D4 ;calc charTop * dstRow
ADD.L D4,A5 ;add to dstPtr
;
; figure alignment offset in source so that dest is long aligned
;
MOVEQ #$1F,D0 ;get a 5 bit mask, needed later
MOVE.L D1,D5
;
; Setup dstPtr in A5, address of leftmost dst word
;
MOVE D3,D6 ;GET A COPY OF DSTLEFT
ASR #5,D6 ;CONVERT FROM DOTS TO LONGS
MOVE D6,D4 ;copy dest left in longs for later
LSL #2,D6 ;quad for bytes
ADD D6,A5 ;move dest pointer to top of character
;
; figure number of longs to move
;
MOVE D2,D6 ;copy dstRight
ASR #5,D6
SUB D4,D6 ;if same, it fits into a single long
BEQ fitsInLong ;most 1 bit deep characters fit into a long
;——————————————————————————————————————————————————————————————————————————————————————
;
; Character spans long in destination, so it must be moved in pieces
; Registers used at this point:
; D0 = 5 bit mask D1 = src offset D2 = dstRight D3 = dstLeft
; D4 = -- D5 = src offset D6 = longs to move D7 = character height
; A0 = -- A1 = character ptr A2 = source row sz A3 = dest row size
; A4 = source row ptr A5 = dest row ptr A6 = locals A7 = stack
NEG D3 ;negate for bit counting
AND D0,D3 ;get bottom 5 bits of dstLeft
BNE.S @skip32
MOVEQ #32,D3 ;if 0, make it 32
@skip32
MOVE D6,D4 ;total longs (not including left part)
LSL #2,D4 ;make it a byte count
SUB D4,A2 ;adjust source bump count
SUB D4,A3 ;adjust dest. bump count
SUBQ #1,D6 ;number of whole longs, less left & right parts
ADD D3,D1 ;the right hand start
MOVEQ #32,D4
SUB.L D4,D1
;
; if not 1 bit font & mode is not srcOr, do moves instead
;
TST.B orNotOK(A6)
BNE.S DoMove
;
; OR words to the screen; set up right mask
;
AND D0,D2 ;get bottom 5 bits of dstRight
MOVEQ #1,D4
ROR.L #1,D4 ;set the high bit
ASR.L D2,D4 ;$80000000 to $FFFFFFFF
ASL.L #1,D4 ;$00000000 to $FFFFFFFE
MOVE D6,D2 ;initialize whole long count
MOVE D6,A0 ;save long count for later
MOVE.L D5,D6
ADD D3,D6
MOVEQ #32,D0
SUB.L D0,D6
;
; Slow loop only taken in wierd cases where dst wider than a long.
; Or the more common case that the font is more than 1 bit deep
;
MAIN1
BFEXTU (A4){D5:D3},D0 ;GET SRC FROM BITMAP
BRA.S @checkLong ;see if there is some number of longs to do
@main2
BFEXTU (A4){D6:0},D0 ;GET SRC FROM BITMAP
@checkLong
OR.L D0,(A5)+ ;OR SRC INTO DST
ADDQ #4,A4 ;BUMP SRCPTR RIGHT
DBRA D2,@main2 ;LOOP TILL LAST long
BFEXTU (A4){D1:0},D0 ;GET SRC FROM BITMAP
AND.L D4,D0
OR.L D0,(A5) ;OR SRC INTO DST
ADD.L A2,A4 ;BUMP TO NEXT ROW
ADD.L A3,A5 ;BUMP DST TO NEXT ROW
WIDE1 MOVE A0,D2 ;GET long count
DBRA D7,MAIN1 ;LOOP ALL ROWS
BRA decCount ;skip mask blt part
;
; Handle case of drawing into the offscreen bit map in color separately
;
DoMove
MOVE D2,D4 ;copy dstRight
AND D0,D4 ;get bottom 5 bits of dstRight
MOVE D6,longCount(A6) ;save # of whole longs
MOVE D6,D2 ;set up first loop count
MOVE.L bkCol(A6),D6 ;get a long full of the background color
BFEXTU D6{0:D3},D0 ;background color & left mask
MOVE.L D0,leftBack(A6) ;save for quick compare
BFEXTU D6{0:D4},D0 ;background color & right mask
MOVE.L D0,rightBack(A6) ;right mask color compare
MOVE bitDepth(A6),D0 ;bits in a single pixel
BFEXTU D6{0:D0},D0 ;get a single pixel of the background color
MOVE D0,bkCol1(A6) ;a single background color for quick compare
MOVEQ #32,D6 ;
SUB D3,D6 ;
MOVE.L D5,A0
ADD D3,A0
SUB #32,A0 ;set up center move offset
;
; Slow loop taken in cases where dst wider than a long (common for fonts more than 1 bit
; deep.) Need to move only the pixels that are not colored same as background.
;
MoveLeft
BFEXTU (A5){D6:D3},D0 ;get current background of destination
CMP.L leftBack(A6),D0 ;compare it against the background color AND leftMask
BNE.S leftOnePix ;if different, must move 1 pixel at a time
;
; Here the destination has only background color pixels, so the whole thing can be moved
;
BFEXTU (A4){D5:D3},D0 ;GET SRC FROM BITMAP
BFINS D0,(A5){D6:D3}
checkLong
EXG A0,D5 ;set up center move offset
midChkLong
ADDQ #4,A5 ;bump destination
BRA.S checkMLong ;see if there is some number of longs to do
MoveMid
MOVE.L bkCol(A6),D0
CMP.L (A5),D0 ;same as background color?
BNE.S midOnePix ;if different, move 1 at a time
BFEXTU (A4){D5:0},D0 ;GET SRC FROM BITMAP
MOVE.L D0,(A5)+ ;OR SRC INTO DST
checkMLong
ADDQ #4,A4 ;BUMP SRCPTR RIGHT
DBRA D2,MoveMid ;LOOP TILL LAST WORD
MoveRight
EXG A0,D5 ;set up left move offset
TST D4
BEQ.S nextRow
BFEXTU (A5){0:D4},D0 ;look at the destination
CMP.L rightBack(A6),D0 ;compare it against the background AND rightMask
BNE.S rightOnePix ;if different, must move 1 pixel at a time
;
; Here the destination has only background color pixels, so the whole thing can be moved
;
BFEXTU (A4){D1:D4},D0 ;get the right part of the character
BFINS D0,(A5){0:D4} ;move it to the destination
nextRow
ADD.L A2,A4 ;BUMP TO NEXT ROW
ADD.L A3,A5 ;BUMP DST TO NEXT ROW
offMove
MOVE longCount(A6),D2 ;GET long count
DBRA D7,MoveLeft ;LOOP ALL ROWS
BRA checkMask
;
; need to move only the pixels that are not colored same as background
;
leftOnePix
MOVEM.L D1/D3-D6,-(SP) ;save temporary registers
MOVEM bkCol1(A6),D0/D1 ;D0 = back color D1 = pixel width
@nxtPixel
BFEXTU (A4){D5:D1},D4 ;pick up a source pixel
CMP D4,D0 ;is it the same as the back color?
BEQ.S @skipInsert ;if so, dont add to destination
BFINS D4,(A5){D6:D1} ;if not, copy it to the destination
@skipInsert
ADD.L D1,D5 ;move to next source pixel
ADD D1,D6 ;move to next destination pixel
SUB D1,D3 ;decrement count
BGT.S @nxtPixel ;do until were done
MOVEM.L (SP)+,D1/D3-D6 ;restore bkCol, left & right widths, src & dest offsets
BRA.S checkLong
midOnePix
MOVEQ #32,D0 ;full long size in bits
MOVEM.L D1/D3-D6,-(SP) ;save temporary registers
MOVEQ #0,D6
MOVEM bkCol1(A6),D1/D3 ;D1 = back color D3 = pixel width
@nxtPixel
BFEXTU (A4){D5:D3},D4 ;pick up a source pixel
CMP D4,D1 ;is it the same as the back color?
BEQ.S @skipInsert ;if so, dont add to destination
BFINS D4,(A5){D6:D3} ;if not, copy it to the destination
@skipInsert
ADD.L D3,D5 ;move to next source pixel
ADD D3,D6 ;move to next destination pixel
SUB D3,D0 ;decrement count
BGT.S @nxtPixel ;do until were done
MOVEM.L (SP)+,D1/D3-D6 ;restore bkCol, left & right widths, src & dest offsets
BRA midChkLong
rightOnePix
MOVEM.L D1/D3-D6,-(SP) ;save temporary registers
MOVEQ #0,D6
MOVEM bkCol1(A6),D3/D5 ;D3 = back color D5 = pixel width
@nxtPixel
BFEXTU (A4){D1:D5},D0 ;pick up a source pixel
CMP D0,D3 ;is it the same as the back color?
BEQ.S @skipInsert ;if so, dont add to destination
BFINS D0,(A5){D6:D5} ;if not, copy it to the destination
@skipInsert
ADD.L D5,D1 ;move to next source pixel
ADD D5,D6 ;move to next destination pixel
SUB D5,D4 ;decrement count
BGT.S @nxtPixel ;do until were done
MOVEM.L (SP)+,D1/D3-D6 ;restore bkCol, left & right widths, src & dest offsets
BRA nextRow
;—————————————————————————————————————————————————————————————————————————————————————————————————
; Here, the character does not cross a long boundary, so faster loops are in order.
;
fitsInLong
MOVE charWidth(A6),D3 ;set up character width in bits
TST.B notMaskPass(A6) ;if dest is 1 bit, or this is the mask,
BEQ.S @skipMul ;then skip the mul scale
MOVE bitShift(A6),D4 ;set up bit depth
LSL D4,D3
@skipMul
TST.B orNotOK(A6) ;can we OR?
BNE.S offLong ;if not, bit extract/insert instead
;
; Optimize if dst fits in one long. (most 1 bit deep characters do)
;
LONG1
;
; OR words to the screen; set up right mask
MOVE D2,D1 ;copy dest right
NEG D1 ;figure not bits from left but bits from right
AND D0,D1 ;but only from 0 to 31
ADD D1,D3 ;add right mask to extract width
AND D0,D2 ;get bottom 5 bits of dstRight
MOVEQ #1,D4
ROR.L #1,D4 ;set the high bit
ASR.L D2,D4 ;$80000000 to $FFFFFFFF
ASL.L #1,D4 ;$00000000 to $FFFFFFFE
; if D5 + D3 < 32, use a faster set of code:
longLoop
BFEXTU (A4){D5:D3},D0 ;GET SRC DATA
AND.L D4,D0
OR.L D0,(A5) ;OR RESULT INTO DST
ADD.L A2,A4 ;BUMP SRCPTR TO NEXT ROW
ADD.L A3,A5 ;BUMP DSTPTR TO NEXT ROW
DBRA D7,longLoop ;LOOP ALL ROWS
BRA.S decCount
;
; Optimize if dst fits in one long. (most normal characters do)
;
offLong
MOVE D2,D6
AND.L D0,D6
SUB D3,D6
BFEXTU bkCol(A6){0:D3},D2
MOVEM.L D5/D6,leftOffset(A6) ;save source left, destination left offsets
MOVE D5,D0 ;source left offset less
ADD D3,D0 ; width of pixels to be moved
MOVE D0,longCount(A6) ; determines inner loop bounds
MOVE bitDepth(A6),D4 ;get source depth
BFEXTU D2{0:D4},D1 ;set up 1 pixel of background color
offLongLoop
; check to see if existing destination is untouched (equal to background) so that there is no
; concern about obliterating over a part of a character that kerns into this space.
BFEXTU (A5){D6:D3},D0 ;get the existing background
CMP.L D2,D0 ;is it background colored?
BEQ.S @okToBlast ;if so, it is safe to cut and fill
; inner loop taken if some kerning has occured so that bits can not be moved directly over bkground
@nxtPixel
BFEXTU (A4){D5:D4},D0
CMP D0,D1
BEQ.S @skipInsert
BFINS D0,(A5){D6:D4}
@skipInsert
ADD D4,D6
ADD D4,D5
CMP longCount(A6),D5 ;where to stop with the mask
BLT.S @nxtPixel
MOVEM.L leftOffset(A6),D5/D6 ;restore source left, destination left offsets
BRA.S @nextRow
; if no kerning, data can be moved without concern for what is already there.
@okToBlast
BFEXTU (A4){D5:D3},D0 ;GET SRC DATA
BFINS D0,(A5){D6:D3} ;move to destination
@nextRow
ADD.L A2,A4 ;BUMP SRCPTR TO NEXT ROW
ADD.L A3,A5 ;BUMP DSTPTR TO NEXT ROW
DBRA D7,offLongLoop ;LOOP ALL ROWS
;
; here, set up things for mask blt
;
checkMask
TST bitShift(A6) ;is source depth 1?
BEQ.S decCount ;if so, skip mask (just copy result to mask later)
TST.B maskFont(A6)
BEQ.S decCount
SF orNotOK(A6) ;next time through, can OR the mask
SF notMaskPass(A6) ;force bitDepth to 1 this pass
MOVEM maskBlts(A6),D1-D3/A3 ;set up words
MOVEM.L mSrcROW(A6),A2/A4/A5 ;set up longs
BRA maskBlt ;then blt mask
decCount
SUB #1,charsRemain(A6) ;decrement total character count
SUB #1,countCopy(A6) ;decrement partial draw character count
BGT NEXTCH ;LOOP IF MORE CHARS LEFT
;------
STRDONE MOVE.L SAVEA5(A6),A5 ;RESTORE GLOBAL PTR
TST.B FASTFLAG(A6) ;WERE WE GOING DIRECT TO SCREEN ?
BEQ.S @1 ;NO, CONTINUE
TST.B CRSRFLAG(A6) ;DRAWING TO SCREEN?
BEQ.S @0 ;=>IF NOT, JUST RETURN
move.b MMUsave(a6),d0 ;get previous MMU state in d0
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
@32bitNot
_SHOWCURSOR ;YES, RESTORE CURSOR
@0 BRA GOHOME ;AND QUIT
@1 MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A3 ;GET CURRENT GRAFPORT
MOVE.L FONTPTR(A0),A4 ;POINT TO FMOUTPUT
MOVE.L 2(A4),A2 ;GET FONT HANDLE
MOVE.L (A2),A2 ;DE-REFERENCE IT
MOVE CHARLOC(A6),D7 ;GET FINAL CHARLOC INT PART
SUB fKernMax(A2),D7 ;UN-ADJUST FROM KERNING, but not italic
;
; Make buffer bold if necessary:
;
CKBOLD CLR D2 ;GET READY FOR BYTE
MOVE.B 6(A4),D2 ;GET NUMBER OF OVERSTRIKES
BRA.S NXTBOLD ;BOLD BUFFER IF ANY
BOLDIT MOVE.L BUFSTART(A6),A0 ;POINT TO START OF BUFFER
MOVE BUFSIZE(A6),D1 ;HOW MANY LONGS IN BUF
SUB D0,D0 ;CLEAR X-BIT
BOLDLP MOVE.L (A0),D0 ;GET ONE LONG
ROXR.L #1,D0 ;ROTATE RIGHT WITH EXTEND
OR.L D0,(A0)+ ;OR BACK INTO BUFFER
DBRA D1,BOLDLP ;LOOP ENTIRE BUFFER
NXTBOLD DBRA D2,BOLDIT ;LOOP FOR EACH OVERSTRIKE
;
; Slant the buffer if necessary:
; Work from bottom of buffer up, shifting each row right.
; Work right to left to avoid clobbering src.
;
MOVEQ #0,D2 ;GET READY FOR BYTE
MOVE.B 7(A4),D2 ;DO WE NEED ITALIC ?
BEQ.S CHECKUL ;NO, CONTINUE
MOVE.L BUFEND(A6),A1 ;DSTPTR:=END OF BUFFER
MOVE BUFROW(A6),D3 ;GET BUFFER ROWBYTES
SUB D3,A1 ;BACK UP DSTPTR TO END OF 2ND ROW
LSR #2,D3 ;LONGCNT:=ROWBYTES DIV 4
SUB #1,D3 ;LONGCOUNT-1 FOR DBRA LOOP
MOVE HEIGHT(A6),D6 ;INIT ROW COUNTER
MOVEQ #0,D4 ;INIT OFFSET
BRA.S DOSLANT ;GO TO LOOP START
NXTROW ADD.L D2,D4 ;OFFSET:=OFFSET+ITALIC
MOVE.L D4,D5 ;COPY OFFSET
LSR.L #4,D5 ;DELTA := OFFSET SCALED BY 16
NEG.L D5 ;make negative for BFEXTU
MOVE.L A1,A0 ;SRCPTR:=DSTPTR
SUB #4,A0 ;POINT TO LAST LONG
MOVE D3,D1 ;INIT LOOP TO LONGCNT
NXTLONG BFEXTU (A0){D5:0},D0 ;GET A SHIFTED LONG OF SRC
SUB #4,A0 ;BUMP SRCPTR LEFT ONE LONG
MOVE.L D0,-(A1) ;STORE IN DST AND BUMP DSTPTR
DBRA D1,NXTLONG ;LOOP ALL LONG THIS ROW
DOSLANT DBRA D6,NXTROW ;LOOP FOR ALL ROWS IN BUFFER
;
; Underline characters in buffer if necessary.
;
; Use characters in buffer to hide parts of the underline.
;
CHECKUL TST.B 10(A4) ;IS ULTHICK ZERO ?
BEQ.S NOTUL ;YES, CONTINUE
MOVE.L BUFSTART(A6),A0 ;POINT TO BUFFER START
MOVE BUFROW(A6),D1 ;GET BYTES PER ROW OF BUFFER
MOVE locASCENT(A2),D0 ;GET ASCENT
MOVE locDESCENT(A2),D2 ;GET DESCENT
MULU D1,D0
ADD.L D0,A0 ;POINT TO BASELINE ROW
MOVE.L A0,A1
MOVE.L A0,A2
ADD D1,A1 ;POINT TO BASELINE+1
CMP #2,D2 ;IS DESCENT AT LEAST 2 ?
BLT.S NOTUL ;NO, SKIP UNDERLINE
BEQ.S ONLY2 ;ONLY USE 2 IF DESCENT=2
ADD D1,A2
ADD D1,A2 ;POINT TO BASELINE+2
ONLY2 SUB D1,SP ;ALLOCATE TEMP SCANBUF
MOVE.L A3,-(SP) ;SAVE GRAFPORT
LEA 4(SP),A3 ;POINT TO START OF TEMP
LSR #2,D1 ;CONVERT BYTES TO LONGS
SUB #1,D1 ;INIT DBRA LOOP COUNT
MOVE D1,D2 ;COPY LOOP COUNT
SUB D0,D0 ;CLEAR X-BIT
UL1 MOVE.L (A0)+,D0 ;GET FROM BASELINE
OR.L (A1)+,D0 ;OR WITH BASELINE+1
OR.L (A2)+,D0 ;OR WITH BASELINE+2
MOVE.L D0,(A3) ;PUT RESULT TO TEMP
ROXR.L #1,D0 ;SHIFT WITH CARRY
OR.L D0,(A3)+ ;OR INTO TEMP
DBRA D1,UL1 ;LOOP ALL LONGS IN ROW
MOVE.L A1,A0 ;COPY END PTR
SUB D0,D0 ;CLEAR X-BIT
UL2 MOVE.L -(A3),D0 ;GET FROM TEMP
ROXL.L #1,D0 ;SHIFT LEFT WITH CARRY
OR.L (A3),D0 ;OR WITH TEMP
NOT.L D0 ;INVERT
OR.L D0,-(A1) ;DRAW SOME UNDERLINE
DBRA D2,UL2 ;LOOP ALL LONGS IN ROW
MOVE.L (SP)+,A3 ;RESTORE GRAFPORT
;
; Setup fakeRgn, a dummy rectangular region
;
NOTUL MOVE #10,FAKERGN+RGNSIZE(A6) ;SIZE=10 BYTES FOR RECT RGN
MOVE.L DSTPIX+BOUNDS(A6),FAKERGN+RGNBBOX(A6)
MOVE.L DSTPIX+BOUNDS+4(A6),FAKERGN+RGNBBOX+4(A6)
LEA FAKERGN(A6),A0 ;GET ADDR OF FAKERGN
MOVE.L A0,FAKEPTR(A6) ;POINT FAKE MASTERPTR TO IT
;
; SET UP SOURCE BITMAP TO TRANSFER TO SCREEN
;
; SRCPIX := buffer
;
LEA SRCBITS(A6),A0 ;POINT TO source bits
MOVE.L A0,A1
MOVE.L BUFSTART(A6),(A0)+ ;SET UP BASEADDR
MOVE BUFROW(A6),(A0)+ ;SET UP ROWBYTES
MOVE TEXTRECT+TOP(A6),(A0)+ ;SET UP BOUNDS TOP
MOVE BUFLEFT(A6),(A0)+ ;SET UP BOUNDS LEFT
MOVE.L TEXTRECT+BOTRIGHT(A6),(A0)+ ;SET UP BOTTOM RIGHT
LEA SRCPIX(A6),A2
_BitsToPix
TST.B maskFont(A6)
BEQ.S @finishSrcPix
LEA maskBits(A6),A0 ;POINT TO mask bits
MOVE.L maskStart(A6),(A0)+ ;SET UP BASEADDR
MOVE mBufRow(A6),(A0)+ ;SET UP ROWBYTES
MOVE TEXTRECT+TOP(A6),(A0)+ ;SET UP BOUNDS TOP
MOVE BUFLEFT(A6),(A0)+ ;SET UP BOUNDS LEFT
MOVE.L TEXTRECT+BOTRIGHT(A6),(A0)+ ;SET UP BOTTOM RIGHT
@finishSrcPix
TST bitShift(A6) ;is the bit depth 1?
BEQ.S @skipColorJam
MOVE bitDepth(A6),srcPix+pixelSize(A6) ;set up bit depth
MOVE.L dstPix+pmTable(A6),srcPix+pmTable(A6) ;set up color table
@skipColorJam
;
; check if any shadowing:
;
CLR D3 ;GET READY FOR BYTE
MOVE.B 11(A4),D3 ;GET SHADOW COUNT
BEQ NOSHAD ;SKIP IF NO SHADOWING
;
; Shadowing will be used. Allocate buf2, 4 scans taller than BUF1.
; Clear out new 4 scanlines, and copy BUF1 into the rest.
;
MOVE BUFROW(A6),D0 ;GET 4 * NUMBER OF LONGS PER ROW
SUB #1,D0 ;INIT LOOP COUNTER
CLR.L -(SP) ;ALLOW ONE LONG OF SLOP
MOVE.L SP,BUF2END(A6) ;REMEMBER END OF BUF2
CLR2 CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG
DBRA D0,CLR2 ;CLEAR 4 SCANLINES WORTH
MOVE BUFSIZE(A6),D0 ;GET NUMBER OF LONGS IN BUF1
SUB #1,D0 ;INIT DBRA COUNTER
MOVE.L BUFEND(A6),A0 ;POINT TO END OF BUF1
COPYLP MOVE.L -(A0),-(SP) ;COPY FROM BUF1 TO NEW BUF2
DBRA D0,COPYLP ;COPY ALL OF BUF1
MOVE.L SP,BUF2START(A6) ;REMEMBER START OF BUF2
CLR.L -(SP) ;ALLOW ONE LONG OF SLOP
;
; Bold buf2 across to the right enough for shadow.
;
AND #3,D3 ;RESTRICT SHADOW COUNT TO 1..3
MOVE D3,D2 ;INIT BOLD COUNTER
ACROSS1 MOVE.L BUF2START(A6),A0 ;POINT TO START OF BUFFER2
MOVE BUFSIZE(A6),D1 ;INIT COUNT OF LONGS
SUB D0,D0 ;CLEAR X-BIT
ACROSS2 MOVE.L (A0),D0 ;GET A LONG FROM BUF2
ROXR.L #1,D0 ;SHIFT IT RIGHT EXTENDED
OR.L D0,(A0)+ ;OR IT BACK INTO BUFFER
DBRA D1,ACROSS2 ;LOOP FOR ALL LONGS
DBRA D2,ACROSS1 ;BOLD RIGHT 2,3, OR 4 TIMES
;
; Bold BUF2 down enough for shadow.
;
MOVE.L BUF2START(A6),A2 ;GET LIMIT POINTER
DOWN1 MOVE.L BUF2END(A6),A1 ;DSTPTR:=END OF BUF2
MOVE.L A1,A0
MOVE SRCBITS+ROWBYTES(A6),D2 ;GET SRC ROWBYTES
SUB D2,A0 ;SRCPTR:=END - 1 SCANLINE
DOWN2 MOVE.L -(A0),D0 ;GET A LONG FROM LINE ABOVE
OR.L D0,-(A1) ;OR INTO THIS LINE
CMP.L A2,A0 ;IS SRCPTR <= BUF2START ?
BGT.S DOWN2 ;NO, LOOP ALL LONGS
DBRA D3,DOWN1 ;BOLD DOWN 2,3, OR 4 TIMES
; XOR the plain text into the shadow buffer
MOVE bufSize(A6),D1 ;size of buffers in longs
MOVE.L bufStart(A6),A0 ;start of plain text
MOVE.L A2,A1 ;start of shadowed text
ADD D2,A1 ;bump down a line in the shadowed text
SUB D0,D0 ;clear x bit
@xor
MOVE.L (A0)+,D0 ;a line of plain text
ROXR.L #1,D0 ;shift it right, extended
EOR.L D0,(A1)+ ;combine with shadowed text
DBRA D1,@xor ;repeat for all longs
;
; Alter SRCBITS to use BUF2
;
MOVE.L A2,SRCBITS+BASEADDR(A6) ;SRC BASEADDR:=BUF2START
ADD #4,SRCBITS+BOUNDS+BOTTOM(A6) ;4 SCANS TALLER
;
; Push params and call StretchBits to transfer shadow to screen
;
MOVE.L TEXTRECT(A6),SRCRECT(A6) ;DSTRECT := SRCRECT
MOVE.L TEXTRECT+4(A6),SRCRECT+4(A6)
ADD #4,SRCRECT+BOTTOM(A6) ;PLUS 4 SCANS TALLER
MOVE.L SRCRECT(A6),DSTRECT(A6)
MOVE.L SRCRECT+4(A6),DSTRECT+4(A6)
LEA DSTRECT+TOP(A6),A0 ;OFFSET BY (-1,-1)
SUB #1,(A0)+ ;TOP
SUB #1,(A0)+ ;LEFT
SUB #1,(A0)+ ;BOTTOM
SUB #1,(A0)+ ;RIGHT
TST.B STRETCH(A6)
BEQ.S @1
PEA DSTRECT(A6)
PEA FROMRECT(A6)
PEA TORECT(A6)
_MAPRECT ;THEN MAPPED FOR SCALING
@1
PEA SRCBITS(A6) ;PUSH SRCPIX
MOVE.L maskBitsPtr(A6),-(SP) ;a mask?
BEQ.S @noMask
MOVE.L 4(SP),(SP) ;replace mask with copy of source
@noMask
PEA PORTBITS(A3) ;TRANSFER TO SCREEN
PEA SRCRECT(A6) ;PUSH SRCRECT = TEXTRECT
PEA SRCRECT(A6) ;maskRect same as source rect
PEA DSTRECT(A6) ;PUSH DSTRECT = TEXTR2
MOVE locMode(A6),-(SP) ;PUSH TEXTMODE
CLR.L -(SP) ;NO PATTERN FOR NOW
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN HANDLE
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN HANDLE
PEA FAKEPTR(A6) ;PUSH FAKE HANDLE
CLR -(SP) ;pass multicolor flag false
_StretchBits ;TRANSFER BUFFER TO SCREEN
; if old port, srcOr, draw center part in bic; if bic, in srcOr
; (This is done for compatibility with older applications like MacProject and MacDraw that
; expect to put text on an arbitrary background, relying on the center of the shadow to show.)
TST portBits+rowBytes(A3) ;a new port?
BMI.S GOHOME
MOVE locMode(A6),D0
CMP #srcOr,D0
BEQ.S @useBic
CMP #srcBic,D0
BNE.S GOHOME
@useBic
; restored altered srcBits
MOVE.L bufStart(A6),srcBits+baseAddr(A6)
SUB #4,srcBits+bounds+bottom(A6)
; adjust params for center portion StretchBits
CLR.L maskBitsPtr(A6) ;no mask
EOR #2,D0 ;change or to bic, bic to or
MOVE D0,locMode(A6) ;adjust textmode
;
; Push params and call StretchBits to transfer buffer to screen
;
NOSHAD
PEA SRCPIX(A6) ;PUSH SRCBITS
MOVE.L maskBitsPtr(A6),-(SP) ;may be 0 if no mask bitmap
PEA PORTBITS(A3) ;TRANSFER TO SCREEN
PEA TEXTRECT(A6) ;PUSH SRCRECT = TEXTRECT
PEA TEXTRECT(A6) ;maskRect same as source rect
PEA TEXTR2(A6) ;PUSH DSTRECT = TEXTR2
MOVE locMode(A6),-(SP) ;PUSH TEXTMODE
CLR.L -(SP) ;NO PATTERN FOR NOW
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN HANDLE
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN HANDLE
PEA FAKEPTR(A6) ;PUSH FAKE HANDLE
MOVE.B colorSource(A6),-(SP) ;pass multicolor flag true if source is multibit
_StretchBits ;TRANSFER BUFFER TO SCREEN
GOHOME
MOVE.L saveStk(A6),SP ;throw away the buffers
MOVE charsRemain(A6),D0
SUB countCopy(A6),D0
MOVE D0,charsRemain(A6) ;if iterative, this will be greater than zero
BGT secondHalf ;so there are more characters to draw
BSET #hiliteBit,HiliteMode ;reset hilite override, in case colormap was skipped
TST stackOffset(A6) ;was the stack aligned?
MOVEM.L (SP)+,D0-D7/A1-A4 ;RESTORE REGS
UNLK A6
BEQ.S @skipAlign
ADDQ #2,SP
@skipAlign
RTD #PARAMSIZE ;Return and pop the stack <1.6-11april89-CEL>
ENDPROC
;
; < ABOVE COPIED VERBATIM FROM THE ROM >
;
;---------------------------------------------------------------------------------------
ENDIF ; <6.0.5> <CEL>
;____________________________________________________________________________ dba <3.0>
; Menu manager patch
;
; The following patch fixes the head of InitProcMenu. The wrong version was
; rolled into the ROM, so we replace the head with this.
NewInitProcMenu proc export
ROMIMCommon equ $16D52 ; place to rejoin ROM in InitMenus
; the following code is copied out of the Menu Manager
move.l (sp)+,a0 ; get the return address
move.w (sp)+,d1 ; get the MBDF resource ID
move.l a0,-(sp) ; put return address back on the stack
jsrROM ROMIMCommon ; call InitMenus <4.0>
move.l MenuList,a0 ; get the menu list <4.0>
move.l (a0),a0 ; dereference the menu list <4.0>
move.w d1,mbResID(a0) ; store MBDF ID <4.0>
rts ; return to InitProcMenu caller <4.0>
endproc
; The following patch reinstates the WaitMouseUp in MenuSelect. It was removed as part
; of the tear-off menu stuff (in an attempt to support double-clicking in the menu bar),
; but that change was probably not a good idea, even for the tear-off menu case.
NewMenuSelect proc export
ROMContinueMenuSelect equ $171A2 ; place to rejoin ROM in MenuSelect
ROMDoneMenuSelect equ $17296 ; place to rejoin ROM in MenuSelect
; the following code is copied out of the Menu Manager
;-----------------------------------------------
; MenuSelect stack frame definitions
;-----------------------------------------------
STARTPT EQU 8 ; 1st parameter is 8, and is 4 bytes long
FUNCRESULT EQU 12 ; longword function result (menu,item)
ITEMRESULT EQU 14 ; item portion of funcResult
MENURECT EQU -8 ; rectangle (8 bytes)
MSavePort EQU MENURECT-4 ; saved grafPort
msLastMenu EQU MSavePort-2 ; how many menus are on the screen
DelayTicks EQU msLastMenu - 4 ; how long mouse in HItem
DragTicks EQU DelayTicks - 4 ; how long mouse moving towards HMenu
menuDelaySave EQU DragTicks - 1 ; store menuDelay from pRAM
menuDragSave EQU menuDelaySave - 1 ; store menuDrag from pRAM
lastFuncResult EQU menuDragSave - 2 ; funcResult last time thru MSLoop
lastItemResult EQU lastFuncResult - 2 ; itemResult last time thru MSLoop
firstMenuID EQU lastItemResult - 2 ; ID of REGULAR menu up
NewHMenuOffset EQU firstMenuID - 2 ; offset into MenuList of new HMenu
tRect1 EQU NewHMenuOffset - 8 ; temp rectangle
SelectFrame EQU tRect1 ; number of bytes to save
;-----------------------------------------------
link a6,#SelectFrame ; set up a stack frame
movem.l d2-d7/a2-a4,-(sp) ; save work registers
clr.w -(sp) ; push zero for this
_HiliteMenu ; make sure no menu is hilited
clr.l funcResult(a6) ; assume nothing will be selected
clr.l MenuDisable ; clear the low-memory location MenuDisable
clr.w -(sp) ; push zero for this
_WaitMouseUp ; is the mouse still down?
tst.b (sp)+ ; examine result
beq.s DoneMenuSelect ; if not still down, dont bother
jmpROM ROMContinueMenuSelect ; continue in ROM
DoneMenuSelect jmpROM ROMDoneMenuSelect ; continue in ROM
endproc
;____________________________________________________________________________ djw <3.6>
; Slot Manager pInitEntry patch
;
; Fixes a bug when calling _InsertSRTRec, inserting a ROM sRsrc with a valid
; refnum, pInitEntry is called. pInitEntry calls _sFindDevBase to calc a base
; addr to place in the DCE. The bug is _sFindDevBase is called with a bad
; sRsrc id. The fix is one line to restore the spId before calling
; _sFindDevBase.
;
pInitEntry Proc Export
With spBlock,srrBlock,SlotRsrcType
ROMpInitEntry Equ $00006904 ; addr to continue to in ROM
ROMpInitError Equ $0000691c ; addr of @Error label in ROM
ROMpInitDone Equ $00006920 ; addr of @Done label in ROM
ROMMapUnit Equ $00006930 ; addr of MapUnit routine in ROM
MOVEM.L D1/A2,-(SP) ; save regs
SUBA.W #SRSize,SP ; alloc size to read sRsrc sType field
MOVEA.L SP,A2 ; save A2 = ptr to buffer
; Fill in the fields of a new SRT entry
MOVE.B spSlot(A0),srrSlot(A1) ; slot number
MOVE.B spId(A0),srrId(A1) ; sRsrc id
MOVE.B spExtDev(A0),srrExtDev(A1) ; external device id
CLR.B srrHWDev(A1) ; clear hardware device id
MOVE.W spRefNum(A0),srrRefNum(A1) ; driver reference number
MOVE.W spIOReserved(A0),srrIOReserved(A1) ; IO reserved field (good for nothin?)
MOVE.L spsPointer(A0),srrsRsrcPtr(A1) ; set the ptr to the RAM or ROM sRsrc
CLR.L srrFlags(A1) ; clear flag field
MOVE.L spParamData(A0),D0 ; test state of enable/disable value
BEQ.S @ReadStuff ; zero - sRsrc is marked as enabled
BSET.B #srDisable,srrFlags+3(A1) ; set flag to indicate disabled
; Read the hardware sRsrc id
@ReadStuff MOVE.B #sRsrcHWDevId,spId(A0) ; get hardware id (if present)
_sReadByte ; no error if not present
BNE.S @Continue
MOVE.B spResult+3(A0),srrHWDev(A1) ; only a byte value
; Find and read the sRsrc type field <category><type><drvrSW><drveHW>
@Continue MOVE.B #sRsrcType,spId(A0) ; get ptr to sRsrc type
_sFindStruct
BNE.S @Error ; error - sRsrc type field is required
MOVE.L #SRSize,spSize(A0) ; set size to read
MOVE.L A2,spResult(A0) ; set buffer ptr
_sReadStruct
BNE.S @Error ; error - found but can't read ?
MOVE.L sCategory(A2),srrCategory(A1) ; copy <cat><type>
MOVE.L sDrvrSw(A2),srrDrvrSw(A1) ; copy <drvrSW><drvrHW>
; If there is a valid reference number, then find the DCE and calculate the dCtlDevBase
MOVEQ #0,D0 ; set a good return
MOVE.W spRefNum(A0),D1 ; get ref num
BEQ.S @Done ; no ref num - done
jsrROM ROMMapUnit ; return reg A2 = ptr to DCE
BNE.S @Error ; some error with ref num or DCE
; Read a 24 or 32 bit base address from the sResource
move.b srrId(a1),spId(a0) ; set spId of sRsrc to get base addr (the fix)
jmpROM ROMpInitEntry ; continue in ROM
; Jump points back into ROM
@Error jmpROM ROMpInitError ; jump to @Error label
@Done jmpROM ROMpInitDone ; jump to @Done label
EndProc
;____________________________________________________________________________ DAF <4.1>
; This patch really didn't get in until <5.1>
;
; SaveEntries Patch
;
; OK, I blew it on a patch roll-in from ROM78Fix into the Aurora ROM. In SaveEntries
; the a test was added for non-CLUT devices, but when I rolled it inline, I jumped
; back to the wrong place. This patch head patches the routine just like ROM78Fix
; so that it never hits the ROM routine if there is an error.
;
mySaveEntries PROC EXPORT
ROMSaveEntries EQU $3C920
MOVE.L ([theGDevice]),A0 ; get a pointer to the current device
CMP.W #CLUTType,GDType(A0) ; is it a clut device?
BNE.S SEDevErr ; nope, so report an error
JMPRom ROMSaveEntries ; OK, so execute normal saveEntries
SEDevErr
MOVE.W #cDevErr,QDErr ; post error code
RTD #12 ; and return
;____________________________________________________________________________
; SetEntries, dvb < 124 > 1991
; Mark bit 3 of QDSpare0 when the color environment changes, so pmgrexit
; only cleans up if bit was set for that layer.
mySetEntries PROC EXPORT
ROMSetEntries EQU $3C6C0
; Mark QDSpare that the color environment has changed, but only if
; QD exists
TST.B QDExist ; is QD around?
BNE.S @noQDE ; no, skip this next
MOVE.L (A5),A0
BSET #3,QDSpare0(A0) ; Tell PMgrExit to do color cleaning
@noQDE
JMPRom ROMSetEntries ; and on with our regularly scheduled program. < 124 >
;____________________________________________________________________________
; Script Manager patch to Pack6, fixes problem with pointer to unlocked
; handle in Transliterate. <4.3><08/21/89 pke>
; Also fixes another problem in LwrString, CharType, Transliterate, FindWord:
; These routines need to have the Script Manager IntlForce flag cleared
; before calling IUGetIntl (this flag must be saved beforehand and restored
; afterward). This ensures that the itl2 tables used by these routines apply
; to the current script. <4.5><08/21/89 pke>
; Only do the second fix for Scripts604 OR (SysVers > $604) <4.7><08/21/89 pke>
;
; This patch is not installed for A/UX, since A/UX doesn't support the Script
; Manager.
;
IF doScriptMgrPack6Fix AND (NOT installScriptMgrPtch39) THEN ; <42><50>
ptchPack6 PROC Export
fromROMLwrString EQU $0C0B2
fromROMCharType EQU $1D986
fromROMFindWord EQU $1DBE0
fromROMTranslit EQU $1DB34
toROMTranslit EQU $1DB3A
ROMPack6 EQU $262B2
tlRecord record {a6link},decr
result ds.w 1 ; function result.
tlArgs equ *-8 ; size of arguments.
srcHandle ds.l 1 ; srcHandle.
dstHandle ds.l 1 ; dstHandle.
target ds.w 1 ; target.
srcMask ds.l 1 ; srcMask.
selector ds.l 1 ; selector
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
tlLocals equ * ; size of local variables.
endr
cmp.w #iuGetIntl,4(sp) ; is it an IUGetIntl call?
bne.s @NoPatch ; skip if not (optimization)
CmpRA fromROMLwrString,(sp)
beq.s @PatchOther
CmpRA fromROMCharType,(sp)
beq.s @PatchOther
CmpRA fromROMFindWord,(sp)
beq.s @PatchOther
CmpRA fromROMTranslit,(sp)
beq.s @PatchTrans ; Translit is special - 2 bugs
@NoPatch
JmpROM ROMPack6 ; nothing interesting to do
@PatchTrans
; We get here if we came from the _IUGetIntl in Transliterate (IUGetIntl is a
; macro that pushes a selector and then does a _Pack6 trap). A few instructions
; before the _IUgetIntl, we had handles in a1 and a2 which were then dereferenced
; into the same registers. We want to postpone this dereferencing till after
; _Pack6. Fortunately, the original handles are still available in Transliterate's
; a6 frame, so we can get them after the Pack6 call, dereference them again, and
; stuff them where they belong. We also need to clear the IntlForce flag around
; Pack6 if it is set.
WITH tlRecord, SMgrRecord
addq #4,sp ; kill old return address
GetSMgrCore a0 ; get pointer to SMgrRecord
tst.b smgrIntlForce(a0) ; check IntlForce flag
bne.s @fixFlag ; if set, go fix it
JsrROM ROMPack6
bra.s @doDeref
@fixFlag
clr.b smgrIntlForce(a0) ; now force it to 0
JsrROM ROMPack6
GetSMgrCore a0 ; get pointer to SMgrRecord
st smgrIntlForce(a0) ; restore IntlForce
@doDeref
; The next two lines are what follow the _IUGetIntl in the ROM Transliterate
move.l (sp)+,a4 ;
movem.l (sp)+,a1/d1-d2 ;
; Now we expect to have pointers in a1 and a2, so set them up again (this is
; the fix) and jump back into ROM:
move.l srcHandle(a6),a1 ; get source handle.
move.l dstHandle(a6),a2 ; get destination handle.
move.l (a1),a1 ; get source pointer.
move.l (a2),a2 ; get destination pointer.
JmpROM toROMTranslit
ENDWITH
@PatchOther
; We get here if we came from the _IUGetIntl in LwrString, CharType, or
; FindWord. If IntlForce is currently zero, we just JMP to the old Pack6.
; Otherwise, we copy part of the stack in order to save the return address,
; then JSR to Pack6, then fix up the stack.
WITH SMgrRecord
GetSMgrCore a0 ; get pointer to SMgrRecord
tst.b smgrIntlForce(a0) ; check IntlForce flag
beq.s @NoPatch ; if already 0, nothing to do
clr.b smgrIntlForce(a0) ; now force it to 0
; At this point the stack has 12 bytes that are significant for Pack6:
; 8(sp).L = space for returned handle
; 6(sp).W = argument, specifies which itlx
; 4(sp).W = Pack6 routine selector = #iuGetIntl
; 0(sp).L = return address
; We now copy the selector, argument, and return space below the return address.
; This sets up the stack correctly for the JsrROM (which will add a new return
; address) while preserving our original return address.
clr.l -(sp) ; new place for returned handle
move.l 8(sp),-(sp) ; copy selector and arguments
; Now this piece of stack has changed as follows:
; 16(sp).L = old space for returned handle
; 14(sp).W = old copy of argument (unnecessary)
; 12(sp).W = old copy of selector (unnecessary)
; 8(sp).L = old return address
; 4(sp).L = new space for returned handle
; 2(sp).W = new copy of argument, specifies which itlx
; 0(sp).W = new copy of Pack6 routine selector = #iuGetIntl
; We are now set up to call Pack6:
JsrROM ROMPack6
; The last stack picture:
; 12(sp).L = old space for returned handle
; 10(sp).W = nothing useful
; 8(sp).W = nothing useful
; 4(sp).L = old return address
; 0(sp).L = returned handle
; We need to copy the returned handle to where it should go, clean up the stack,
; set IntlForce, and return.
move.l (sp)+,8(sp) ; copy returned handle to its place
move.l (sp)+,a1 ; get return address
addq #4,sp ; finish cleaning up stack
GetSMgrCore a0 ; get pointer to SMgrRecord
st smgrIntlForce(a0) ; restore IntlForce
; Now we just have the returned handle on the stack (see, no picture).
jmp (a1) ; go home (I'm about to).
ENDWITH
ENDPROC
ENDIF ; <42>
;============================================================================ pke <4.6>
; Patch UprString,RelString,CmpString to reintroduce the bug in which "`" is
; converted to uppercase as "a". This is necessary to prevent HFS problems,
; since existing disk catalogs use the old, buggy sorting. All we need to do
; is patch them up to the point where they access the UpperTab table, which
; does not have the necessary bug in ROM.
;
; A/UX uses the ROM versions of these routines, so we can install them for
; A/UX.
;
PROC
EXPORT NewUprString,NewCmpString,NewRelString
ROMUprStringAfterEntString equ $0C10C
ROMRelStringAfterEntString equ $0C136
ROMEntStringAfterLEAUpperTab equ $0C196
;______________________________________________________________________
;
; Routine: UprString
; Arguments: D0.W (input) -- string length
; A0.L (input) -- pointer to string to canonize
; Opcode bit 10 -- 0 - map to upper case; 1 - case sensitive
; Opcode bit 9 -- 0 - diacritical sensitive; 1 - strip diacrits
; All registers are preserved.
; Function: UprString is a utility routine which, according to
; a pair of input booleans, strips diacritical marks
; and/or maps all characters to upper case.
;
;______________________________________________________________________
NewUprString
BSR EntString ; changed
jmpRom ROMUprStringAfterEntString
;______________________________________________________________________
;
; Routine: CmpString, RelString
; Arguments: D0.L (input) -- high-order word = string 0 length
; low-order word = string 1 length
; A0.L (input) -- pointer to string 0
; A1.L (input) -- pointer to string 1
; D0.W (output) --
; CmpString -- result code = 0, 1 for equal, unequal.
; RelString -- result code = -1, 0, 1 according as string 0
; is <, =, > than string 1, respectively.
; Opcode bit 10 -- 0 - map to upper case; 1 - case sensitive
; Opcode bit 9 -- 0 - diacritical sensitive; 1 - strip diacrits
; Pascal register conventions are observed.
;
; Calling Sequence for Pascal strings:
; LEA str0,A0
; LEA str1,A1
; MOVEQ #0,D0
; MOVE.B (A0)+,D0
; SWAP D0
; MOVE.B (A1)+,D0
; _CmpString
;
; Function: CmpString is a utility routine to compare two strings for
; equality. The strings are pointed to by A0 and A1
; on entry; the result is returned in D0.
; Two booleans determine the flavor of the compare:
; Marks --
; if set, all diacritical marks are ignored.
; Case --
; if set, all characters are mapped to upper case.
;______________________________________________________________________
;
; To expedite CmpString, test for length differences first. If they're the same,
; use the absolute value of RelString's return.
;
NewCmpString
MOVE.W D0,D2 ; str 1 length
SWAP D0 ; str 0 length
CMP.W D0,D2
BNE.S CSQuickNE
SWAP D0 ; realign for fresh start in RelString
BSR.S NewRelString ; count on CCR from last D0 store <4.6>
BPL.S @1
NEG.L D0 ; -1 ---> 1
@1
RTS
CSQuickNE
MOVEQ #1,D0 ; must differ since lengths do
RTS
;
; Register usage:
; D0 = shorter string length = loop index
; D1 = trap opcode, with embedded booleans
; D2 = string 0 input buffer
; D3 = string 1 input buffer
; D4 = -1, 0, 1 according to string lengths
;
; A0 = string 0 pointer
; A1 = string 1 pointer
;
; Output:
; D0 = -1, 0, 1
; CCR reflects D0
; D1-D2/A0-A1 trash
;
NewRelString
BSR.S EntString
jmpROM ROMRelStringAfterEntString ; <4.6>
;______________________________________________________________________
;
; Utility EntString saves regs D3-D4/A2-A3, sets up opword for quick
; test in Canonizer, and primes A2 with UpperTab and A3 with CmpTab.
; D2 is cleared for use by Canonizer.
;
; Utility ExtString cleans up and returns, leaving CCR. It is jumped to...
;______________________________________________________________________
EntString
MOVE.L (SP)+,D2 ; return address
MOVEM.L D2-D4/A2-A3,-(SP) ; return on top
LEA UpperTab,A2
jmpROM ROMEntStringAfterLEAUpperTab ; <4.6>
;
; Handy macro allows for ease in building big, regular tables.
; ASSEMBLER WON'T ALLOW EIGHTH ARGUMENT ON SAME LINE!!!!!!!!!!!!!!
;
MACRO
crow
DC.B (&Syslst[1]),( &Syslst[1]+1),( &Syslst[1]+2),( &Syslst[1]+3),( &Syslst[1]+4),( &Syslst[1]+5),( &Syslst[1]+6)
DC.B (&Syslst[1]+7)
ENDM
MACRO
dcrow
crow &Syslst[1]
crow &Syslst[1]+8
ENDM
;_________________________________________________________________________________________________________
;
; <4.6> <08/21/89 dba/pke>
;
; Note the $61 at the beginning of the lower-case letters. In Feb. 89 for the ROMs, Peter E. fixed the
; upper casing of the "`" (backquote) character. Previously, it would turn into "a" (ASCII $61).
; Unfortunately, to our dismay, all of our old HFS disks require that this bug be perpetuated forever,
; at least for the ordering of HFS names in the B-Tree, which use RelString. We also realized that
; others may be using the string traps to order internal data structure. Because of all of this, we
; are reintroducing the bug. The uppercase version of backquote is hereby declared to be lower-case a.
;
UpperTab
; Special chars, punctuation, digits, upper-case letters.
dcrow $00
dcrow $10
dcrow $20
dcrow $30
dcrow $40
dcrow $50
; Lower-case letters and some symbols.
DC.B $61,( 'A'),( 'B'),( 'C'),( 'D'),( 'E'),( 'F'),( 'G') ; fixed ` <02/29/89 pke> unfixed <4.6>
crow $48
crow $50
DC.B ('X'),( 'Y'),( 'Z'), $7B, $7C, $7D, $7E, $7F
; Accented characters.
crow $80
DC.B $CB, $89, $80, $CC, $81, $82, $83, $8F
DC.B $90, $91, $92, $93, $94, $95, $84, $97
DC.B $98, $99, $85, $CD, $9C, $9D, $9E, $86
; Symbols and upper-case AE and O-slash
dcrow $A0
; Symbols and ae, o-slash
crow $B0
DC.B $B8, $B9, $BA, $BB, $BC, $BD, $AE, $AF
; Symbols, upper A-acute, A-tilde, O-tilde, OE, and oe
crow $C0
DC.B $C8, $C9, $CA, $CB, $CC, $CD, $CE, $CE
; Symbols and undefineds. y-umlaut cannot map up.
dcrow $D0
dcrow $E0
dcrow $F0
; End of UpperTab
;_________________________________________________________________________________________________________
ENDPROC
IF doScriptMgrStr2DatFix AND (NOT installScriptMgrPtch39) THEN ; <7.8><42><50>
;============================================================================ pke <7.8>
; Patch Script Manager routines InitDateCache and String2Date for bug fixes
; needed by HyperCard.
; ----------------------------------------------------------------------------
proc
export NewInitDateCache,NewString2Date
ROMValidLong equ $1EE60 ; <7.8>
ROMBlock2String equ $1EEA0 ; <7.8>
ROMMatchString equ $1EF20 ; <7.8>
; in InitDateCache ($1EF80):
ROMAfter2ndJSRCopyArray equ $1F0E8 ; <7.8>
ROMExit equ $1F160 ; <7.8>
; in/after String2Date ($1F190):
ROMAfterDBNE equ $1F2D6 ; <7.8>
ROMDTComExit equ $1F426 ; <7.8>
ROMFixValue equ $1F46E ; <7.8>
ROMDateTimeEntry equ $1F47E ; <7.8>
WhiteSpace EQU 1 ; token number for white space
AlphaToken EQU 4 ; token number for string
NumericToken EQU 5 ; token number for number
AltNumericToken equ $B ; alternate token type for numbers
NonAlphNumToken EQU 16 ; token numbers starting here correspond to non-alpha numeric tokens
MaxTokens EQU 32 ; number of tokens for which there is space
omdy EQU 0 ; date order constants
odmy EQU 1
oymd EQU 2
Str15 EQU 16 ; length of string[15]
DayMonthLen equ 15 ; length of days and months
NumDays EQU 7 ; length of various arrays
NumMonths EQU 12
DayList EQU NumDays*Str15
MonthList EQU NumMonths*Str15
NumStrBytes EQU 300
Cache RECORD 0
version ds.w 1
CurrentDate DS LongDateRec
BaseDate DS LongDateRec
theDays DS.B DayList ; <7.8>
theMonths DS.B MonthList ; <7.8>
theEveStr DS.B Str15
theMornStr DS.B Str15
the24hrStr DS.B Str15
theTimeSep DS.W 1
theDateSep DS.W 1
theDateOrder DS.b 1
longDateOrder ds.b 1
theAbbrLen DS.W 1
TBlock DS tokenBlock
CacheSize equ *
theTimeStrings equ theEveStr
ENDR
; ----------------------------------------------------------------------------
; function InitDateCache(theCache: CachePtr): OSErr;
;
; InitDateCache will initialize the items in the DateCacheRecord pointed to by theCache^
; and set the initialized item to true
;
; The bug fixes are in the CopyArray subroutine <7.8>.
; ----------------------------------------------------------------------------
idcSaveRegs REG A2-A4/D3/d4
InitCacheRec RECORD {A6link},decr
Result DS.W 1 ; offset to function result (integer)
paramBegin EQU *
theCache DS.L 1 ; pointer to the cache record
selector ds.l 1 ; added for resource
paramEnd EQU *
return DS.L 1
A6link DS.L 1
theTokens DS.B 2*TokenRec.tokenRecSize
Intl0 DS.L 1 ; handle, not pointer
Intl1 DS.L 1 ; handle, not pointer
altSpace ds.w 1 ; use top byte
aLongDate ds LongDateTime ;
localsize EQU *
ENDR
WITH InitCacheRec,LongDateField
NewInitDateCache
LINK A6,#localsize ; Establish local frame and variables
MOVEM.L idcSaveRegs,-(SP) ; saved used registers
CLR.W Result(A6) ; clear function result
MOVE.L theCache(A6),A2 ; cache addr
move.b #' ',altSpace(a6) ; assume no alt space
sub.l #6,sp ; reserve returns
_IntlScript ; get the script
move.w #smScriptRight,-(sp) ; get flag
_GetScript ; get value
tst.l (sp)+ ; got it?
beq.s @NoAltSpace ; no
move.b #' '+$80,altSpace(a6) ; use alt space.
@NoAltSpace
WITH Cache
lea aLongDate(a6),a0 ; @temp
clr.l (a0)+ ; no high
move.l Time,(a0)+ ; low = current
pea aLongDate(a6) ; extended
pea CurrentDate(A2) ; get current date from system global time and convert to date
_LongSecs2Date
lea aLongDate(a6),a0 ; @temp
clr.l (a0)+ ; no high
clr.l (a0)+ ; low = current
pea aLongDate(a6) ; extended
pea BaseDate(A2) ; get base date and convert to date
_LongSecs2Date
; IUGetIntl(0): Handle
CLR.L -(SP)
CLR.W -(SP)
_IUGetIntl
MOVE.L (SP)+,Intl0(A6)
move.w ResErr,d0 ; did intl0 load in all right
BEQ.S GotIntl0Ok ; if so, go on
MOVE.W d0,Result(A6)
BRA Exit
GotIntl0Ok
; IUGetIntl(1): Handle
CLR.L -(SP)
MOVE.W #1,-(SP)
_IUGetIntl
MOVE.L (SP)+,Intl1(A6)
TST.W ResErr ; did intl0 load in all right
BEQ.S GetSeparators ; if so, go on
MOVE.W ResErr,Result(A6)
BRA Exit
GetSeparators
MOVE.L Intl0(A6),A3
; Lock itl0 across Block2String calls (which can now move memory)
move.l a3,a0
_MoveHHi
move.l a3,a0
_HLock
MOVE.L (A3),A3 ; now a3 is pointer to itl0
; Block2String(eveStr,theEveStr,4,true)
LEA eveStr(A3),A0 ; get international 0 record for evening string
LEA theEveStr(A2),A1
MOVEQ #4,D0
MOVE.B #1,D1
move.b altSpace(a6),d2 ; pass alt string
JsrROM ROMBlock2String ; convert packed array of char into string <7.8>
; with no leading spaces
; Block2String(mornStr,theMornStr,4,true)
LEA mornStr(A3),A0 ; get international 0 record for morning string
LEA theMornStr(A2),A1
MOVEQ #4,D0
MOVE.B #1,D1
move.b altSpace(a6),d2 ; pass alt string
JsrROM ROMBlock2String ; convert packed array of char into string <7.8>
; with no leading spaces
; Block2String(time1Stuff,the24hrStr,1,true)
LEA timeSuff(A3),A0 ; get international 0 record for 24 hour string
LEA the24hrStr(A2),A1
MOVEQ #1,D0
MOVE.B #1,D1
move.b altSpace(a6),d2 ; pass alt string
JsrROM ROMBlock2String ; convert packed array of char into string <7.8>
; with no leading spaces
MOVE.B timeSep(A3),theTimeSep(A2) ; get time separator from intl 0
MOVE.B dateOrder(A3),theDateOrder(A2)
MOVE.B dateSep(A3),(theTimeSep + 1)(A2)
; Now unlock itl0
move.l Intl0(A6),a0
_HUnlock
MOVE.L Intl1(A6),A3
; Lock itl1 across Copy Array calls; it calls Block2String, which can now move memory
move.l a3,a0
_MoveHHi
move.l a3,a0
_HLock
MOVE.L (A3),A3 ; now a3 is pointer to itl1
; Get the long date order and convert
; false => dmy, true => mdy; otherwise fancy stuff
move.l #omdy,d1 ; assume false
clr.w d0 ; wordize
move.b lngDateFmt(a3),d0 ; get long format
beq.s @GotLong ; done
move.l #odmy,d1 ; assume true
cmp.b #$FF,d0 ; true?
beq.s @GotLong ; yes, got it
; if we are looking at the long date, only the day and year are important,
; since the dayOfWeek and month are both strings. Walk through the format until
; we find either one or the other
@LongFmtLoop
move.b d0,d2 ; get bottom half-nybble
and.b #3,d2 ; got it
cmp.b #longDay,d2 ; day?
beq.s @GotLong ; yes, return #odmy
cmp.b #longYear,d2 ; year?
beq.s @LongYearFirst ; go for it
lsr.b #2,d0 ; strip bottom
bne.s @LongFmtLoop ; repeat until done
@LongYearFirst
move.l #oymd,d1 ; year first (also if none found)
@GotLong
move.b d1,longDateOrder(a2) ; set it
; continue
MOVE.B abbrLen(A3),theAbbrLen(A2) ; get abbrLen
; changed order for more convenience in the later routine
lea months(a3),a4 ; source of days
LEA theMonths(A2),a1 ; destination names of the day and months
MOVE.L #(numMonths - 1),D3 ; load day and months from intl 1 rec into space
jsr CopyArray ; copy days
lea days(a3),a4 ; source of days
LEA theDays(A2),a1 ; destination names of the day and months
MOVE.L #(numDays - 1),D3 ; load day and months from intl 1 rec into space
jsr CopyArray ; copy days
; Now continue with ROM code
JmpROM ROMAfter2ndJSRCopyArray ; <7.8>
Exit
JmpROM ROMExit ; <7.8>
; little subroutine for code savings
; a4 is source pointer
; a1 is dest pointer
; d3 is byte length
CopyArray
move.l a1,d4 ; dest ptr
@LOOP MOVE.L A4,A0 ; move string from intl 1 rec <7.8>
MOVE.L d4,A1 ; into local frame
moveq #0,d0 ; Block2String wants a long! <7.8>
MOVE.B (A0)+,D0 ; with length from first byte of string
MOVEQ #1,D1 ; with no local frame
move.b altSpace(a6),d2 ; pass alt string
JsrROM ROMBlock2String ; search <7.8>
ADD.L #Str15,d4 ; get next string to transfer
ADD.w #Str15,A4 ; into next string in local frame <7.8>
DBRA D3,@LOOP
rts
ENDWITH ; Cache
ENDWITH
; ----------------------------------------------------------------------------
;function String2Date( textPtr: Ptr;
; textLen: longint;
; theCache: DateCachePtr;
; var lengthUsed: longint;
; var DateTime: LongDateRec): Integer;
;
; String2Date will look for a date in the text given it according to the international
; resource format. Using the Tokenizer routine it will look for a dayofWeek (which will
; be a string), a month (either a string or a number) and a day and year (both numbers).
; If the month is a number, order is decided by the ShortDate format in INTL 0; otherwise
; String2Date uses a table. Note if only two numbers are found they are assumed to be day
; and month. If one number is found it is assumed to be a date. Missing fields are
; filled in by the current date and time
;
; Register Usage
;
; A2 - Work register D3 - loop control register
; A3 - Work register D4 - MonthFound
; A4 - Cache Addr D5 - ResultNum
; D6 - AbbrLen
; D7 - NumDelimsFound
;
; The bug fixes are: … <7.8>
; ----------------------------------------------------------------------------
s2dSaveRegs REG D3-D7/A2-a4 ; removed a5
DateFrame RECORD {A6link},decr
Result DS.W 1 ; offset to function result (integer)
paramBegin EQU *
textPtr DS.L 1 ; offset to Date2Time's paramters
textLen DS.L 1
theCache DS.L 1 ; @DateCacheRecord
RestofText DS.L 1 ; @Longint
DateTime DS.L 1 ; @LongDateRec
selector ds.l 1 ; added for resource
paramEnd EQU *
return DS.L 1
A6link DS.L 1
theTokens DS.B MaxTokens*TokenRec.tokenRecSize ; storage for tokens found by tokenizer
theDate DS LongDateRec ; date time rec
results DS.W 3 ; three temporary results
myDateOrder DS.W 1
DayFound DS.W 1
lastItemSep DS.W 1
lastToken DS.W 1
lastTokenAddr DS.L 1
lastExToken DS.W 1
dummyLongDate ds LongDateTime
stringStorage DS.B NumStrBytes
localsize EQU *
ENDR
WITH DateFrame
With Cache,LongDateField
NewString2Date
LINK A6,#localsize ; Establish local frame and variables
MOVEM.L s2dSaveRegs,-(SP) ; saved used registers
JsrROM ROMDateTimeEntry ; initialize & call _IntlTokenize
; Note that DateTimeEntry also does the following:
; 1. moves theCache(a6) into a4
; 2. moves TheTokens(a6) into a3
; 3. sets result(a6)
; 4. clears D7,D6; sets D5.L = -1
; 5. after IntlTokenize, sets D3= number of tokens - 1
tst.w result(a6) ; entry failed?
bne DTComExit ; bail if so
; specific stuff
MOVEQ #-1,D4 ; initialize MonthFound to -1
CLR.W DayFound(A6)
LEA CurrentDate(A4),A1 ; source
LEA theDate(A6),A0 ;
MOVE.L (A1)+,(A0)+ ; era, year
MOVE.L (A1)+,(A0)+ ; month, day
MOVE.L (A1)+,(A0)+ ; hour, minute
move.w (a1)+,(a0)+ ; second
CLR.W (A0)+ ; clear out dayOfWeek. Will either be set by user or be set
; in the course of the validity check of the date
MOVE.B theAbbrLen(A4),D6
WITH TokenRec
@TokenLoop
MOVE.W theToken(A3),D1 ; get token code from TokenRec record at (A3)
CMP.W #NonAlphNumToken,D1 ; is it a separator
BGE.S @FoundSeparator
SUB.W #WhiteSpace,D1 ; was it a white space?
BEQ @TokenLoopEnd ; ignore
SUBQ.W #(AlphaToken - WhiteSpace),D1 ; is it an alpha token?
beq.s @FoundAlpha
SUBQ.W #(NumericToken - AlphaToken),D1 ; is it a number token?
BEQ.S @NumberToken
SUBQ.W #(AltNumericToken - NumericToken),D1 ; is it a number token?
BEQ.S @NumberToken ;
BRA @TokenLoopEnd ; ignore any other characters
@FoundSeparator
TST.B D7 ; possible separator. Has a separator already been found
BEQ.S @OneDelimFound ; no, so no error yet
OR.W #TooManySeps,Result(A6) ; yes, so now we have too many separators
@OneDelimFound
ADDQ.B #1,D7 ; record separator found
TST.w D5 ; is this after the first number loaded? (.w) <1/5/88med>
BMI @TokenLoopEnd ; if we have not reached a number yet go on
BNE.S @CheckDateSep ; if we loaded in a number then check consistency
MOVE.W D1,lastItemSep(A6) ; otherwise update lastItemSep with just found separator
BRA @TokenLoopEnd
@CheckDateSep
CMP.W lastItemSep(A6),D1 ; are they consistent
BEQ @TokenLoopEnd ; if yes, than go on
OR.W #SepNotIntlSep+sepNotConsistent,Result(A6) ; record warning
BRA @TokenLoopEnd
@NumberToken
; check for numbers separated only by white space
tst.w d7 ; got a separator?
bne.s @1 ; yes
tst.w d5 ; first number?
blt.s @1 ; yes, skip
bne.s @0 ; have 1 number
move.w #WhiteSpace,lastItemSep(A6) ; set separator
bra.s @1 ; continue
@0
cmp.w #WhiteSpace,lastItemSep(a6) ; same?
beq.s @1 ; yes, continue
or.w #SepNotIntlSep+sepNotConsistent,Result(A6) ; record warning
@1
; end of white space check
CLR.L D7 ; clear out past separators
CMP.W #2,D5 ; make sure that results array is not full
BGE @ExtrnsToken ; if full, record warning and search <7.8>
; for final string (remove .s)
; ValidLong(position,textLength): longint
MOVE.L stringPosition(A3),A0
JsrROM ROMValidLong ; get number in text at TokenRec.position <7.8>
BMI DTComExit
JsrROM ROMFixValue ; <7.8>
bra @TokenRecognized ; get next token (remove .s) <7.8>
@FoundAlpha
CLR.L D7 ; clear out past separators
; UprString(newTextPtr,AbbrLen) ; and make it uppercase for case insensitive search
MOVE.L stringPosition(A3),A2
ADDQ.L #1,A2
MOVE.L A2,A0
MOVE.L length(A3),D0 ; use real length
_UpperText ; _LwrString with uppercase function <39><45>
TST.W D4
BPL.S @SearchForDay ; <7.8>
; MatchString(newTextPtr,AbbrLen,@months,15,12): integer
CLR.W -(SP) ; attempt to find a day/month string which matches alpha token
MOVE.L A2,-(SP)
MOVE.W length+2(a3),-(SP) ; push length as integer
MOVE.W D6,-(SP) ; push minlen as integer
PEA theDays(A4) ; <7.8>
MOVE.W #DayMonthLen,-(SP)
MOVE.W #NumMonths+NumDays,-(SP) ; check for both at once
JsrROM ROMMatchString ; <7.8>
MOVE.W (SP)+,D2 ; save in D2
BLE.S @ExtrnsToken ; checking both
; decide between days and months
sub.w #NumDays,d2 ; months?
ble.s @CheckForDay ; no, do days
; got a month
CMP.W #2,D5 ; is result array already full?
BGE.S @ExtrnsToken ; if so, then its not a needed token
ADDQ.W #1,D5 ; is in range, result is not full and string
MOVE.W D5,D1 ; did not match as a day
ADD.W D1,D1 ; double index for integer array
LEA results(A6),A1 ; ResultNum:= ResultNum + 1
MOVE.W D2,(A1,D1.W) ; results[ResultNum]:= match result
MOVE.W D5,D4 ; MonthFound:= resultNum
BRA.S @TokenRecognized
; if day not found yet, we need to see if current string matches a day <7.8>
@SearchForDay
TST.B DayFound(a6) ; have we found one yet?
BNE.S @ExtrnsToken ; day already found, record warning
CLR.W -(SP) ; attempt to find a day string which matches alpha token
MOVE.L A2,-(SP)
MOVE.W length+2(a3),-(SP) ; push length as integer
MOVE.W D6,-(SP) ; push minlen as integer
PEA theDays(A4)
MOVE.W #DayMonthLen,-(SP)
MOVE.W #NumDays,-(SP) ; just check days this time
JsrROM ROMMatchString ; <7.8>
MOVE.W (SP)+,D2 ; save in D2
BLE.S @ExtrnsToken ; checking both
BRA.S @HaveDay
@CheckForDay
TST.B DayFound(a6) ; off of a6!
BNE.S @ExtrnsToken ; day already found, record warning
add.w #NumDays,d2 ; restore days <7.8>
@HaveDay ; <7.8>
ST DayFound(A6) ; record that day was found <7.8>
MOVE.W D2,theDate.dayOfWeek(A6) ; otherwise, load dayOfWeek into date time record
TST.W D5 ; is dayOfWeek between two numbers (.w)
BMI.S @NoWarning ; if no number has been found yet, go on
OR.W #fieldOrderNotIntl,Result(A6) ; record warning
@NoWarning
BRA.S @TokenRecognized
@ExtrnsToken
TST.W lastExToken(A6) ; is this the first extraneous token found?
BPL.S @TokenLoopEnd ; no, go on
MOVE.W D3,lastExToken(A6) ; a string which we don't recognize has been found
BRA.S @TokenLoopEnd ; record warning and go on
@TokenRecognized
MOVE.W D3,lastToken(A6)
MOVE.L A3,lastTokenAddr(A6) ; save loop and token addr for later use
@TokenLoopEnd
ADD.L #tokenRecSize,A3 ; add size of TokenRec record to A3 to get next token
CMP.W #2,D5 ; if the result array full (.w)
SGE D0
AND.B DayFound(A6),D0 ; and dayofWeek string been found
DBNE D3,@TokenLoop ; then stop loop, otherwise go until all tokens are looked at
JmpROM ROMAfterDBNE
DTComExit
JmpROM ROMDTComExit
endproc
ENDIF
IF doScriptMgrRstKCHRFix AND (NOT installScriptMgrPtch39) THEN ; <8.0><42><50>
;============================================================================ pke <8.0>
; Tail patch on _GetIndADB to fix bug in Script Manager ResetKCHR routine
; called by SwapKybd: it clears ADB keyboard driver dead state as a word,
; should be a long.
; ----------------------------------------------------------------------------
proc
export ptchGetIndADB
ROMAfterGetIndADB equ $1E048
ROMAfterClrDeadKey equ $1E058
ROM@1dbra equ $1E064
ptchGetIndADB
CmpRA ROMAfterGetIndADB,OSTrapReturnAddressDepth(sp) ; From ResetKCHR?
bne.s @0 ; if not, just continue with trap
lea ptchResetKCHR,a1 ; a1 is not a param for GetIndADB
move.l a1,OSTrapReturnAddressDepth(sp) ; so trap returns to patch, not ROM
@0 BackToTrap oldGetIndADB ; now get on with the trap
; When we reach the patch below, we are in ResetKCHR just after the _GetIndADB
rkRecord record {a6link},decr
rkArgs equ *-8 ; size of arguments.
pointer ds.l 1 ; new KCHR pointer.
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
adb ds ADBDataBlock ; ADB data structure.
oldKeyboard ds.l 1 ; old keyboard pointer
rkLocals equ * ; size of local variables.
endr
ptchResetKCHR
with rkRecord
cmp.b #kybdADBAddr,adb.origADBAddr(a6) ; is it a keyboard?
bne.s @1 ; no -> skip it.
move.l adb.dbDataAreaAddr(a6),a0 ; load data area pointer.
clr.l KybdDriverData.deadKey(a0) ; clear dead state - long! <8.0>
JmpROM ROMAfterClrDeadKey ; <8.0>
@1 JmpROM ROM@1dbra ; <8.0>
endwith
endproc
ENDIF
IF doScriptMgrLwrString2 AND (NOT installScriptMgrPtch27) THEN ; <8.5><50>
;============================================================================ pke <8.5>
; Patch LwrString to handle 2-byte chars via Transliterate.
; ----------------------------------------------------------------------------
; routine: LwrString
; input: a0 textPtr
; d0.w length
; d1.w trap word; the following bits are significant in 7.0 only:
; Opcode bits
; 10 9 Function
; -- -- --------
; 0 0 convert to lower-case
; 0 1 strip diacritics
; 1 0 convert to upper-case
; 1 1 convert to upper-case and strip diacritics
; output: d0.w error
; function: Change text pointed to by a0 according to opcode bits. Before 7.0, we
; just assume that these bits are 0 and act accordingly.
; ----------------------------------------------------------------------------
proc
export ptchLwrString
lwrTrFrame record {a6link},decr
return ds.l 1 ; return address
a6link ds.l 1 ; link pointer
sourcePtr ds.l 1 ; orig source ptr
sourceLen ds.l 1 ; orig source len
sourceHndl ds.l 1 ; new handle with copy of source
destHndl ds.l 1 ; new handle for transliterate result
errCode ds.w 1 ; err code to be returned in d0
lwrTrLocals equ * ; size of locals
endr
; ----------------------------------------------------------------------------
; NOTE: For 2-byte scripts, we need to call Transliterate. So, the first thing to
; do is figure out what script we're in. We also test for length <= 0 (tests >32K).
; ----------------------------------------------------------------------------
ptchLwrString
ext.l d0 ; as fast as tst.w and we need ext.l later
ble lwrRTS ; if bad length, quit
movem.l a0/d0/d1,-(sp) ; save important registers
subq.l #2,sp ; make room for return
_FontScript ; find script of port
move.w (sp)+,d2 ; pop it into d2
movem.l (sp)+,a0/d0/d1 ; restore important registers
; ----------------------------------------------------------------------------
; Here we make use of the fact that a word redraw flag of 1 (or anything >0)
; indicates a 2-byte script.
; ----------------------------------------------------------------------------
with SMgrRecord,ScriptRecord
lsl.w #2,d2 ; make script code a long offset
move.l IntlSpec,a1 ; get SMgrRecord pointer
move.l smgrEntry(a1,d2.w),d2 ; get ScriptRecord pointer
beq lwrRTS ; if nil (script not installed), do nothing
move.l d2,a1
tst.b scriptEnabled(a1) ; is script enabled?
beq lwrRTS ; if not, do nothing
tst.b scriptRedraw(a1) ; is it a 2-byte script?
ble not2Byte ; if not, go use normal LwrString
endwith
; ----------------------------------------------------------------------------
; OK, we need to set up for Transliterate: set up source & dest handles
; ----------------------------------------------------------------------------
with lwrTrFrame
link a6,#lwrTrLocals ; create local storage
move.l a0,sourcePtr(a6) ; save source ptr
move.l d0,sourceLen(a6) ; save length
_PtrToHand ; make new handle containing copy of text
move.w d0,errCode(a6) ; save err code
bne.s lwrTrUnlk ; if error in PtrToHand, quit
move.l a0,sourceHndl(a6) ; save new source handle
move.l sourceLen(a6),d0 ; get length again
_NewHandle ; make new handle with random contents
move.w d0,errCode(a6) ; save err code
bne.s lwrTrDisp1Hndl ; if error in NewHandle, quit
; ----------------------------------------------------------------------------
; Now do Transliterate and check result: dest length should equal source length
; ----------------------------------------------------------------------------
move.l a0,destHndl(a6) ; save new dest handle
subq.l #2,sp ; space for Transliterate error code
move.l sourceHndl(a6),-(sp) ; push source handle
move.l a0,-(sp) ; push dest handle (still in a0)
move.w #smTransLower+smTransAscii,-(sp) ; lower-case conversion, target=Roman
move.l #smMaskAscii,-(sp) ; convert Roman only
_Transliterate
move.w (sp)+,errCode(a6) ; save error code
bne.s lwrTrDisp2Hndl ; if error in Transliterate, quit
move.l destHndl(a6),a0 ; now check result…
_GetHandleSize
move.w d0,errCode(a6) ; save err code
tst.l d0 ; .l, because the result is really a long
blt.s lwrTrDisp2Hndl ; if error in GetHandleSize, quit
move.w #-1,errCode(a6) ; assume len err; need a better err code!
cmp.l sourceLen(a6),d0 ; should be same as source len
bne.s lwrTrDisp2Hndl ; if not, set err and bail
; ----------------------------------------------------------------------------
; Copy result (destHndl) to original text buffer (sourcePtr).
; NOTE: For large text blocks, _BlockMove might be faster than this loop.
; ----------------------------------------------------------------------------
move.l destHndl(a6),a0 ; get dest handle and…
move.l (a0),a0 ; deref it to get source ptr for this copy
move.l sourcePtr(a6),a1 ; old source ptr is dest for this copy
move.l sourceLen(a6),d0 ; length for copy (we know it is >= 1)
subq.l #1,d0 ; set up for dbra
@1 move.b (a0)+,(a1)+ ; copy a byte
dbra d0,@1 ; loop till done
clr.w errCode(a6) ; no errors!
; ----------------------------------------------------------------------------
; Exits - need to dispose of handles we created
; ----------------------------------------------------------------------------
lwrTrDisp2Hndl
move.l destHndl(a6),a0 ;
_DisposHandle ;
lwrTrDisp1Hndl
move.l sourceHndl(a6),a0 ;
_DisposHandle ;
lwrTrUnlk
move.w errCode(a6),d0 ; set err code
unlk a6 ;
rts
endwith
lwrRTS
clr.w d0
rts
; ----------------------------------------------------------------------------
; This is not a 2-byte script, just use old LwrString.
; ----------------------------------------------------------------------------
not2Byte
BackToTrap oldLwrString ;
endproc
ENDIF
;_______________________________________________________________________
; <7.1><8.7><41><81><123><125><126><128><135><137> Async Serial Driver Patch
; <4><5>
;
; Start of patch code for fix of bugs in the serial driver
; introduced into the aurora ROM (and hence the F19 overpatch ROM) by the
; port arbitration code, which was accidently included in those ROMS.
;
; The patch is installed in a patch vector for the async driver.
; Note the 'simple' come-from patching mechanism has been really hosed by the
; addition of the pic chip code; now we have to include all that code in the
; patch. Something to watch for when fixing the ROM driver.
;
; Needed to include all code which jumped TO the ExtSts interrupt handler.
;
; Traps patched: -- The AsyncVector, which is in the middle of the OS ToolTable
; is patched, Trap number = $A0BE
; -- all the PIC driver headers patched. <41>
;
;
; HISTORY:
; <7.1> 10/2/89 patch ExtAIntHnd and ExtBIntHnd
; <8.7> check SCCIOPFlag now instead of PRAM to determine which driver to load.
; changed sense of bypass bit to agree with new ROM definition.
; <41> fixed <8.7> to use the patch macros. Also added in patch for the
; IOPSerialDriver for the prime code. As a result, had to patch ALL
; the IOP driver headers. yuck.
; <81> added VM support for the SerSetBuf control call.
; <123> added nike printer support:
; patched control call 16 in bypass driver to use bit 6 for setting
; external/internal clocking modes.
; Patched both bypass and IOP code to add status call to return version.
; Patched InitSCC routine in bypass driver to use this RAM-based table so
; that clocking mode is now variable instead of hard-wired to internal only.
; -- set clock divide to 1 instead of 16 for external clocking
; -- clear HWHS enable since we can't clock and handshake on same line
; Patched bypass mode driver to set bit 3 of AsyncErr if break rcvd.
; <125> We patch all the bypass driver headers (iop headers are already patched)
; so that we can put a signature word before each header that we can use
; to identify ourselves as the Apple async serial driver. We do this
; right now so that that our linked patch on Open (in Serialpatches.a) will
; not stomp the version number of some third party driver that sticks them-
; selves into our spot in the unit table. I think this idea will come in
; handy later as well.
; I think i'll use the signature word 'wong'.
; <126> fixed a bug in EXTSTS interrupt handler for port A. Because of the BAP
; stuff, AInDCE no longer has a valid ptr the .Ain driver's DCE. We solve
; the problem the same way we did in the port B code, by getting the DCE
; ptr straight from the unit table.
; <127> Fixed a bug in the External Status interrupt handler. On
; port A we crashed on receiving a break if a read was pending
; because we weren't getting the .Ain DCE ptr properly. Now we get
; the DCE ptr directly from the Unit table, just like for port B.
; <129> Fixed bug in external clock stuff that was causing us to disable
; internal clocking on both ports if we were trying to do external
; clocking on just one. So Nike would print but Tabasco would just
; sit there. The fix was to set clocking params at each time we go
; thru InitSCC, rather than just once during the external clocking
; control call. This way even tho the ports share the InitSCCTable,
; we set the Table properly by keying off of the value in CtlOptions
; variable, which they don't share.
; <135> Status call 9 and $8000 return fixed version equate instead of
; what's in the DCE. Fixed SerSetBuff (control call 9) to not sign
; extend the buffer count.
; <137> Fixed bug in IOP code that caused SerSetBuff to fail for zero size
; buffer. Wasn't clearing upper word of count passed to UnholdMemory.
; <4> patched Rx and SCx interrupt handlers to help thruput on Apollo and TIM LC
; <5> patched SCx interrupt handler to fix the StyleWriter bug. On faster
; machines we are able to send out a byte fast enough after the TBE bit
; in RR0 gets set that the byte gets written before the TBE interrupt
; is generated. Instead of just not generating the interrupt, the SCC goes
; ahead and generates it, but changes the interrupt source code to read
; 'no interrupt' instead of 'TBE'. This 'no interrupt' code is identical
; to the 'Special Condition on port B' code, which was the source of our
; problem. Fix is to just exit SCIntHnd if no special condition bits are
; set.
;
;_______________________________________________________________________
AsyncPatch proc
export SerialPatch
;
; equates
;
PortAVars EQU SerialVars ; serial chan A variables and buffer
SerialVers EQU 5 ; current version 3/91 <135>
;
; Bypass driver var offsets
;
OutDCE EQU 0 ;(4) long DCE pointer for output driver
SCCOffset EQU 4 ;(2) word of SCC offset . . .
InBufPtr EQU 6 ;(4) pointer to local input buffer
BufSize EQU 10 ;(2) size of local input buffer
BufLow EQU 12 ;(2) low buf byte count to send XOn
BufHigh EQU 14 ;(2) bytes from end of buffer to send XOff
SWHS EQU 16 ;(1) software handshake enable
HWHS EQU 17 ;(1) hardware handshake enable
XONChar EQU 18 ;(1) input char which continues output (SWHS)
XOFFChar EQU 19 ;(1) input char which stops output
Options EQU 20 ;(1) bit 4 = abort on parity error
; bit 5 = abort on overrun
; bit 6 = abort on framing error
PostOptions EQU 21 ;(1) bit 7=1 enables posting break changes
; bit 5=1 enables posting handshake changes
InSWHS EQU 22 ;(1) input XOn/XOff flow control enable
InHWHS EQU 23 ;(1) input RTS (DTR) flow ctl enb <14Oct85>
AsyncErr EQU 24 ;(1) error indications (cumulative)
SoftOR EQU 0 ; bit 0 = soft overrun
; bit 4 = parity error
; bit 5 = overrun error
; bit 6 = framing error
FlowOff EQU 25 ;(1) $80 = input flow shut off by XOff, $40 by DTR
ReadCmd EQU 26 ;(1) FF = read command pending
WriteCmd EQU 27 ;(1) FF = write command pending
CTSFlag EQU 28 ;(1) FF = CTS asserted
XOFFlag EQU 29 ;(1) FF = XOFF pending
LastWR5 EQU 30 ;(1) WR5 value with last DTR state <14Oct85>
DTRNegVal EQU 31 ;(1) WR5 value used to negate DTR <14Oct85>
SCCReset EQU 32 ;(1) WR9 value for reset
StopBits EQU 33 ;(1) stop bits/parity option (WR4 value)
WR1AVal EQU 34 ;(1) first WR1 value to write
WR3AVal EQU 35 ;(1) first WR3 value to write
WR5AVal EQU 36 ;(1) first WR5 value to write
BaudLoCnst EQU 37 ;(2) 2 byte baud rate constant (WR12-13)
BaudHiCnst EQU 38
RcvrBits EQU 39 ;(1) 1 byte receiver bits/char (WR3 value)
XmitBits EQU 40 ;(1) 1 byte xmitter bits/char (WR5 value)
WReqPin EQU 41 ;(1) w/req pin state (WR1 value)
lastSetup EQU 42 ;(2) last SCC init values . . .
BufIndex EQU 44 ;(2) index into local buffer (insert)
BufOutdex EQU 46 ;(2) index into local buffer (remove)
LocalBuf EQU 48 ;(64) local buffer for input chars
LclBufSize EQU 64 ; default input buffer size = 64 bytes
HSCount EQU 112 ;(2) count of CTS pulses in VBL time (clk detect) <14Oct85>
LastTime EQU 114 ;(4) ticks time of last CTS pulse (clk detect) <14Oct85>
SendXOnff EQU 118 ;(1) flag to xmit logic to send XOn/XOff <14Oct85>
CharMask EQU 119 ;(1) $1F,$3F,$7F, or $FF mask for input chars <14Oct85>
PEChar EQU 120 ;(1) char to change incoming parity errors to <14Oct85>
AltChar EQU 121 ;(1) char to change incoming PEChars to <14Oct85>
InSWHS1 EQU 122 ;(1) saved InSWHS state <14Oct85>
CtlOptions EQU 123 ;(1) bits 0-6=0 (reserved). bit 7=1 to leave <14Oct85>
; DTR state unchanged at close.
SaveExInt EQU 124 ;(4) saved Ext int vector <14Oct85>
SaveTxInt EQU 128 ;(4) saved TxD int vector <14Oct85>
SaveRxInt EQU 132 ;(4) saved RxD int vector <14Oct85>
SaveSxInt EQU 136 ;(4) saved Special Rx int vector <14Oct85>
InDCE EQU 140
VarSize EQU 144 ; output driver storage size
LclVarSize EQU 144 ; output driver storage size
;
; PIC driver var offsets and misc equ
;
PICOpenFlag EQU 0 ; marks if driver is open
OpenMsgPB EQU 22
EventMsgPB EQU 106
OpenMsg EQU 270
PICInBufPtr EQU 368 ; ptr to current input buffer
PICBufSize EQU 372 ; size of current input buffer
PICBufIndex EQU 374 ; index for putting bytes into input buffer
PICBufOutdex EQU 376 ; index for taking bytes out of input buffer
PICLocalBuf EQU 378 ; ptr to driver's local buffer
; General Equates for message fields
Results Equ 0 ;(1) Message return code
OpCode Equ Results+1 ;(1) Some messages slots are shared
CloseOpCode Equ 2; Close
;____________________________________________________________________
;
; ROM address offsets
;
;____________________________________________________________________
; bypass driver ROM entrypoint addresses <125>
;port A
ROM_AInEntryOpen EQU $6ac2a
ROM_AInEntryClose EQU $6af82
ROM_AInEntryPrime EQU $6b2a8
ROM_AOutEntryOpen EQU $6acf2
ROM_AOutEntryClose EQU $6af0e
ROM_AOutEntryPrime EQU $6b1ec
ROM_AEntryControl EQU $6b002
ROM_AEntryStatus EQU $6afac
;Port B
ROM_BInEntryOpen EQU $6ac30
ROM_BInEntryClose EQU $6af82
ROM_BInEntryPrime EQU $6b2ae
ROM_BOutEntryOpen EQU $6ad22
ROM_BOutEntryClose EQU $6af22
ROM_BOutEntryPrime EQU $6b1f2
ROM_BEntryControl EQU $6b008
ROM_BEntryStatus EQU $6afb2
; Open patch equates for bypass driver
fromAOutOpen EQU $0006B542 ; at end of drvr, in IOP stuff (ChkConfig called there)
fromBOutOpen EQU $0006B550
fromAInOpen EQU $0006B55E
fromBInOpen EQU $0006B56C
fromControl EQU $6B01a
fromClose EQU $6af3e
fromStatus EQU $6afc4
fromInitSCC EQU $6aeb8
backToAOutOpen EQU $0006AD12 ; returning to finish up Open routines in ROM
backToBOutOpen EQU $0006AD44
PlugInDrvr EQU $0006B594 ; plug header addr into DCE and continue
backToInOpen EQU $0006ac34 ; finish In Open routines in ROM
ROM_PollDtain EQU $0006B372 ; rom routines addresses we must push on the stack
ROM_SCAIntHnd EQU $0006B466
ROM_SCBIntHnd EQU $0006B45C
ROM_RAIntHnd EQU $0006B3B0
ROM_RBIntHnd EQU $0006B3A6
ROM_TAIntHnd EQU $0006B276
ROM_TBIntHnd EQU $0006B26C
ROM_AsyncAIn EQU $0006abca ; ROM header addresses for byass drivers
ROM_AsyncAOut EQU $0006ABE2
ROM_AsyncBIn EQU $0006abfa
ROM_AsyncBOut EQU $0006AC12
; Control patch equates for bypass driver
backToControl EQU $6b02c ; for fixing control calls
ROM_CtlGood EQU $6b062
ROM_CtlExit EQU $6b064
FinishCall9 EQU $6b0c0
InitSCC EQU $6aea8
; Close patch equates for bypass driver
SyncOutput EQU $6af86
InitSCC1 EQU $6aeae
backToClose EQU $6af64
ResetData EQU $6aefe
ResetLth EQU $10
; InitSCC patch equates for bypass driver
backToInitSCC EQU $6aeb8
initData EQU $6ae74
; Status patch equates for bypass driver
backToStatus EQU $6afde
; Interrupt Handler equates for the bypass driver
; External/Status interrupt handler equates
ToContOut1 EQU $0006B29C ; return to finish up interrupt routines in ROM
ToRdReqDone EQU $0006B4B6
ToCtlSet EQU $0006B14C
; Rx interrupt handler equates
ROM_PutInOurBuf EQU $6b400
ROM_toStash EQU $6b312
ROM_GoodFinish EQU $6b234
; SC interrupt handler equates
ROM_abortReq EQU $6b4ae
; PIC driver ROM entrypoint addresses
; (note some are here for documentation purposes only)
ROM_PICAInOpen EQU $0006B60A ; .AIn
ROM_PICAInPrime EQU $0006BA7C
ROM_PICAInControl EQU $0006B870
ROM_PICAInStatus EQU $0006B7B8
ROM_PICAInClose EQU $0006B7AC
ROM_PICAOutOpen EQU $0006B618 ; .Aout
ROM_PICAOutPrime EQU $0006B9DC
ROM_PICAOutControl EQU $0006B868
ROM_PICAOutStatus EQU $0006B7B0
ROM_PICAOutClose EQU $0006B72C
ROM_PICBInOpen EQU $0006B60A ; .BIn
ROM_PICBInPrime EQU $0006BA82
ROM_PICBInControl EQU $0006B876
ROM_PICBInStatus EQU $0006B7BE
ROM_PICBInClose EQU $0006B7AC
ROM_PICBOutOpen EQU $0006B648 ; .BOut
ROM_PICBOutPrime EQU $0006B9DC
ROM_PICBOutControl EQU $0006B868
ROM_PICBOutStatus EQU $0006B7B0
ROM_PICBoutClose EQU $0006B72C
; equates for PIC patches
IntoChkAConfig EQU $0006AC8A ; for the Open patches
IntoChkBConfig EQU $0006AC4E
ROM_BufferShuffle EQU $0006BD1E ; for the Input Prime patches
backToPICControl EQU $6b898 ; for Control patches
backToPICKillIO EQU $6b884
ROM_PICCtlExit EQU $6b8d4
backToPICClose EQU $6b764 ; for Close patch
StatusErrExit EQU $6b85a ; for Status patch
BacktoPICStatus EQU $6b7d8
PICStatusOkExit EQU $6b858
;_______________________________________;
;
; IOP Driver Headers
;
;_______________________________________;
DC.b 'wong' ; our personal signature
PICAsyncAIn
DC.W $4D00 ; read, control, status, lock
DC.W 0,0 ; not an ornament
DC.W 0 ; no menu
DC.W PICAInOpen-PICAsyncAIn ; Initialization routine
DC.W PICAInPrime-PICAsyncAIn ; input Prime routine
DC.W PICAInControl-PICAsyncAIn ; shared Control routine
DC.W PICAInStatus-PICAsyncAIn ; shared Status routine
DC.W PICAInClose-PICAsyncAIn ; Close routine
DC.B 4 ; channel A input driver
DC.B '.AIn '
DC.b 'wong' ; our personal signature
PICAsyncAOut
DC.W $4E00 ; write, control, status, lock
DC.W 0,0 ; not an ornament
DC.W 0 ; no menu
DC.W PICAOutOpen-PICAsyncAOut ; Initialization routine
DC.W PICAOutPrime-PICAsyncAOut ; output Prime routine
DC.W PICAOutControl-PICAsyncAOut ; Control routine
DC.W PICAOutStatus-PICAsyncAOut ; Status routine
DC.W PICAOutClose-PICAsyncAOut ; Close routine
DC.B 5 ; channel A output driver
DC.B '.AOut'
DC.b 'wong' ; our personal signature
PICAsyncBIn
DC.W $4D00 ; read, control, status, lock
DC.W 0,0 ; not an ornament
DC.W 0 ; no menu
DC.W PICBInOpen-PICAsyncBIn ; Initialization routine
DC.W PICBInPrime-PICAsyncBIn ; input Prime routine
DC.W PICBInControl-PICAsyncBIn ; Control routine
DC.W PICBInStatus-PICAsyncBIn ; Status routine
DC.W PICBInClose-PICAsyncBIn ; Close routine
DC.B 4 ; channel B input driver
DC.B '.BIn '
DC.b 'wong' ; our personal signature
PICAsyncBOut
DC.W $4E00 ; write, control, status, lock
DC.W 0,0 ; not an ornament
DC.W 0 ; no menu
DC.W PICBOutOpen-PICAsyncBOut ; Initialization routine
DC.W PICBOutPrime-PICAsyncBOut ; output Prime routine
DC.W PICBOutControl-PICAsyncBOut ; Control routine
DC.W PICBOutStatus-PICAsyncBOut ; Status routine
DC.W PICBOutClose-PICAsyncBOut ; Close routine
DC.B 5 ; channel B output driver
DC.B '.BOut'
;_______________________________________;
;
; IOP Driver Stubs -- routines that are
; just along for the ride, and jump back
; directly to ROM
;
;_______________________________________;
PICAInClose jmpROM ROM_PICAInClose ; input Close routine
;__________________________________
PICAOutPrime jmpROM ROM_PICAOutPrime ; output Prime routine
;__________________________________
PICBInClose jmpROM ROM_PICBInClose ; input Close routine
;__________________________________
PICBOutPrime jmpROM ROM_PICBoutPrime ; output Prime routine
;__________________________________
;
; Patched PIC Routines
;
;__________________________________
; Open Routines
; We patch out the Open routines because if we jump into ROM Open
; we'll stuff the ROM PIC driver into the DCE instead of this patched one.
; So instead we load up the value we want in the DCE ourselves, and
; then jump into the open patch for the Bypass driver below.
; Also note for the Open calls, that because of the way PICChkXXXDrvr
; is written in ROM, we must the SAME instruction exactly 4 bytes
; into our Open patch as is in ROM. Else PICChkXXXDrvr would try
; to jump back to some weird place it wasn't meant to.
PICAInOpen jmp @10 ; need 4 bytes here to correspond to ROM driver
jmpROM ROM_PICAInOpen ; finish up in ROM
@10 leaROM ROM_AsyncAIn,a2 ; load up the inputs
lea PICAsyncAIn,a3
toAOpenPatch leaROM IntoChkAConfig,a0 ; continue on in ChkAConfig
moveq #4,d1 ; use hyigh 4 bits in SPConfig
moveq #8,d2 ; and PortAUse
bra.w OpnFx1 ; go to our byPass driver patch
PICAOutOpen jmp @10 ; need 4 bytes here to correspond to ROM driver
jmpROM ROM_PICAOutOpen ; finish up in ROM
@10 leaROM ROM_AsyncAOut,a2 ; load up the inputs
lea PICAsyncAOut,a3
bra.s toAOpenPatch
PICBInOpen jmp @10 ; need 4 bytes here to correspond to ROM driver
jmpROM ROM_PICBInOpen ; finish up in ROM
@10 leaROM ROM_AsyncBIn,a2 ; load up the inputs
lea PICAsyncBIn,a3
toBOpenPatch leaROM IntoChkBConfig,a0 ; continue on in ChkBConfig
bra.w OpnFx1
PICBOutOpen jmp @10 ; need 4 bytes here to correspond to ROM driver
jmpROM ROM_PICBOutOpen ; finish up in ROM
@10 leaROM ROM_AsyncBOut,a2 ; load up the inputs
lea PICAsyncBOut,a3
bra.s toBOpenPatch
;
; Prime Routines
;
; We patch the input prime routines because they're trashing the error code
; value thru one thread.
PICAInPrime move.l SerialVars,d0 ;Port A uses serial vars
bra.s InPrime
PICBInPrime
move.l ExpandMem,a2 ;Port B uses expand mem
move.l ExpandMemRec.emSerdVars(a2),d0
InPrime
move.l d0,a2 ;a2 = serial storage ptr (assume ok)
bgt.s @10 ;output driver is open
move.w #ReadErr,d0
move.l JIODone,-(sp) ;output side not open
rts
@10
clr.l ioActCount(a0) ;get ready for read
move.l a1,10(a2) ;save dce showing cmd active into ReadCmdDCE variable
moveq.l #NoErr,d0 ;clear out the error code!!! <41>
jmpROM ROM_BufferShuffle ;return to the twisted code in ROM
;
; Close Routines
;
; So far we only need to patch control for 7.0 VM to unhold the buffer
; we may have held durning ctl call #9.
;
PICAOutClose
PICBOutClose
with IOPRequestInfo
move.l a1,-(sp) ; save dce on stack
MOVE.L DCtlStorage(A1),a2 ; a2 = handle to local storage
MOVE.L (A2),A2 ; a2=local storage pointer
clr.b PICOpenFlag(a2) ;mark driver as closed
;kill the waiters on the event message
; fixed rmv to use same pb.
lea EventMsgPB(a2),a0 ; get address of the waiter
move.l a0,d0
_StripAddress ; and strip it
move.l d0,a0
move.b #irRemoveRcvWaiter,irRequestKind(a0) ;remove a wait for msg
_IOPMsgRequest ;remove it
;send a close msg to pic
move.b #CloseOpCode,OpenMsg+OpCode(a2) ;close opcode
lea OpenMsgPB(a2),a0 ;send msg to pic
_IOPMsgRequest
@10
tst.b OpenMsgPB+irReqActive(a2) ;is it done yet?
bne.s @10 ;no, wait some more
; and finally do what we came here for...
jsr UnHoldPICBuf ; unhold the buffer
jmpROM backToPICClose ; and go back to the ROM
endwith
;
; UnHoldPICBuf -- unholds the the buffer that may have been held
; Called by: control, close
; Inputs: a2 -- ptr to the serial vars
UnHoldPICBuf
; if old buffer was held, we better unhold it. it will have been held
; if it was not our LocalBuf, i.e. was not in the system heap
; first time thru this loop InBufPtr is 0.
move.l #gestaltVMAttr,d0 ; is VM installed?
_Gestalt
move.w a0,d0
beq.s @goodEnd ; if not, we're outta here
lea PICLocalBuf(a2),a0 ; inBufPtr = LocalBufPtr?
move.l a0,d0
_StripAddress ; being careful
movea.l PICInBufPtr(a2),a0 ; addr of old buffer
cmp.l a0,d0
beq.s @goodEnd ; yes, then don't need to unhold
cmpa.l #0,a0 ; inBufPtr = 0? (for first time thru)
beq.s @goodEnd ; yes, then don't need to unhold
clr.l d0 ; load count.l into a1 <137>
move.w PICBufSize(a2),d0 ; <137>
move.l d0,a1 ; <137>
_UnHoldMemory ; unhold the old buffer
rts
@goodEnd moveq #0,d0 ; everything a-ok
rts
;
; Control Routines
;
; So far we only need to patch control for 7.0 VM to hold the buffer in
; ctl call #9 in memory.
;
PICAOutControl
PICBOutControl
move.l DCtlStorage(a1),a2 ;recover handle from DCE
move.l (a2),a2 ;recover pointer
bra.s Control_1
PICAInControl ;Requires output driver open
move.l SerialVars,d0 ;Port A uses serial Vars
bra.s Control
PICBInControl ;Requires output driver open
move.l ExpandMem,a2 ;Port B uses expand mem area
move.l ExpandMemRec.emSerdVars(a2),d0
Control
;a0 = iopb
;a1 = dce
;d0 = address of serial storage (maybe)
move.l d0,a2 ;a2 = address of serial storage -- assume it is ok
bgt Control_1 ;is ok if not zero or < 0
jmpROM backToPICKillIO ;we don't want to be here unless storage ptr is ok
Control_1
move.w CSCode(a0),d1 ;
cmpi #9,d1 ; opcode 9?
beq.s Ctl9OpCode ; if so, handle here in the patch
jmpROM backToPICControl ; if not, let ROM handle it
;-------------------------------------------------
; Ctl9OpCode - install/remove user supplied buffers
; a0 = iopb
; a1 = dce
; a2 = output driver local storage
;-------------------------------------------------
Ctl9OpCode
movem.l a0-a1,-(sp) ; save out PB ptr and DCE ptr
clr.w PICBufIndex(a2) ;clear input and output indexes
clr.w PICBufOutdex(a2)
move.l CSParam(a0),a4 ; nubuf ptr
clr.l d1 ; clear out buffer count <135>
move.w CSParam+4(a0),d1 ;is nubuf being supplied (cnt)
beq.s @10 ;no, use our own
;::::::::::::::::::::::VM STUFF START::::::::::::::::::::::::::
; hold the new non-local buffer so VM doesn't page it out
move.l #gestaltVMAttr,d0 ; is VM installed? not on a mac II w/o MMU
_Gestalt
move.w a0,d0
beq.s @15 ; if not, skip the hold
movea.l a4,a0 ; hold buffer addr
movea.l #0,a1 ; clear out count
movea.l d1,a1 ; hold buffer count <135>
; since VM won't let us call _holdmemory with interrupts
; masked, we return the error that VM spits at us.
; note that PIC driver does not set interrupt mask at all
_HoldMemory ; hold the new buffer in memory
tst.w d0 ; did we get our physical buffer?
beq.s @15 ; yes, go on
bra.s toPicCtlExit ; no, punt with a VM error
@10
;install our own buffers
lea PICLocalBuf(a2),a4
move.w #LclBufSize,d1
@15 jsr UnHoldPICBuf ; unhold the old buffer if necessary
tst.w d0 ; did we release the old buffer?
bne.s toPicCtlExit ; no, punt with VM error
;::::::::::::::::::::::VM STUFF STOP:::::::::::::::::::::::::::
move.l a4,PICInBufPtr(a2) ; actually install the buffer
move.w d1,PICBufSize(a2)
clr.w d0 ;all done
toPicCtlExit movem.l (sp)+,a0-a1 ; restore PB ptr and DCE ptr
jmpROM ROM_PICCtlExit
;
; Status Routines
;
; We patch the status routines in order to provide a new Version number
; status call (9 and $8000 csCodes). We are adding negative csCodes for
; system required codes (see David Wong).
;
PICAOutStatus
PICBOutStatus
move.l DCtlStorage(a1),a2 ;recover storage ptr from our own DCE
move.l (a2),a2
bra.s Status_1
PICAInStatus
move.l SerialVars,d0 ;Port A uses serial Vars
bra.s Status
PICBInStatus
move.l ExpandMem,a2 ;Port B uses expand mem area
move.l ExpandMemRec.emSerdVars(a2),d0
Status
;a0 = iopb
;a1 = dce
;d0 = address of serial storage (maybe)
move.l d0,a2 ;a2 = address of serial storage -- assume it is ok
bne Status_1 ;is ok if not zero or < 0
move.w #StatusErr,d0 ;mark as status error
jmpROM StatusErrExit ;error output driver not open
Status_1
;process the status call always will complete immediately
;a0 = iopb
;a1 = dce
;a2 = output driver storage
MOVE.W CSCode(A0),D1 ; get opcode
cmpi.w #9,d1 ; do we care?
beq.s @version ; yes
cmpi.w #$8000,d1 ; largest negative number csCode for Version
beq.s @version ; yes
jmpROM BacktoPICStatus
@version
move.b #SerialVers,CSParam(a0); return the version <135>
jmpROM PICStatusOkExit;
; end of patched PIC routines
;_______________________________________
;_______________________________________
;
; Bypass Patch Code Entry Point
; (Patched Bypass mode routines here)
;
; Called By: we get here via the async serial patch vector ($a0be)
;
SerialPatch
movem.l d0/a2-a3,-(SP) ; save reg d0,a2,a3 <PMAB401>
move.l 16(SP),D0 ; get D0 = return address <PMAB401>
lea AsyncAIn,a2 ; assume we are coming from AIn
lea PICAsyncAIn,a3 ;
cmpRA fromAInOpen,D0 ; test for ChkAConfig call from AInOpen
beq.w OpenFix
lea AsyncAOut,a2 ; assume we are coming from Aout
lea PICAsyncAOut,a3 ;
cmpRA fromAOutOpen,D0 ; test for ChkAConfig call from AOutOpen
beq.w OpenFix
lea AsyncBIn,a2 ; assume we are coming from BIn
lea PICAsyncBIn,a3 ;
cmpRA fromBInOpen,D0 ; test for ChkBConfig call from BBInOpen
beq.w OpenFix
lea AsyncBOut,a2 ; assume we are coming from Bout
lea PICAsyncBOut,a3 ;
cmpRA fromBOutOpen,D0 ; test for ChkBConfig call from BOutOpen
beq.w OpenFix
move.l 12(sp),d0 ; one less level indirection for non-open calls
cmpRA fromControl,d0 ; to fix bypass control calls
beq.w ControlFix
cmpRA fromStatus,d0 ; to fix bypass control calls
beq.w StatusFix
cmpRA fromClose,d0 ; to fix bypass close calls
beq.w CloseFix
cmpRA fromInitSCC,d0 ; to fix initSCC routine
beq.w InitSCCFix
movem.l (sp)+,d0/a2-a3 ; restore regs <PMAB401>
RTS ; back to ROM
;
; Close fixes-- so far we only need to do it for 7.0 VM to unhold
; the buffer we may have held in control call #9.
;
CloseFix
ADD.L #16,SP ; pop save reg d0, for some reason the driver saved
; out ptr to globals in a6
move.l a1,-(sp) ; save out the DCE ptr
MOVE.L (A6),A2 ; get locals pointer <14Oct85>
TST.B CtlOptions(A2) ; leave DTR unchanged? <14Oct85>
bmi.s @1 ; <C216/16oct86>
bclr #7,XmitBits(A2) ; no, clear the DTR bit <C216/16oct86>
bclr #7,WR5AVal(A2) ; <C216/16oct86>
@1 bclr #3,XmitBits(A2) ; always clear Tx enable <C216/16oct86>
jsrROM SyncOutput ; delay until last char has cleared <14Oct85>
; output buffer
LeaROM ResetData,A3
MOVEQ #ResetLth,D1
jsrROM InitSCC1 ; shut down the channel
; now that we've shut down the channel it should be safe to unhold
; the input buffer. we won't check for error since we can't do much
; about it anyway.
jsr UnHoldInputBuf ; unhold the buffer if necessary
move.l (sp)+, a1 ; restore the DCE ptr
jmpROM backToClose
;::::::::::::::::::::::VM STUFF START::::::::::::::::::::::::::
;
; UnHoldInputBuf -- unholds the the buffer that may have been held
; Called by: control, close
; Inputs: a2 -- ptr to the serial vars
; if old buffer was held, we better unhold it. it will have been held
; if it was not our LocalBuf, i.e. was not in the system heap
; first time thru this loop InBufPtr is 0.
UnHoldInputBuf
move.l #gestaltVMAttr,d0 ; is VM installed?
_Gestalt
move.w a0,d0
beq.s @goodEnd ; if not, we're outta here
; check usual case...is inBufPtr equal to LocalBufPtr?
move.l d1,-(sp) ; save a reg
lea LocalBuf(a2),a0 ;inBufPtr = LocalBufPtr?
move.l a0,d1
move.l InBufPtr(a2),d0
eor.l d1,d0
_StripAddress ; ignore differences in the high bits
move.l (sp)+,d1 ; restore a reg
tst.l d0 ;
beq.s @goodEnd ; same, so don't need to unhold
; check first time thru case, when InBufPtr
; would equal zero
move.l InBufPtr(a2),d0 ; for first time thru, is InBufPtr zero?
beq.s @goodEnd ; yes, then don't need to unhold
; unhold the puppy
movea.l d0,a0 ; a0 <- ptr
moveq #0,d0 ; clear out count
move.w BufSize(a2),d0 ;
movea.l d0,a1 ; a1<- cnt
_UnHoldMemory ; unhold the old buffer
rts
@goodEnd moveq #0,d0 ; everything a-ok
rts
;::::::::::::::::::::::VM STUFF STOP:::::::::::::::::::::::::::
;
; Routine: InitSCC
; Patch: --We patch this routine to use the InitData table here in RAM
; instead of the one in ROM. We do this so that the values in
; WR11 and WR14 aren't hardcoded, so that we can support external
; clocking.
; --We also fix the value of StopBits (WR4) here to have the clock
; divide bits correspond to the the external/internal clock state
; indicated in CtlOptions. We do this here so that CtlConfig calls
; won't stomp StopBits in the ToSCCInit routine.
; --We also disable HWHS so we don't try to use CTS line for both
; clocking and handshaking.
clkBit equ 6 ; bit 6 in CtlOptions controls ext/int SCC clk
clkDvdBit equ 6 ; divide clock bit in WR4
clkMask equ %01000000 ; mask for getting at clkBit <129>
extClkSrc equ %00101000 ; SCC clk src is TRxC (CTS) pin (WR11) <129>
intClkSrc equ %01010000 ; SCC clk src is baud rate generator (WR11) <129>
BRGEnbl equ %00000001 ; enable baud rate generator (WR14) <129>
BRGDsbl equ %00000000 ; disable baud rate generator (WR14) <129>
SCCDataTable
DC.B $02,9 ; status in low bits, MIE disabled
clkDvd DC.B 4,$FF ; x16 clk, stop bits, parity options
DC.B 1,$FF ; WR1 reg, first write
DC.B 3,$FF ; bits/char option rcvr
DC.B 5,$FF ; bits/char option xmitter
DC.B $00,2 ; zero interrupt vector
DC.B $00,10 ; NRZ encoding
ClkMode DC.B $50,11 ; brgen/TRxC clk to rcvr, xmitter--default to internal
DC.B 12,$FF ; set baud rate low byte
DC.B 13,$FF ; set baud rate high byte
DC.B 3,$FF ; enable rcvr
DC.B 5,$FF ; enable xmitter
BRGEnable DC.B $01,14 ; enb/disable baud rate generator from RTxC pin --default to on
dc.b $A0,15 ; Break, CTS external ints (dcd not needed) <2.3>
DC.B $10,0 ; reset ext/status twice
DC.B $10,0
DC.B 1,$FF ; w/req pin configuration
DC.B $0A,9 ; enable interrupts, status in low bits
SCCDataTableLth EQU *-SCCDataTable ;
InitSCCFix
movem.l (sp)+,d0/a2-a3 ; restore drvr storage ptr in a2, InitSCC table in a3
add.l #4,sp ; pop saved rtrn addr--we jump back
move.l a3,d0
cmpRA InitData,d0 ; are we initializing SCC?
bne @done
lea SCCDataTable,a3 ; use our RAM table instead of the ROM one
moveq #SCCDataTableLth,d1
movem.l d1/a0,-(sp) ; save out reg's <129>
; default to internally clocked state <129>
bset.b #clkDvdBit,StopBits(a2) ; default to a divide-by-16 clock <129>
moveq #intClkSrc,d0 ; internal clocking source <129>
moveq #BRGEnbl,d1 ; enable baud rate generator <129>
btst.b #clkBit,CtlOptions(a2) ; are we externally clocked?
beq.s @load ; not externally clocked, so load
; set to externally clocked state
bclr.b #clkDvdBit,StopBits(a2) ; set to a divide-by-one clock <129>
moveq #extClkSrc,d0 ; external clock source <129>
moveq #BRGDsbl,d1 ; disable baud rate generator <129>
clr.b HWHS(a2) ; make sure we're not trying to do HWHS <129>
@load lea ClkMode,a0 ; load params into InitSCC data table <129>
move.b d0,(a0) ; <129>
lea BRGEnable,a0 ; <129>
move.b d1,(a0) ; <129>
movem.l (sp)+,d1/a0 ; restore reg's <129>
@done jmpROM backToInitSCC ; finish up in ROM
;
; Routine: Status
; Patch: We patch status to add a call to return the driver's version.
StatusFix
movem.l (sp)+,d0/a2-a3 ; restore drvr storage ptr in a2
add.l #4,sp ; pop saved rtrn addr--we jump back
MOVE.W IOTrap(A0),-(SP) ; save trap to distinguish immed calls<14Oct85>
MOVE.L A1,-(SP) ; save passed DCE for in/out <14Oct85>
MOVE.W SR,-(SP) ; disable interrupts for ctl call <14Oct85>
ORI #HiIntMask,SR ; <A357/06nov86>
LEA CSCode(A0),A0 ; get pointer to return parameters
MOVEQ #StatusErr,D0 ; assume status error
MOVE.L A2,D1 ; have our variables been set up? <14Oct85>
Bgt @stat1 ; exit if not (only input side open)
jmpROM ROM_CtlExit ; just like ROM
@stat1 MOVE.W (A0)+,D1 ; get opcode
cmpi.w #9,d1 ; do we care?
beq.s @version ; yes
cmpi.w #$8000,d1 ; largest negative number csCode for Version
beq.s @version ; yes
jmpROM BackToStatus ; no
@version move.b #SerialVers,(a0) ; return the version <135>
jmpROM ROM_CtlGood
;
; Routine: Control
; Patch: We patch control for the following reasons:
; 1) to add VM support for control call 9--lock/unlock the buffer
; 2) to add external clock support in control call 16
;
ControlFix
movem.l (sp)+,d0/a2-a3 ; restore drvr storage ptr in a2
add.l #4,sp ; pop saved rtrn addr--we jump back
MOVE.W IOTrap(A0),-(SP) ; save trap to distinguish immed calls<14Oct85>
MOVE.L A1,-(SP) ; save passed DCE for in/out <14Oct85>
MOVE.W SR,-(SP) ; disable interrupts for ctl call <14Oct85>
ORI #HiIntMask,SR ; <A357/06nov86>
moveq #0,d0 ; for the killIO call
LEA CSCode(A0),A0 ; get parameters
MOVE.W (A0)+,D1 ; get opcode
cmpi.w #9,d1 ; opcode 9? (buffer)
beq CtlBuffer ; if so, handle here in the patch
cmpi.w #16,d1 ; opcode 16? (ctlOptions) <extClk>
beq CtlSwitchCTSClock ; <extClk>
jmpROM backToControl ; if not, let ROM handle it
;_______________________________________;
;
; Install a new input buffer.
;
; The patch is needed for 7.0 VM. We must 'hold' the buffer in memory
; so that there is no possibility it is paged out at interrupt time (which
; would have the potential for causing a double page fault).
;_______________________________________;
CtlBuffer CLR.L BufIndex(A2) ; clear in and out indices
MOVE.L (A0)+,A4 ; buffer pointer
moveq #0,d1 ; clear out length reg
MOVE.W (A0),D1 ; length of buffer?
BEQ.S InstllLBuf ; if zero, revert to our own buffer
; hold the new non-local buffer so VM doesn't page it out
move.l #gestaltVMAttr,d0 ; is VM installed? not on a mac II w/o MMU
_Gestalt
move.w a0,d0
beq.s InstllABuf ; if not, skip the hold
movea.l a4,a0 ; hold buffer addr
movea.l d1,a1 ; hold buffer count
; since VM won't let us call _holdmemory with interrupts
; masked, we set the interrupt level back to that app's
; interrupt level, which hopefully was zero. If so, then
; everything should be peachy. If not, then we return the
; error that VM spits at us.
move.w sr,-(sp) ; save our int lvl
move.w 2(sp),d0 ; get app's int lvl
and.w (sp),d0 ; and set us to that
move.w d0,sr
_HoldMemory ; hold the new buffer in memory
move.w (sp)+,sr ; and restore our int lvl
tst.w d0 ; did we get our physical buffer?
beq.s InstllABuf ; yes, go on
Ctl_Err jmpROM ROM_CtlExit ; no, then pass back VM error
; InstllLBuf is also called from OpenInstall!
InstllLBuf LEA LocalBuf(A2),A4 ; use our meager local buffer for now
MOVEQ #LclBufSize,D1 ;
InstllABuf
; since VM won't let us call _holdmemory with interrupts
; masked, we set the interrupt level back to that app's
; interrupt level, which hopefully was zero. If so, then
; everything should be peachy. If not, then we return the
; error that VM spits at us.
move.w sr,-(sp) ; save our int lvl
move.w 2(sp),d0 ; get app's int lvl
and.w (sp),d0 ; and set us to that
move.w d0,sr
jsr UnHoldInputBuf ; unhold the buffer if necessary
move.w (sp)+,sr ; restore our int lvl
tst.w d0 ; did we release old buffer?
bne.s Ctl_Err ; no, pass back VM error
jsrROM FinishCall9 ; and finish up the call in ROM
jmpROM ROM_CtlGood ; and go back to ctl call dispatcher
;::::::::::::::::::::::VM STUFF STOP:::::::::::::::::::::::::::
; Routine: SetCtlOptions -- Opcode 16
; Patch: We patch this routine so that bit 6 of CtlOptions variable now
; controls a switch to internal/external clocking on the CTS (HSIn) line.
; We must call InitSCC to get the clocking option to kick in.
; Inputs: byte number in IOPB value
; (26) [$0010] opcode
; (28) bit 7 = 0 for drop DTR at close
; bit 7 = 1 for leave DTR unchanged at close
; bit 6 = 0 for internal clocking
; bit 6 = 1 for external clocking
; bits 0-5 reserved for future use
; Notes: We will not put control for the GPI internal/external
; clocking switch here, as that requires the control of
; HW external to the SCC (namely, the VIA vSync pin). Control
; of the GPIa line is in _HWPriv.
;
CtlSwitchCTSClock
move.b (a0),CtlOptions(a2) ; store new value <129>
jsrROM InitSCC ; set up the SCC according to new value <129>
jmpROM ROM_CtlGood ; finish up in ROM <129>
;
; Open Fixes
;
;
; note that no stack fiddling is allowed, as the chkConfigure EXPECTS to be called directly
; from the open routine, and will not go to IOCore with error properly should one occur.
; Common code for open patches
OpenFix move.l d0,a4 ; save where we came from w/o use of the stack
ADD.L #12,SP ; pop save reg d0,a2,a3 - not needed <PMAB401>
MOVE.L (SP)+,A0 ; pop A0 = addr to continue ChkConfig
addq #4,SP ; pop async open ret addr - will jmp back
OpnFx1 jsr (a0) ; finish ChkConfig (A1,D1,D2 params)
; check to see whether we are in IOP or Bypass mode
if isUniversal then ; <2.1>
TestFor SCCIOPExists ;check to see if we even have an IOP <2.1>
beq.s @05 ;if not, just use bypass mode driver <2.1>
endif ; <2.1>
btst #0,SCCIOPFlag ;are we in bypass mode? <8.7> test low mem, not PRAM
bne.s @05 ;yes, in bypass mode; use SCC driver <8.7> change bit sense
move.l a3,a2 ; plug in PIC driver header address
@goback jmpROM PlugInDrvr ; go finish open call
; install our RAM-based bypass driver header into DCE <125>
; a2 has pointer to RAM driver header
; a1 has pointer to DCE
@05
move.l a2,(a1) ; install ourselves into the DCE
; check again where we came from to see if which open fix to branch off to.
move.l a4,d0 ; restore where we came from
cmpRA fromAOutOpen,d0 ; test for ChkAConfig call from AOutOpen
beq.s FixAout
cmpRA fromBOutOpen,d0 ; test for ChkAConfig call from AOutOpen
beq.s FixBout
jmpROM backToInOpen ; for In driver just go finish open call <125>
FixAout
; replace receive routine vectors installed by async open
LEA PortAVars,A2 ; local variables address
peaROM ROM_PollDtaIn,-(sp) ; ROM--this proc handles disk poll data <20Oct85>
pea NewSCAIntHnd ; Special RxD int handler <4> <20Oct85>
pea NewRAIntHnd ; int handler <4> <20Oct85>
peaROM ROM_TAIntHnd,-(sp) ; ROM--TxD int handler <20Oct85>
PEA Lvl2DT+16 ; SCC interrupt dispatch table, chan A <20Oct85>
PEA NewExtAIntHnd ; External int handler <20Oct85>
jmpROM backToAOutOpen ; JUMP BACK INTO ROM
FixBout
; replace receive routine vectors installed by async open
move.l ExpandMem,a2 ; local variable address in is <2.0>
lea ExpandMemRec.emSerdVars(a2),a2 ; expandmem <2.0>
CLR.L -(SP) ; no disk poll routine
pea NewSCBIntHnd ; Special RxD int handler <4> <20Oct85>
pea NewRBIntHnd ; RxD int handler <4> <20Oct85>
peaROM ROM_TBIntHnd,-(sp) ; ROM--TxD int handler <20Oct85>
PEA Lvl2DT ; SCC interrupt dispatch table, chan B <20Oct85>
PEA NewExtBIntHnd ; External int handler <20Oct85>
jmpROM backToBOutOpen ; JUMP BACK INTO ROM
;-----------------------------------------------------------------------
;
; Interrupt Handlers
;
;-----------------------------------------------------------------------
;________________________________________________________________________
;
; Routine: RXIntHnd
;
; Arguments: A0 (input) -- chan A/B control read address
; A1 (input) -- chan A/B control write address
;
; Function: This routine handles SCC receiver interrupts for
; both channels; the data is read and stashed, IODone called
; if necessary.
;
; Patches: Patched to fix the serial thruput problem on Apollo and TimLC. <4>
; If we complete a device manager request we change the return
; address on the stack to return to the primary
; level 4 interrupt dispatcher, rather than to the code in the
; secondary dispatcher that checks to see if there is another
; RxChar available (and loops to process the next interrupt if so).
; This way we guarantee that we return all the way out of the interrupt
; handlers at least once per device manager request, allowing
; things like deferred tasks a chance to run.
;________________________________________________________________________
Lvl4IntPatchSize equ 10 ; size of interrupt patch code
NewRBIntHnd
move.l ExpandMem,a3 ; get appropriate variables (chan B) <2.0>
lea ExpandMemRec.emSerdVars(a3),a3 ; <2.0>
BRA.S RXIntHnd ; go to shared code
NewRAIntHnd LEA PortAVars,A3 ; get appropriate variables (chan A)
RXIntHnd MOVE.B SCCData(A0),D0 ; get the data byte
PollStash MOVE.L (A3)+,A2 ; get pointer to local variables
move.l InDCE(a2),a3 ; and DCE pointer <2.0>
AND.B CharMask(A2),D0 ; zero unused high bits <14Oct85>
MOVE.B PEChar(A2),D1 ; Are we translating PE Characters?
BEQ.S @1 ; No, just save the char.
CMP.B D1,D0 ; Is the new char a PEChar?
BNE.S @1 ; No, just do normal stuff
MOVE.B AltChar(A2),D0 ; Make sure that a good char <14Oct85>
; doesn't look like PEChar.
@1 TST.B SWHS(A2) ; software handshake enabled?
BEQ.S StashIt ; branch if not
CMP.B XONChar(A2),D0 ; was this an XON? <14Oct85>
bne.s chkXoff ; not an XOn <4>
ContOut CLR.B XOFFlag(A2) ; we got an XON, so clear Xoff-received flag <4>
jmpROM ToContOut1 ; XOn, so start output again <4>
chkXoff CMP.B XOFFChar(A2),D0 ; how about an XOFF? <14Oct85><4>
BNE.S StashIt ; if not, then stash the character
ST XOFFlag(A2) ; if so, then note it
InputRTS rts ; and exit <4>
; stash byte in the user's buffer if a request is pending, otherwise use our own
StashIt TST.B ReadCmd(A2) ; read request pending?
bne.s PutInUserBuf ; request pending, so stash byte in user buffer <4>
jmpROM ROM_PutInOurBuf ; no request pending, so stash byte in our buffer <4>
PutInUserBuf
MOVE.L A3,A1 ; get DCE pointer
jsrROM ROM_toStash ; use utility routine to save code <4>
BPL.S InputRTS ; if request isn't finished, just RTS
CLR.B ReadCmd(A2) ; no longer a read request pending
add.l #Lvl4IntPatchSize,(sp); return to rts at end of int dispatcher <patch><4>
; so we return out of Interrupt handler completely
; since we have finished a request
jmpROM ROM_GoodFinish ; we have a good finish
;________________________________________________________________________
;
; Routine: SCIntHnd
;
; Arguments: A0 (input) -- channel A/B control read address
; A1 (input) -- channel A/B control write address
;
; Function: This routine handles SCC special condition interrupts:
; these occur when an input character is received that has
; a parity error, framing error, or causes an overrun.
; If the option is set to abort on the error, the character
; is discarded and the input request (if any) aborted; otherwise,
; the error is noted and the character buffered as usual.
;
; Patch: Must patch this rtn because we patch the RxIntHnd which <4>
; includes the 'Stashit' label called here.
;
; If there are no special condition bits set, then this is NOT <5>
; a special-condition interrupt, but an interrupt for which
; the cause has already been removed. This occured with the
; Stylewriter on faster machines, when we wrote out a byte
; faster than the TBE interrupt could be generated (after
; the TBE bit was set in RR0).
;________________________________________________________________________
NewSCBIntHnd
move.l ExpandMem,a3 ; get appropriate variables (chan B) <2.0>
lea ExpandMemRec.emSerdVars(a3),a3 ; <2.0>
BRA.S SCIntHnd ; go to shared code
NewSCAIntHnd LEA PortAVars,A3 ; get appropriate variables (chan A)
SCIntHnd MOVE.B #1,(A1) ; point to error reg
MOVE.L (A3)+,A2 ; get local variables pointer
move.l InDCE(a2),A3 ; and DCE pointer (delay, too) <2.0>
MOVE.B (A0),D1 ; read the error condition
MOVEQ #$70,D3 ; form $70 mask
AND.B D3,D1 ; isolate error bits
beq.s InputRTS ; no errors posted, then this is not a SC interrupt <5>
OR.B D1,AsyncErr(A2) ; accumulate errors (delay, too)
MOVE.B SCCData(A0),D0 ; get the data byte
AND.B CharMask(A2),D0 ; zero unused high-order bits <14Oct85>
MOVE.B Options(A2),D2 ; get abort options
AND.B D1,D2 ; should we abort?
MOVE.B #$30,(A1) ; reset the error flag
AND.B D3,D2
beq.s @dontAbort ; options say we should NOT abort request <4>
jmpROM ROM_abortReq ; options say we should abort request <4>
@dontAbort MOVE.B PEChar(A2),D3 ; alternate char for parity errors? <4>
BEQ.S @1 ; br if not
CMP.B D0,D3 ; Is the incoming char equal to the PEChar?
BNE.S @0 ; No, no substitution needed.
MOVE.B AltChar(A2),D0 ; Make sure that a good char <14Oct85>
; doesn't look like PEChar.
@0 BTST #4,D1 ; parity error?
BEQ.S @1 ; br if not
MOVE.B D3,D0 ; replace it
@1 bra.s StashIt ; go stash it . . .<StashIt is IN RAM NOW> <4>
;________________________________________________________________________
;
; Routine: ExtIntHnd
;
; Arguments: A0 (input) -- channel A/B control read address
; A1 (input) -- channel A/B control write address
; D0 (input) -- SCC read reg 0 value
; D1 (input) -- SCC read reg 0 changed bits
;
; Function: This routine handles SCC external/status interrupts for
; both channels; mouse (DCD) interrupts are passed along to the
; mouse interrupt handler in CrsrCore. Only Break/Abort and CTS
; external interrupts are enabled (besides DCD).
;
; Note that CTS low in read reg 0 currently means that the
; hardware handshake line is asserted which means 'ok to transmit'.
;________________________________________________________________________
NewExtBIntHnd
move.l ExpandMem,a3 ; get appropriate variables - chan B <2.0>
move.l ExpandMemRec.emSerdVars(a3),a2 ; <2.0>
move.w #28,d2 ; .Bin is offset 28 into unit table <126>
bra.s ExtIntHnd
NewExtAIntHnd
LEA PortAVars,A3 ; get appropriate variables - chan A
MOVE.L (A3)+,A2 ; get pointer to local variables
move.w #20,d2 ; Ain is offset 20 in the unit table <126>
ExtIntHnd
movea.l UTableBase,a3 ; get addr of Utable <126>
movea.l 0(a3,d2.w),a3 ; get DCE handle (d2 has offset) <126>
movea.l (a3),a3 ; get DCE ptr <126>
MOVE.B D1,D2 ; changed bits
AND.B postOptions(A2),D2 ; post this change?
BEQ.S @0 ; br if not
MOVEM.L D0/A0,-(SP) ; preserve these registers
MOVE.W #IODrvrEvt,A0
ASL.W #8,D0 ; make room for 'changed' values
MOVE.B D1,D0
SWAP D0 ; make room for driver refnum
MOVE.W DCtlRefnum(A3),D0
_PostEvent ; and post the event
MOVEM.L (SP)+,D0/A0
@0 TST.B D1 ; see if it's a change in break status
BMI.S extBreak ; branch if it was a break interrupt
LSL.B #2,D0 ; must be CTS change
SMI CTSFlag(A2) ; set flags according to CTS
; This piece of code is used to detect a clock into the HWHS line
; and shut off the ext/sts interrupt for the handshake line.
CMP.W #80,HSCount(A2) ; exceeded 80 transitions in 16 MS? <14Oct85>
BCS.S @2 ; br if not <14Oct85>
MOVEQ #-128,D0 ; ($80) leave break ints enabled <14Oct85>
MOVEQ #15,D1 ; write register 15 <14Oct85>
jsrROM ToCtlSet ; <patch>
@2 MOVE.L Ticks,D2 ; get current tick time <14Oct85>
CMP.L LastTime(A2),D2 ; same as last? <14Oct85>
BEQ.S @3 ; br if so <14Oct85>
MOVE.L D2,LastTime(A2) ; new last time <14Oct85>
CLR.W HSCount(A2) ; restart count for new time <14Oct85>
@3 ADDQ #1,HSCount(A2) ; update count <14Oct85>
jmpROM toContOut1 ;<patch> BRA ContOut1--if freshly asserted, continue output<14Oct85>
extBreak TST.B D0 ; check break level
BMI.S @1 ; if it's asserted, terminate any input
MOVE.B SCCData(A0),D0 ; otherwise (end of break), discard null
@0 RTS ; and return
@1 MOVEQ #BreakRecd,D0 ; note the break
bset.b #3,AsyncErr(a2) ; we now note break level in status
TST.B ReadCmd(A2) ; read request pending?
beq.s @0 ; just return if done <7.1>
jmpROM ToRdReqDone ; return to ROM code
;_______________________________________________________________________
;
; Patched Driver headers (with signature long word before each header)
;
DC.b 'wong' ; our personal signature
AsyncAIn
DC.W $4D00 ; read, control, status, lock
DC.W 0,0 ; not an ornament
DC.W 0 ; no menu
DC.W AInOpen-AsyncAIn ; Initialization routine
DC.W AInPrime-AsyncAIn ; input Prime routine
DC.W AControl-AsyncAIn ; shared Control routine
DC.W AStatus-AsyncAIn ; shared Status routine
DC.W AInClose-AsyncAIn ; Close routine
DC.B 4 ; channel A input driver
DC.B '.AIn '
DC.b 'wong' ; our personal signature
AsyncAOut
DC.W $4E00 ; write, control, status, lock
DC.W 0,0 ; not an ornament
DC.W 0 ; no menu
DC.W AOutOpen-AsyncAOut ; Initialization routine
DC.W AOutPrime-AsyncAOut ; output Prime routine
DC.W AControl-AsyncAOut ; shared Control routine
DC.W AStatus-AsyncAOut ; shared Status routine
DC.W AOutClose-AsyncAOut ; Close routine
DC.B 5 ; channel A output driver
DC.B '.AOut'
DC.b 'wong' ; our personal signature
AsyncBIn
DC.W $4D00 ; read, control, status, lock
DC.W 0,0 ; not an ornament
DC.W 0 ; no menu
DC.W BInOpen-AsyncBIn ; Initialization routine
DC.W BInPrime-AsyncBIn ; input Prime routine
DC.W BControl-AsyncBIn ; shared Control routine
DC.W BStatus-AsyncBIn ; shared Status routine
DC.W BInClose-AsyncBIn ; Close routine
DC.B 4 ; channel B input driver
DC.B '.BIn '
DC.b 'wong' ; our personal signature
AsyncBOut
DC.W $4E00 ; write, control, status, lock
DC.W 0,0 ; not an ornament
DC.W 0 ; no menu
DC.W BOutOpen-AsyncBOut ; Initialization routine
DC.W BOutPrime-AsyncBOut ; output Prime routine
DC.W BControl-AsyncBOut ; shared Control routine
DC.W BStatus-AsyncBOut ; shared Status routine
DC.W BOutClose-AsyncBOut ; Close routine
DC.B 5 ; channel B output driver
DC.B '.BOut'
;_______________________________________________________________________
;
; jumping to ROM from our patched entry points
;
AInOpen jmpROM ROM_AInEntryOpen ;port a <125>
AInClose jmpROM ROM_AInEntryClose
AInPrime jmpROM ROM_AInEntryPrime
AOutOpen jmpROM ROM_AOutEntryOpen
AOutClose jmpROM ROM_AOutEntryClose
AOutPrime jmpROM ROM_AOutEntryPrime
AControl jmpROM ROM_AEntryControl
AStatus jmpROM ROM_AEntryStatus
BInOpen jmpROM ROM_BInEntryOpen ;port b
BInClose jmpROM ROM_BInEntryClose
BInPrime jmpROM ROM_BInEntryPrime
BOutOpen jmpROM ROM_BOutEntryOpen
BOutClose jmpROM ROM_BOutEntryClose
BOutPrime jmpROM ROM_BOutEntryPrime
BControl jmpROM ROM_BEntryControl
BStatus jmpROM ROM_BEntryStatus
endproc
;_______________________________________________________________________
; <7.1><8.7><81><123><125> Async Serial Driver Patch
;
; End of patch code for fix of bugs in the serial driver
; introduced into the aurora ROM (and hence the F19 overpatch ROM) by the
; port arbitration code, which was accidently included in those ROMS.
;_______________________________________________________________________
;_______________________________________________________________________
;________________________________________________________________________________
; <8.8> RecoverHandle() patch for 32-bit Memory Manager
;
; This patch fixes RecoverHandle so that if the passed block pointer isn't in
; either the system or app heaps, it makes a last-ditch pass and sees if the
; pointer points to a ROM resource. If so, great, else it bails with an error.
; This is especially useful since several new AppleTalk resources are in ROM
; and their users have a tendency to do RecoverHandles on them because they
; don't know any better (and shouldn't have to).
;
; No traps are patched. These routines are patched into the 32-bit Memory Manager's
; vector tables in lo-mem at JMemMgr24 ($1E00) and JMemMgr32 ($1F00).
;________________________________________________________________________________
PROC
EXPORT v24RecoverHandle,v32RecoverHandle
;________________________________________________________________________________
;
; Routine: v24RecoverHandle,v32RecoverHandle
;
; Inputs: A0 -- pointer to block
; A6 -- pointer to current heap zone
;
; Outputs: A0 -- handle to block
; D0 -- unchanged from input
; MemErr contains the error code
;
; Function: Given a pointer to an alleged heap block, it returns the block's handle.
;________________________________________________________________________________
v24RecoverHandle ; 24 bit version of RecoverHandle
MOVE.L Lo3Bytes,D2 ; mask to strip extraneous bits
BRA.S vRecoverHandle
v32RecoverHandle ; 32 bit version of RecoverHandle
MOVEQ #-1,D2 ; no extraneous address bits in 32-bit mode
vRecoverHandle
Move.L BusErrVct,A2 ; save current bus error handler
LEA RHBusErrHandler,A3 ; our ZC version
Move.L A3,BusErrVct
Move.L -4(A0),A1 ; Handle, or ROMBase on bus error
Move.L A2,BusErrVct ;restore old one after danger
Add.L A6,A1
; The following code tests for bad mp, but can only set MemErr
Move.L A0,D1 ; original pointer
And.L D2,D1 ; stripped to RAW address
AND.L (A1),D2 ; master pointer value stripped to RAW address
Sub.L D1,D2 ; if equal, have required error code!
Beq.S RecoverExit
; If we get here, the pointer either didn't point to a block in the suspected
; heap or is a bogus block pointer. We'll assume it's the first case and try
; looking in the ROZ created for the ROM resource map before giving up completely.
; This will not affect the performance of RecoverHandle() since this code is only
; executed as part of the error path (which shouldn't be taken most of the time).
MOVEA.L A6,A3 ; save the previous zone start pointer
MOVEA.L RomMapHndl,A6 ; get the handle to the ROM resource map
MOVEA.L (A6),A2 ; and de-reference it
SUBA.L -4(A2),A6 ; calculate heap start based on rel hdl in MP
CMPA.L A3,A6 ; have we been here before?
BNE.S v32RecoverHandle ; -> no, try again with the ROZ
MoveQ #memBCErr,D2 ; block check failure
RecoverExit
Move.W D2,MemErr ; stuff global error code (is anybody out there?)
MoveA.L A1,A0 ; restore A0=handle
Move.L vMMNoErrEpilogue,-(SP) ; get MMNoErrEpilogue vector
RTS
;________________________________________________________________________________
;
; RHBusErr -- bus error handler for RecoverHandle
; A bus error in RecoverHandle causes ROMBase to be jammed for
; the relative handle.
; Clear DF bit in frame to inhibit retry of failed read from RAM, and force
; ROMBase into result, i.e. A1.
; Input: none
; Output: potentially forces ROMBase to result field (ultimately A1)
; Regs: A3
; Triggered by bus errors in Move.L -4(A0),A1 in RecoverHandle.
;________________________________________________________________________________
RHBusErrHandler
AndI.W #$FEFF,$A(SP) ;clear DF bits
Move.L ROMBase,$2C(SP) ;fake Nil value in DIB
RtE
ENDPROC
;________________________________________________________________________________
;
; <8.8> End of RecoverHandle() patch
;________________________________________________________________________________
;________________________________________________________________________________
; RMP <12>
;
; SetHandleSize() patch for 32-bit Memory Manager
;
; This patch fixes A32SetSize not to de-reference off from a nil handle (i.e. A1)
; when it is called by v32SetHandleSize.
;
; No traps are patched. These routines are patched into the 32-bit Memory Manager's
; vector tables in lo-mem at JMemMgr32+jsetHandleSize ($1F64).
;________________________________________________________________________________
PROC
EXPORT v32SetHandleSize
IMPORT a32SetSize
;----------------------------------------------------------------------
;
; FUNCTION SetHandleSize(h: Handle; cb: LongInt): result;
;
; This routine is used to change the size of a relocatable memory block.
; The block handle remains the same; the Master Pointer is unchanged if
; the new length is less than or equal to the old.
;
; Arguments:
; D0 - cb: new block size
; A0 - handle: pointer to master pointer
;
; Result:
; D0 - 0 => success; memFullErr => failure
;
; Registers:
;
; A0 - next free block
; A1 - handle
;
v32SetHandleSize
BNE.S SHSOk
SHSNil
MoveQ #nilHandleErr,D0 ;return error code
BrA.S SHSExit
SHSOk
BSR.S a32SetSize ;Set size as specified in D0
SHSExit
Move.L A1,A0 ;restore A0 for RecoverHandle
Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue <v1.9>
RTS ; jump to it <v1.9>
ENDPROC
;________________________________________________________________________________
;
; <12> End of SetHandleSize() patch
;________________________________________________________________________________
;________________________________________________________________________________
; <68> <85>
;
; SetPtrSize() patch for 32-bit Memory Manager
;
; This patch fixes A32SetSize not to de-reference off from a nil handle (i.e. A1)
; when it is called by v32SetPtrSize.
;
; No traps are patched. These routines are patched into the 32-bit Memory Manager's
; vector tables in lo-mem at JMemMgr32+jsetptrSize ($1F4C).
;________________________________________________________________________________
PROC
EXPORT v32SetPtrSize,a32SetSize
; addresses in ROM
a32ActualS EQU $E5A2
a32GetSize EQU $E5D2
HBlockMove EQU $E334
a32MakeSpace EQU $EB40
ClearGZStuff EQU $E5F2
SubtractFree EQU $E92A
A32MakeBkF EQU $DDF4
AdjustFree EQU $E91C
A32SetLogSize EQU $E2A0
a32RelocRel EQU $EC66
a32SetSizePatch EQU $87996
SmartSetSize EQU 1
;----------------------------------------------------------------------
;
; FUNCTION SetPtrSize(blk: Ptr; cb: Size): result;
;
; This routine is used to set the size of non-relocatable memory blocks
;
; Arguments:
; D0 - cb: new block size
; A0 - blk: pointer to block data
; A1 - h: NIL, set up by MMPPrologue
;
; Result:
; D0 - 0 => success; memFullErr => failure
;
; Registers:
;
; A0 - next free block
; A1 - current free block
; A2 - theZone
; D0 - number of bytes needed
; D1 - number of bytes in current free block
; D2 - new block length (temporary)
;
v32SetPtrSize
BSR.S a32SetSize ; set its size <v1.1>
Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue <v1.9>
RTS ; jump to it <v1.9>
; ----- 32 bit version -----
a32SetSize
MoveM.L D1-D6/A0-A3,-(SP) ;Save registers. <18Apr85>
Move.L A0,A2 ;Points to block text. <v1.4>
Move.B MPtag32-BlkData32(A2),-(SP) ;save flags of block <v1.1>
Move.L D0,D1 ;Save desired logical size.
JSRROM a32ActualS ;
Move.L D0,D3 ;New physical size.
JSRROM.S a32GetSize ;Get current logical size in D0.
Cmp.L D0,D1 ;sNew = sCur?
BEq @SSEqual ;Yes, return to caller. <121>
Move.L A0,A2 ;Points to block text.
Sub.L #BlkData32,A2 ;Point to block header. <v1.1>
Move.L BlkSize32(A2),D2 ;Get physical size. <v1.1>
Move.L D2,D4 ;Old physical size.
Cmp.L D2,D3 ;sNAct = sCAct?
BEq @SSLogical ;Yes, just set logical size.
BCS @SSShrink ;sNAct < sCAct, shrink the block.
******************************** Start conditional block. ******************************** <18Apr85>
IF SmartSetSize THEN
; The block must be grown. <18Apr85>
; Registers: D0=D3=new phys size; D1=new log size; D2=D4=phys size; D5=?? <18Apr85>
; A0=text ptr; A1=handle; A2=block ptr; A3=?? <18Apr85>
; Across the code use registers: <18Apr85>
; D0=tmp; D1=new log size; D2=D4=phys size; D3=new phys size; D5=delta size <18Apr85>
; A0=tmp; A1=handle; A2=block ptr; A3=tmp <18Apr85>
; <18Apr85>
; First, set up some registers and the GZ's. <18Apr85>
Move.L D3,D5
Sub.L D2,D5 ;delta physical size
Move.L A1,GZRootHnd ;record handle being sized
Move.L A0,GZRootPtr ;record pointer " "
; In this loop, A3 steps across the blocks and D6 accumulates free space. <18Apr85>
MoveA.L A2,A3
AddA.L D4,A3 ;next block after growing
MoveQ #0,D6 ;initial accumulation
@SSAftFree
CmpA.L bkLim(A6),A3 ;have we reached the heap end?
BCC.S @SSAFEnd ;Carry Clear => beyond the end
Tst.B (A3) ;Eq => free block
BNE.S @SSAFEnd
Add.L BlkSize32(A3),D6 ;accumulate free space <v1.1>
AddA.L BlkSize32(A3),A3 ;bump on to next block <v1.1>
BrA.S @SSAftFree ;and continue looping
@SSAFEnd
; Detail: be sure to go on if exactly enough space is there -- for no sliding will be done! <18Apr85>
Sub.L D6,D5 ;D5 := amount unrequited by free space at end
BLS @SSAsUsual ;Lower or Same => enough space for easy growth!
; Provided the block is unlocked, relocatable, try coalescing free space from below, remembering <18Apr85>
; the 'last' block to give a backward peek when A2 is reached. The logic follows BFindS farily <18Apr85>
; closely. Starting at the heap's beginning, outer loop skips over allocated blocks (watching <18Apr85>
; for the one being grown); when a free block is hit, the inner loop starts coalescing until <18Apr85>
; allocated block (or growing one) is found. The loop terminates with A0 pointing to the last <18Apr85>
; free block found, and D0 equal to the amount of free space immmediately before the growing block. <18Apr85>
Move.L A1,D0
BEq @SSAsUsual ;Eq => it's a ptr, cannot move
Tst.B (SP) ;remember, the flags were saved earlier
BMi @SSAsUsual ;Mi => locked, cannot move
LEA heapData(A6),A3 ;start with the first block
@CoalLoop
CmpA.L A2,A3
BCC.S @CoalFini ;Carry Clear => beyond growing pointer
Tst.B TagBC32(A3) ; <v1.1>
BEq.S @CoalFree ;Eq => free block found <v1.1>
Move.L BlkSize32(A3),D0 ;get block size <v1.1>
AddA.L D0,A3 ;bump up to next block
MoveQ #0,D0 ;mark 'no immediately preceeding free space'
BrA.S @CoalLoop
@CoalFree
MoveA.L A3,A0 ;start of free space
MoveQ #0,D0 ;init accumulated free space
@CoalFLoop
CmpA.L allocPtr(A6),A3 ;is the rover at a disappearing block? <23Apr85>
BNE.S @1 ;NotEqual => no... <23Apr85>
Move.L A0,allocPtr(A6) ;don't let allocptr pt to nonexistent block <23Apr85>
@1 ; <23Apr85>
Add.L BlkSize32(A3),D0 ;accumulate free space <v1.1>
AddA.L BlkSize32(A3),A3 ;bump on to next block <v1.1>
Tst.B TagBC32(A3)
BEq.S @CoalFLoop ;Eq => more free space!
Clr.L TagBC32(A0) ;clear 1st long word of block <v1.1>
Move.L D0,BlkSize32(A0) ;update size of coalesced block <v1.1>
BrA.S @CoalLoop ;continue with this non-free block
@CoalFini
; We exit the above loop with D0=free space immediately below growing block, A0 pointing <18Apr85>
; to it. If at least 1/4 of the unrequited space can be made up by sliding, DO IT. <18Apr85>
; In case of a slide: if the free space is within a few minFree's of the needed space, <18Apr85>
; go the whole way, otherwise slide just enough to meet the needs. <18Apr85>
; A special case arises: when D5 is tiny, a fourth is zero, and this is BAD news if D0 is <18Apr85>
; also zero! The test BLS (as opposed to BCS) catches this case along with tinies. <18Apr85>
; Yet another goof -- must bound unrequited size by minFree, since that's the size of block <18Apr85>
; of free block we'll make at the end. <18Apr85>
Move.L D5,D6 ;unrequited space
LSR.L #2,D6 ;1/4 of it
Cmp.L D6,D0
BLS.S @SSNoSlide ;Lower or Same => too little space free (or none available)
MoveQ #minFree32,D6 ;Lower bound for unrequited <v1.2>
Cmp.L D5,D6
BLS.S @5 ;Lower or Same => D5 big enough for slide
Move.L D6,D5 ;Make at least minFree space...
@5
MoveQ #minFree32+minFree32,D6 ;unscientific slop <v1.2>
Add.L D5,D6 ;unrequited space + slop
Cmp.L D6,D0
BCS.S @SSFullSlide ;Carry Set => not enough extra to split free space
; To do a partial slide, decrement the size of the lower block by the amount we'll slide. <18Apr85>
Sub.L D5,D0 ;Size minus amount of slide <v1.1>
Clr.L TagBC32(A0) ;set free block <v1.1>
Move.L D0,BlkSize32(A0) ;Force size of free block (don't need A0 now)<C883>
AddA.L D0,A0 ;Target slot for growing block
Move.L D5,D0 ;Size of slide, for 'sliding' into FullSlide
; Full slide code: D0=amt of slide; D4=size of sliding block; D6=tmp; A0=dst of slide; <18Apr85>
; A1=handle to sliding block; A2=ptr to sliding block. Be sure to update the handle! <18Apr85>
; And after the block is moved, update GZRootPtr and allocPtr, since the latter may point <18Apr85>
; to a nonexistent free block. <18Apr85>
@SSFullSlide
Move.L A0,(A1) ;new location for sliding/growing block
Add.L #blkData32,(A1) ;be sure handle points to text of block!!!! <v1.1>
Move.B (SP),MPtag32(A0) ;restore the tags from home on the stack <v1.1>
MoveM.L D0/A1,-(SP) ;save amt of slide and handle
CmpA.L allocPtr(A6),A2 ;is the rover at the block we're moving? <23Apr85>
BNE.S @10 ;NotEqual => rover is elsewhere... <23Apr85>
Move.L A0,allocPtr(A6) ;point rover at new location <23Apr85>
@10 ; <23Apr85>
Exg A0,A2 ;A0=src of growing block, A1=dst
MoveA.L A2,A1 ;dst, for blockmove
Move.L D4,D0 ;current phys length is length of move!
;+++ BSr HBlockMove
JSRROM HBlockMove
MoveA.L A2,A0 ;ptr to moved block
AddA.L D4,A0 ;ptr just beyond -- to new free block
Move.L (SP)+,BlkSize32(A0) ;stuff size of new free block <v1.1>
Clr.L TagBC32(A0) ;free block <v1.1>
MoveA.L (SP)+,A1 ;restore handle
LEA blkData32(A2),A0 ;text ptr to growing block
Move.L A0,GZRootPtr
BrA.S @SSAsUsual
; Our last resort: check the block following ours; if it's larger and allocated, don't even <18Apr85>
; bother trying to move it. <18Apr85>
@SSNoSlide
MoveA.L A2,A0
AddA.L D4,A0 ;ptr to following block
Move.L BlkSize32(A0),D0 ;get size <v1.1>
Cmp.L D0,D3
BCC.S @SSAsUsual ;Carry Clear => new size is large, so go the normal route
Tst.B TagBC32(A0)
BNE.S @SSDoReloc ;Not Equal => larger, alloc block following
********************************* End conditional block. ******************************** <18Apr85>
ENDIF ; SmartSetSize
; This resumes the original SetSize growth code. The register setup must be adjusted to: <18Apr85>
; D0=??; D1=new log size; D2=D4=phys size; D3=new phys size; D4=phy size; D5=??; D6=?? <18Apr85>
; A0=??; A1=handle; A2=block ptr; A3=?? <18Apr85>
@SSAsUsual
Move.L A2,A0 ;Points to block header.
Move.L D3,D0 ;New physical size.
Sub.L D2,D0 ;Compute delta bytes.
Add.L D2,A2 ;Point to where space is needed
; doesn't move it by accident.
BSet #Lock,MPtag32(A0) ;lock block <v1.1>
JSRROM a32MakeSpace ;Try making room after this block.
BClr #Lock,MPtag32(A0) ;Unlock block <v1.1>
@200 Move.L A2,D4 ;Did we succeed?
BNE.S @SSEnough ;Yes, keep going
; New entry point to bypass MakeSpace when following block is bigger than one we're growing. <18Apr85>
@SSDoReloc
Move.L A1,D4 ;No, maybe we can relocate block.
BEq.S @SSFail ;No, block is Non-Relocatable.
Tst.B (SP) ;Can we move the growing block?
BMi.S @SSFail ;No, block is locked.
Move.L D1,D0 ;Desired new logical size.
; Try to grow the (unlocked) block by relocating&growing simultaneously. Across the call <10Apr85>
; mark it nonpurgeable, since we WANT it! Note must retrieve previous state from stack <10Apr85>
; unlike the BSet/BClr pair bracketing MakeSpace above. To get here, the Lock bit must be <10Apr85>
; clear, so the blithe BClr above jibes with our restoration from the stack. <10Apr85>
Move.L (A1),A3 ;dereference handle <v1.1>
BClr #Purge,MPtag32-BlkData32(A3);Unlock block <v1.1>
JSRROM a32RelocRel ;Relocate the old block into a new.
Move.L (A1),A0 ; get new address of block header <121>
Sub.L #BlkData32,A0 ;Point to block header. <121>
; MOVE.B (SP),MPtag32-BlkData32(A3) ;Restore previous state. <v1.1>
JSRROM ClearGZStuff ;mark gz stuff as done
BrA.S @SSExit ;Return to caller.
@SSFail ;Unable to find space.
JSRROM ClearGZStuff ;mark gz stuff as done
MoveQ #memFullErr,D0 ;Not enough room to reloc. block.
BrA.S @SSExit ;Return to caller.
@SSEnough ;Enough room has been found.
JSRROM ClearGZStuff ;mark gz stuff as done
Move.L BlkSize32(A2),D0 ;Length of free space after. <v1.1>
Move.L D0,D4 ;Physical size of free space.
Add.L D2,D4 ;Physical size of new combined blk.
Move.L A0,A2 ;Points to block.
Move.L D4,BlkSize32(A2) ;set block physical size. <v1.1>
; Neg.L D0 ;Minus size of new space.
; BSR.S AdjustFree ;Account for less free space.
JSRROM SubtractFree ;Account for less free space. <v1.7>
@SSShrink ;Shrink the block.
Sub.L D3,D4 ;Number of bytes to shrink block.
Cmp.L #MinFree32,D4 ;sFree < MinFree? <v1.2>
BCS.S @SSLogical ;Yes, set logical size only.
BTST #ROZ,flags(A6) ;don't shrink ROZ blocks <04Mar85>
BNE.S @SSSkip ; <04Mar85>
Move.L A2,A0 ;Points to block.
Add.L D3,A0 ;Point to new free block.
Move.L D3,BlkSize32(A2) ;set block physical size. <v1.1>
Move.L D4,D0 ;Size of new free block.
JSRROM a32MakeBkF ;Release free space.
JSRROM AdjustFree ;And account for new free space.
@SSLogical ;Set the logical size of the block.
Move.L A2,A0 ;Points to block.
Move.L D1,D0 ;New logical size.
JSRROM a32SetLogSize ;Set logical size.
@SSDone
MoveQ #0,D0 ;Success result code.
@SSExit
; Move.L (A1),A3 ;dereference handle <v1.1>
; Move.B (SP)+,MPtag32-BlkData32(A3) ;Restore MP flag byte. <v1.1>
Move.B (SP)+,MPtag32(A0) ;Restore MP flag byte. <v1.1>
@SSFin
MoveM.L (SP)+,D1-D6/A0-A3 ;Restore registers. <18Apr85>
RTS ;Return to caller.
@SSSkip
MoveQ #memROZWarn,D0 ; <04Mar85>
BRA.S @SSExit ; <04Mar85>
@SSEqual
Move.B (SP)+,D0 ; Don't care about saved MP flag <121>
MoveQ #0,D0 ;Success result code. <121>
Bra.S @SSFin ; <121>
ENDPROC
;________________________________________________________________________________
;
; <68><85> End of SetPtrSize() patch
;________________________________________________________________________________
;________________________________________________________________________
;
; <54> Rolled over changes from split-off sources on 4/16/90 by DDG
;
; Patch To IOPMsgRequest Trap to Fix IOP Serial Driver Control Call Bug
;
; Traps Patched: IOPMsgRequest
;
; The problem: IOP Serial Driver calls are being mis-queued because
; the control rtn is jumping to IODone before the control calls are
; actually completed on the 6502 side.
;
; The fix: to make the patch small, and because the control calls call
; the IOPMsgRequest trap, we do a come-from patch on that trap. If the
; 'come from' addresses match any of those in the driver, then the patch
; code is exectued. Else the ROM code (or previous patch) is jumped to.
; All the patch code does is jsr to the ROM code, then wait around for
; the IOP request to have completed before returning.
;
;________________________________________________________________________
proc
export IOPMsgRequest
;offsets to ROM addresses
IOPControlNormal EQU $6B932
IOPControl08 EQU $6B95A
IOPControl13 EQU $6B9C2
with IOPRequestInfo
IOPMsgRequest
; We can use the new protection scheme, if the first two instructions in the <115>
; patch are a bra.s followed by the jump to the old rom address.
bra.s @protection
@toRom
BackToTrap OldIOPMsgRequest ; no, then just execute ROM Code
@protection
cmpRA IOPControlNormal,OSTrapReturnAddressDepth(sp) ; from IOP serial drvr ctl call?
beq.s @doPatch ; yes, then come back here
cmpRA IOPControl08,OSTrapReturnAddressDepth(sp)
beq.s @doPatch
cmpRA IOPControl13,OSTrapReturnAddressDepth(sp)
bne.s @toRom
@doPatch move.l a0,-(sp) ; ROM IOPMsgRequest does not save a0
bsr.s @toRom ; bsr to IOPMsgRequest in ROM
move.l (sp)+,a0
@syncLoop tst.b irReqActive(a0)
bne.s @syncLoop
rts
endwith
endproc
;_______________________________________________________________________________
;
; <54> End of Patch To IOPMsgRequest Trap to Fix IOP Serial Driver Control Call Bug
;_______________________________________________________________________________
;____________________________________________________________________________ GGD <28>
; Patch the Deferred Task Manager Task Dispatcher to re-enable interrupts upon
; exiting to fix QuickMail servers (for now at least), because they call through
; jDisptch at application level and wind up with all interrupts being masked,
; and the Task Dispatcher expects to only be called from then end of an interrupt
; handler, which will restore the interrupt level via an RTE. Note that Applications
; should NOT be calling through this UNDOCUMENTED LOW MEMORY VECTOR, and we are
; changing this just so QuickMail servers don't hang with interrupts disabled,
; until CE Software can fix their bug.
NewvDisptch proc export
JsrTrap ROMvDisptch ; call the existing ROM code
andi.w #$F8FF,sr ; enable all interrupts
rts ; all done
endproc
; End of Deferred Task Manager Task Dispatcher Patch Installation
;____________________________________________________________________________ GGD <28>
;____________________________________________________________________________ jwk <29>
;
; BusErrHandler -- New and improved chaining SCSI bus error handler.
; When the SCSI Mgr is performing a blind data transfer, it patches
; out the bus error vector. The old SCSI Mgr bus error handler
; assumed that if it got called, it must be handling a SCSI bus error.
; Unfortunately, NuBus cards could bus error while the SCSI Mgr is
; installed. To be a better bus error citizen, the SCSI bus error
; handler now checks for a SCSI address as the fault address, and
; chains to the bus error handler that it replaced.
;
BusErrHandler: PROC EXPORT
ROMBusErrRecovery EQU $00008a6c ; recovery delay routine in ROM <29>
move.l d0,-(sp) ; save d0 <29>
moveq.l #$ffffff9c,d0 ; mask = $ffffff9c <start>
and.l 4+$10(sp),d0 ; clear variable bits of the fault address
cmp.l SCSIHsk,d0 ; was it a SCSI chip access ?
beq.s @start ; if so, start processing the bus error
move.l (sp)+,d0 ; restore d0
move.l OldBusErrVct(a6),-(sp) ; put old bus error handler addr on stack <end>
rts ; jump to old handler, assuming it'll RTE <29>
@start
subq.w #1,BusErrCount(a6) ; retry until we get tired
beq.s CleanUp
jmpROM ROMBusErrRecovery ; back off and try again (RTE) <29>
Cleanup
addq.l #4,sp ; throw away copy of d0 on stack <29>
move.w (sp),d0 ; get sr from stack
bfextu 6(sp){0:4},d1 ; get format code from stack
cmp.b #$0A,d1 ; short exception frame?
bne.s Drop46w ; no, so use larger frame
adda.w #16*2,sp ; dispose of the 16-word frame
bra.s DummyFrame ; and finish up
Drop46w
add.w #46*2,sp ; size of exception frame
DummyFrame
;
; Fake a format code 0 exception frame (4 words) to finish cleaning up
;
move.w zeroReg,-(sp) ; format code 0
pea FinishErr ; PC value
move.w d0,-(sp) ; sr value
rte ; 'return' from the fake exception
FinishErr
moveq.l #scBusTOErr,d0 ; assume slow peripheral
btst.b #bPM,sBSR(a3) ; phase change? <C478/10Dec86> <v1.5><29>
bne.s @ErrorDone ; phase matches: slow peripheral
moveq.l #scPhaseErr,d0 ; return phase change error
@ErrorDone
rts
;
; End of chaining SCSI bus error handler patch
;____________________________________________________________________________ jwk <29>
;_________________________________________________________________________________________ <119> djw
; Beginning code for Quantum 7.9 ROM fix
;
; Detailed description of the Quantum problem and solution:
;
; Quantum drives with the firmware version 7.9, has a problem with loosing the last byte
; of a block during a multi-block write. The problem occurs when the time between blocks
; written to the SCSI bus on the CPU side, is greater than 482 microseconds. This may
; occur in situations where there are a lot of interrupts. When conditions are right and
; the problem happens, the last byte of the previous block (in a multi-block transaction),
; is "eaten" by the drive. Any checksum or CRC calculated by the drive is correct,
; because the drive calculates it after the byte has been corrupted. This problem is
; especially frequent when email packages are installed on the Mac, since they generate
; a lot of interrupts which take a long time. This problem only occurs during fast
; writes in the SCSI manager (pseudo-dma mode).
;
; The way the SCSI manager currently works is it gets a TIB packet which contains the
; instructions on how to talk to a particular device. Included in the TIB is when to
; re-synchronize with the drive by waiting for a *REQ. When we see *REQ, the SCSI
; manager then begins the next TIB data transfer instruction and loads a byte of data
; into the 53C80's output register. After the first byte is "manually" sent, the
; hardware handshaking automatically takes care of the *REQ and *ACK handshaking. When
; the TIB write transfer is complete, pseudo-dma is disable, which releases *ACK,
; completing the handshake. This allows the target to assert *REQ when it is ready.
;
; The window of vulnerability is between the last byte of the previous block and the
; first byte of the next block. More correctly, it is between the rising edge of *ACK
; and the falling edge of the next *ACK. Because we release *ACK to synchronize, an
; interrupt may come in and delay the next transfer.
;
; The solution to the problem is to pre-load a data byte into the 53C80's data output
; register before we release *ACK. There are two ways of releasing *ACK: disable pseudo
; dma, and write a byte to the data output register. Leaving pseudo-dma enabled through
; the entire TIB will mean that whenever a *REQ occurs, there will be data available in
; the output register. This means there will be no delay between bytes because the
; hardware is not subject to interrupt delays.
;
; This patch therefore involves patching the TIB interpreter and the fast write routine
; in the SCSI manager. There are five versions of the SCSI manager to patch: Mac Plus,
; SE, Mac II, Portable, and IIci.
;
;_________________________________________________________________________________________
; QuantumWBlindIIci - patch to NewSCSIWBlind
;
; This code replaces the original NewSCSIWBlind entry point. The new entry for blind
; writes enables pseudo-dma on a per-transaction basis. Pseudo-dma was previously
; enabled only on a per-TIB-instruction basis. We jump back into the ROM to the original
; entry point to continue executing the TIB.
;
; Input: reg a3 = base of SCSI read addr
; a6 = SCSI stack frame
; d7 = zero
;
Export QuantumWBlindIIci
Export FastWriteFix
QuantumWBlindIIci
romNewSCSIWBlind Equ $07574 ; rom offset to NewSCSIWBlind entry point
move.b d7,sTCR+WrOffs(a3) ; set to match data out phase (to zero)
move.b #iDMA,sMR+WrOffs(a3) ; enable DMA in mode register
move.b #iDB,sICR+WrOffs(a3) ; assert data bus in initiator command reg
move.b d7,sDMAtx+WrOffs(a3) ; start write DMA
; Do I need to test for DRQ or *REQ at this point?
jmp ([RomBase],romNewSCSIWBlind); continue at original entry pt in ROM
;_________________________________________________________________________________________
; FastWriteFix - patch to FastWrite
;
; This code replaces the low level data transfer routine for fast writes in the SCSI
; manager. It is rewritten to assume psuedo-dma is always on, and to do the device
; synchronization (looking for *REQ and DRQ), after loading a data byte into the
; output register of the 5380. We don't have to worry about zero-byte transfers. They
; are filtered out in the calling routine (Transfer).
;
; Entry: d2 = number of bytes to transfer
; a1 = addr of sBSR(a3) - by convention, and used by bus error handler
; a2 = ptr to data buffer to transfer
; a3 = base addr of NCR 53C80
; a4 = ptr to SCSI globals
;
; Exit: d1 = number of bytes actually transfered. This value is only good if
; the transfer was good with no errors. It is inaccurate when an
; error aborts the transfer.
With scsiGlobalRecord
FastWriteFix
move.l hhsk5380(a4),a0 ; point to addr for hardware handshaking
adda.w wrOffset(a4),a0 ; add in write offset
move.l d2,d1 ; save to return number of bytes transfered
; Pre-load the NCR 53C80's output register with a byte of data. If we are in
; the middle of a multi-block write, *ACK is currently asserted. Writing a byte
; to the output register will release *ACK, completing the handshaking, allowing
; the target to assert *REQ. Is there a chance We do not need to check for DRQ at this point (to see
; if the chip is ready for the next byte), because all data out routines always
; wait to make sure the last byte got out.
sub.l #1,d2 ; dec number of bytes to xfer
move.b (a2)+,(a0) ; write data byte to output register
; With *ACK released, determine if the target is in sync. We cannot look for
; *REQ to be asserted, because the target may have already accepted the data byte
; and released *REQ at this point. We can sync on DRQ which will signal when
; the NCR 53C80 is ready to accept a data byte, meaning a *REQ from the target
; must have already occurred and our data byte was taken.
@syncWait
btst.b #bDMAR,(a1) ; check bus & status reg for DRQ
bne.s @doWrite ; DRQ present - sync-ed up so proceed
btst.b #bREQ,sCSR(a3) ; no DRQ - is *REQ present ?
beq.s @syncWait ; no *REQ yet - wait for sync
btst.b #bPM,(a1) ; with *REQ, check phase lines
bne.s @syncWait ; still in data out phase - wait
moveq.l #0,d1 ; out of phase - did not xfer any bytes
moveq.l #scPhaseErr,d0 ; return error
bra.s @Done ; exit
; Perform the write to the SCSI chip. First align the bytes to longs, then
; align them to 32 byte chunks. Transfer the bulk of the data in 32 byte
; blocks.
; Reg d2.l = number of bytes to move
@doWrite
cmpi.l #3,d2 ; check for very short copy
bls.s @veryShort ; skip alignment if very short
move.l a2,d0 ; get addr of data buffer
andi.l #$00000003,d0 ; check for long word alignment
beq.s @Aligned ; if no alignment needed
subq.l #4,d0 ; bias by 4 to get correct index
jmp @Aligned(d0.w*2) ; do the alignment
move.b (a2)+,(a0) ; move a byte
move.b (a2)+,(a0) ; move a byte
move.b (a2)+,(a0) ; move a byte
@Aligned
add.l d0,d2 ; adjust the byte count (d0 = neg)
move.l d2,d4 ; save tail byte count
lsr.w #2,d2 ; adjust to number of longs to move
moveq.l #7,d0 ; mask for starting index
and.l d2,d0 ; number of long words to move first
neg.w d0 ; negate to index backwards
lsr.l #3,d2 ; number of 32 byte blocks to move
move.l d2,d3 ; get number of 32*64K byte blks to move
swap d3 ; count in low word
jmp @CopyStart(d0.w*2) ; jump into the loop
@CopyLoop move.l (a2)+,(a0) ; move a 32 byte block of data....
move.l (a2)+,(a0) ; ... 4 bytes at a time
move.l (a2)+,(a0)
move.l (a2)+,(a0)
move.l (a2)+,(a0)
move.l (a2)+,(a0)
move.l (a2)+,(a0)
move.l (a2)+,(a0)
@CopyStart dbra d2,@CopyLoop ; loop in chunks of 32 bytes
dbra d3,@CopyLoop ; loop in chunks of 32*64K bytes
andi.l #$00000003,d4 ; check for tail alignment
move.l d4,d2 ; d2 = number of bytes remaining
@veryShort
neg.w d2 ; negate to index backwards
jmp @Remaining(d2.w*2) ; write remaining bytes
move.b (a2)+,(a0) ; move a byte
move.b (a2)+,(a0) ; move a byte
move.b (a2)+,(a0) ; move a byte
@Remaining
; Before exiting this routine, make sure that the peripheral has actually accepted
; the data byte. Wait for a DRQ (meaning the SCSI chip is ready for another byte)
; before exiting.
@DoneWait
moveq.l #0,d0 ; set good return
btst.b #bDMAR,(a1) ; check for DRQ (a1 = sBSR(a3))
bne.s @Done ; if DRQ, peripheral got the byte
btst.b #bREQ,sCSR(a3) ; no DRQ - is *REQ present ?
beq.s @DoneWait ; no *REQ yet - wait for it
btst.b #bPM,(a1) ; are we still in phase ?
bne.s @DoneWait ; if so, keep waiting
@Done
rts ; we're done
Endp ; end scsi patches
;____________________________________________________________________________ EH <33><37>
;
; Patch To IOPMoveData Trap to Fix IOP Serial Driver DMA Hang Bug
;
; Traps Patched: IOPMoveData
;
; The problem: the iop serial DMA hangs at if more than one byte
; accumulates in the SCC fifo. This is really a problem with the
; timing in the DMA hardware, but we'll work around it in software.
;
; The fix: In the main driver loop, we'll manually remove extra
; bytes from SCC fifo to DMA buffer before restarting the DMA.
;
; Note:If one of these manually moved bytes is in error, it will be
; bucketed (not moved to DMA buffer), as will subsequent bytes in the
; fifo.
;
; MECHANISM: To make the patch small, we do a come-from on IOPMoveData.
; We use the ROM IOPMove Data to download the patches to the 6502 code
; after we've already downloaded the unpatched image.
;
; <37> added in two fixes.
; Fix slow baud rate chars getting munched if a control call is made to
; change the baud rate. Now we wait for an ALL SENT from the SCC before
; dispatching all control calls.
;
; Fix CTS status on open to be reported properly back to 68000 side.
; We now properly set CTSFlag value during the open call, which is the
; value that gets reported in the status call.
;
; <123> added in external control call feature
; -- Use bit 6 now of the CtlOptions byte in control call 16
; bit 6 = 0 means internal clocking
; bit 6 = 1 means external clocking
; -- Incidentally, fixed bug in break handling code such that the null
; char is now discarded when break is de-asserted.
; -- changed ExtStatInt handler code to set bit 3 of Async Err if break is rcv'd.
; -- changed InitSCC rtn to check for ext clocking in setting WR4 clock divide bits.
; we also disable HWHS for the external clock case so we won't try to use the
; CTS line for clocking AND handshaking.
; -- changed the EXTInt handler to disable CTS interrupts if we receive them
; too quickly. This was never implemented in the IOP driver.
; Note we are doing a slime-bucket thing here by using ZP addresses that the ROM
; driver isn't using. But it doesn't look like anybody's using it, so hey, what
; the living heck. ZPSize is 32, so we'll start our stuff at offset $33.
; CTSCount = ZPBase+$33 the count of CTS transitions we started timing
; LastTime = ZPBase+$34 the last timer value (low byte) for a CTS interrupt
; -- Modify the Zero Page initialization to clear all $55 bytes we have
;
; <126>
; -- fix disable to HWHS for external clocking. it now gets disabled write before
; CtlOptions (#16) calls DoInitSCC instead of in the InitSCC routine.
; -- rolled in a fix to close that i had meant to add in <123>. We time out now
; on waiting for the all-sent on the close.
;
; <138>
; -- fix the IOP timer to actually count! i think the code to disable CTS interrupts
; was just working by chance, since i'm also fixing a branch instruction in
; that code to fix the bug with printing to the imagewriter.
;________________________________________________________________________
IOPMoveDataPatch proc
export IOPMoveData
;offsets to ROM addresses
From_IOPOpenCall EQU $0006bC48 ;return addr of IOPMoveData call in IOP Serial Open
ROM_IOPMoveData EQU $00004ed2 ;rom addr for the trap
;Pic RAM addresses
DrvrAPicAddr EQU $2d55 ; driver A start addr for Pic RAM
DrvrBPicAddr EQU $56aa ; driver B start addr for Pic RAM
numPatches EQU 24 ; number of times thru loop
PatchDrvrSize EQU $09ae ; size of the patched driver
;__________________________________________________________
;
; 6502 IOP Driver Patches -- code to fix in downloaded image.
; Patches are in order by offset from beginning of driver.
; Each set of patch bytes is preceded by a word offset to
; start of patch, and a byte for size of patch.
;
; There is one set of patches for Driver A and one for Driver B.
;__________________________________________________________
DrvrAFix
; changes zero page init to clear all $55 bytes
; this one-byte change is inline.
dc.b $00,$09 ; offset to this patch
dc.b @a20end-@a20 ; number patchbytes
@a20 dc.b $55 ; y<-$55, the index to clear out z-page
; fixes the new location of the driver buffers
; new buffer start addr is $3703 = $2d55(base) + $9ae(new offset)
@a20end dc.b $00,$46 ; offset to this patch
dc.b @a1end-@a1 ; number patchbytes
@a1 dc.b $a9,$37 ; lda #>Buffers (new high byte)
dc.b $a2,$03 ; lda #>Buffers (new low byte)
; fix one byte to load into DMA count
@a1end dc.b $00,$94 ; offset to this patch
dc.b @a2end-@a2 ; number patchbytes
@a2 dc.b $FB ; put FB in the DMA count instead of FF
; calls the fix to start the IOP timer since
; patch wouldn't fit inline
@a2end dc.b $00,$98 ; offset to this patch <138>
dc.b @a23end-@a23 ; number patchbytes <138>
; <138>
@a23 dc.b $4C,$f8,$36 ; jmp to fix at addr $36f8 = $2d55(base) +$9a3(offset) <138>
; calls the fix to CTSFlag on Open (see patch at $8D5) since the
; patch wouldn't fit inline
@a23end dc.b $01,$00 ; offset to this patch <37>
dc.b @a3end-@a3 ; number patchbytes <37>
; <37>
@a3 dc.b $4C,$2b,$36 ; jmp to fix at addr $362B = $2d55(base) +$8D6(offset) <37>
; calls the fix to DoPollEvent (see patch at $880) since the
; patch wouldn't fit inline
@a3end dc.b $01,$2F ; offset to this patch
dc.b @a4end-@a4 ; number patchbytes
@a4 dc.b $20,$D5,$35 ; jsr to fix at address $2d55(base) +$880(offset)
; calls the fix to DMA code (see patch at $886) since the
; patch wouldn't fit inline
@a4end dc.b $01,$46 ; offset to this patch
dc.b @a5end-@a5 ; number patchbytes
@a5 dc.b $F0,$03 ; beq to just below
dc.b $4C,$db,$35 ; jmp here if DMA was NOT stopped by interrupt rtn $2d55(base)+$886(offset)
dc.b $4C,$02,$36 ; jmp here if DMA was stopped by interrupt rtn $2d55(base)+$8ad(offset)
; fix one byte to load into DMA count
@a5end dc.b $01,$6E ; offset to this patch
dc.b @a6end-@a6 ; number patchbytes
@a6 dc.b $FB ; put FB in the DMA count instead of FF
; calls patch to close to time-out on the all sent loop since the
; patch wouldn't fit inline
@a6end dc.b $02,$6F ; offset to this patch
dc.b @a21end-@a21 ; number patchbytes
@a21 dc.b $4C,$e0,$36 ; jmp to fix at address $36e0 = $2d55(base) +$98b(offset) <37>
; calls the fix to all sent in control calls (see patch at 8C6) since the <37>
; patch wouldn't fit inline <37>
@a21end dc.b $03,$39 ; offset to this patch <37>
dc.b @a7end-@a7 ; number patchbytes <37>
; <37>
@a7 dc.b $4C,$1b,$36 ; jmp to fix at address $361b = $2d55(base) +$8C6(offset) <37>
; calls patch to add ext clking to control call 16 since the
; patch wouldn't fit inline
@a7end dc.b $4,$4a ; offset to this patch
dc.b @a12end-@a12
@a12 dc.b $4c,$38,$36 ; jump to fix at address $3638= $2d55(base) + $8e3(offset)
; calls patch to disable CTS interrupts if we get them too fast since
; patch wouldn't fit inline
@a12end dc.b $07,$36 ; offset to this patch
dc.b @a18end-@a18
@a18 dc.b $4c,$b5,$36 ; jump to fix at address $36b5= $2d55(base) + $960(offset)
; calls patch to set bit 3 of AsyncErr if break received since
; patch wouldn't fit inline
@a18end dc.b $07,$55 ; offset to this patch
dc.b @a14end-@a14
@a14 dc.b $4c,$82,$36 ; jump to fix at address $3682= $2d55(base) + $92d(offset) <126>
; calls patch to set clock divide bits for WR4 since
; patch wouldn't fit inline
@a14end dc.b $07,$79 ; offset to this patch
dc.b @a16end-@a16
@a16 dc.b $4c,$a1,$36 ; jump to fix at address $36a1= $2d55(base) + $94c(offset) <126>
; fixes the code at DoPollEvent to compare to DMA count,
; not the DMA address.
@a16end dc.b $08,$80 ; offset to this patch
dc.b @a8end-@a8 ; number patchbytes
@a8 dc.b $AD,$23,$F0 ; lda DMACntLo
dc.b $C9,$FB ; cmp #$FB
dc.b $60 ; rts
; fixes DMA code to check for bytes left over in the SCC fifo
@a8end dc.b $08,$86 ; offset to this patch
dc.b @a9end-@a9 ; number patchbytes
@a9 dc.b $AD,$22,$F0 ; lda DMA_AddrHi Set up temp pointer
dc.b $85,$5A ; sta TempBufPtr+1 into the DMA buffer. $55(base)+$05(offset)
dc.b $64,$59 ; stz TempBufPtr $55(base)+$04(offset)
dc.b $AC,$21,$F0 ; ldy DMA_AddrLo Get the byte offset into buffer
;@NxtChar
dc.b $AD,$41,$F0 ; lda SCC_Ctl Read RRO
dc.b $29,$01 ; and #Rx_CharAvail is there a receive char?
dc.b $F0,$2B ; beq @Done no chars, then we are done
dc.b $AD,$43,$F0 ; lda SCC_Data get the data char
dc.b $91,$59 ; sta (TempBufPtr),y store char in buffer $55(base)+$04(offset)
dc.b $84,$7F ; Sty HoldDMACount $55(base)+$2a(offset)
dc.b $C8 ; iny
; if any errors reset the scc
dc.b $A9,$01 ; lda #1 read RR1
dc.b $8D,$41,$F0 ; sta SCC_Ctl
dc.b $AD,$41,$F0 ; lda SCC_Ctl
dc.b $29,$70 ; and #$70 parity, overrun, framing err?
dc.b $85,$5E ; sta HoldRR1 save errors $55(base)+$09(offset)
dc.b $F0,$E3 ; beq @NxtChar no get the next char
; Suppose Special Rx Int has turned off DMA.
; There could be chars in FIFO after interrupt.
; Driver only flags errors on last byte DMAd in.
; To insure this, drop all bytes after error.
; SHOULD BE FIXED WHEN DRIVER REVVED
;@ResetSCC
dc.b $A9,$30 ; lda #$30 send err reset to SCC
dc.b $8D,$41,$F0 ; sta SCC_Ctl
dc.b $AD,$43,$F0 ; lda SCC_Data flush SCC FIFO
dc.b $A9,$30 ; lda #$30 send err reset to SCC
dc.b $8D,$41,$F0 ; sta SCC_Ctl
dc.b $AD,$43,$F0 ; lda SCC_Data flush SCC FIFO
dc.b $A9,$30 ; lda #$30 send err reset to SCC
dc.b $8D,$41,$F0 ; sta SCC_Ctl
;@Done
dc.b $4C,$b0,$2E ; jump back to our regularly scheduled code $2d55(base) +$15b(offset)
; fixes ctrl calls to wait for all sent from SCC before executing
@a9end dc.b $08,$C6 ; offset to this patch
dc.b @a10end-@a10 ; number patchbytes
;@wait_more <37>
@a10 dc.b $78 ; sei turn off interrupts <37>
dc.b $A9,$01 ; lda #$01 read RR1 <37>
dc.b $8D,$41,$F0 ; sta SCC_Ctl <37>
dc.b $AD,$41,$F0 ; lda SCC_Ctl <37>
dc.b $58 ; cli turn on interrupts <37>
dc.b $6A ; ror a test the all sent bit, bit 0 <37>
dc.b $90,$F3 ; bcc @wait_more <37>
dc.b $7C,$33,$35 ; jmp (ControlDispatch,x) <37>
; ControlDispatch at $3533 = $2d55(base) + $7DE(offset) <37>
; fixes ctrl calls to wait for all sent from SCC before executing <37>
@a10end dc.b $08,$D6 ; offset to this patch <37>
dc.b @a11end-@a11 ; number patchbytes <37>
; <37>
; ctsFlag = 0 on input. Acc holds RRO value <37>
@a11 dc.b $29,$A0 ; and #$A0 isolate DTR and break bits <37>
dc.b $85,$58 ; sta holdRR0 $55(base) + $17(offset) <37>
dc.b $29,$20 ; and #$20 is DTR asserted? <37>
dc.b $F0,$02 ; beq @1 yes, then CTSFlag stays 0 <37>
dc.b $C6,$6C ; dec CTSFlag no, then CTSFlag goes to $FF CTSFlag at $55(base) + $17(offset)
dc.b $4C,$59,$2E ;@1 jmp backToCode at $2e59 = $2d55(base) + $104 offset <37>
; adds external clocking control into bit 6 of the
; CtlOptions byte for control call 16
@a11end dc.b $08,$e3 ; offset to this patch
dc.b @a13end-@a13 ; number of patchbytes
@a13 dc.b $a5,$73 ;lda CtlOptions get old clk bit $55(base)+$1e(offset)
dc.b $29,$40 ;and #clkMsk bit 6
dc.b $aa ;tax
dc.b $ad,$84,$02 ;lda C16_CtlOptions get new byte $200(base)+$80(msg#)+$4(offset)
dc.b $a8 ;tay
dc.b $29,$40 ;and #clkMsk bit 6
dc.b $85,$73 ;sta CtlOptions $55(base)+$1e(offset)
dc.b $8a ;txa
dc.b $c5,$73 ;cmp CtlOptions is old clock bit same as new? $55(base)+$1e(offset)
dc.b $d0,$05 ;bne @switchIt nope, switch clk mode
dc.b $84,$73 ;@out sty CtlOptions store new byte $55(base)+$1e(offset)
dc.b $4c,$7f,$30 ;jmp DoControlEvent_Return $2d55(base) +$32a(offset)
dc.b $98 ;@switchIt tya
dc.b $0a ;asl shift into minus bit
dc.b $30,$14 ;bmi @ext
dc.b $a9,$50 ;@int lda #intClkSrc set int clk params
dc.b $8d,$17,$35 ;sta WR11_Data $2d55(base) +$7c2(offset)
dc.b $a9,$01 ;lda #BRGEnbl
dc.b $8d,$1d,$35 ;sta WR14_Data $2d55(base) +$7c8(offset)
dc.b $ad,$0d,$35 ;lda WR4_data set clock divide to 16 $2d55(base) +$7b8(offset)
dc.b $09,$40 ;ora #dvd16Msk clock divide bit is bit 6
dc.b $8d,$0d,$35 ;sta WR4_data in WR4 $2d55(base) +$7b8(offset)
dc.b $80,$12 ;bra @load
dc.b $a9,$28 ;@ext lda #extClkSrc set ext clk params
dc.b $8d,$17,$35 ;sta WR11_Data $2d55(base) +$7c2(offset)
dc.b $a9,$00 ;lda #BRGDsbl
dc.b $8d,$1d,$35 ;sta WR14_Data $2d55(base) +$7c8(offset)
dc.b $ad,$0d,$35 ;lda WR4_data set clock divide to one $2d55(base) +$7b8(offset)
dc.b $29,$BF ;and #dvdOneMsk clock divide bit is bit 6
dc.b $8d,$0d,$35 ;sta WR4_data in WR4 $2d55(base) +$7b8(offset)
dc.b $5a ;@load phy ; save the control byte
dc.b $64,$63 ;stz HWHSenable disable hardware handshaking $55(base)+$0e(offset) <126>
dc.b $20,$f4,$34 ;jsr DoInitSCC $2d55(base) +$79f(offset)
dc.b $7a ;ply
dc.b $80,$c8 ;bra @out <126>
; patch to set bit 3 of AsyncErr if break received
@a13end dc.b $09,$2d ; offset to this patch <126>
dc.b @a15end-@a15 ; number of patchbytes
@a15 dc.b $8a ;txa a=changed bits
dc.b $30,$03 ;bmi @change break changed
dc.b $4c,$ad,$34 ;@done jmp ExtStatEnd $2d55(base) +$758(offset)
dc.b $a5,$58 ;@change lda LastRRO get break value $55(base)+$03(offset)
dc.b $30,$05 ;bmi @post break was set
dc.b $ad,$43,$f0 ;lda SCC_data break unset, discard null
dc.b $80,$f4 ;bra @done
dc.b $a9,$08 ;@post lda #$08 set bit 3
dc.b $24,$67 ;bit ResetAsyncErr has host read stats $55(base)+$12(offset)
dc.b $10,$04 ;bpl @unread
dc.b $64,$68 ;stz AsyncErr $55(base)+$13(offset)
dc.b $64,$67 ;stz ResetAsyncErr $55(base)+$12(offset)
dc.b $05,$68 ;@unread ora AsyncErr $55(base)+$13(offset)
dc.b $85,$68 ;sta AsyncErr $55(base)+$13(offset)
dc.b $80,$e4 ;bra @done
; patch to set clock divide bits for WR4 and disable HWHS for ext clock
@a15end dc.b $09,$4c ; offset to this patch <126>
dc.b @a17end-@a17 ; number of patchbytes
;acc=%0400xxxx default to divide-by-16
@a17 dc.b $da ;phx save reg
dc.b $aa ;tax save acc
dc.b $a5,$73 ;lda CtlOptions are we ext clk'd? $55(base)+$1e(offset)
dc.b $0a ;asl shift ext clk bit into minus bit
dc.b $30,$03 ;bmi @ext yes, go fix clk dvd bits and disable HWHS
dc.b $8a ;@int txa no, just restore acc
dc.b $80,$03 ;bra @done <126>
dc.b $8a ;@ext txa restore acc
dc.b $29,$0f ;and #$0f fix clk dvd bits to div-by-one
; dc.b $64,$63 ;stz HWHSenable disable hardware handshaking $55(base)+$0e(offset)<126>
dc.b $fa ;@done plx restore reg
dc.b $8d,$0d,$35 ;sta WR4_Data and write out WR4 value $2d55(base) +$7b8(offset)
dc.b $4c,$d1,$34 ;jmp FinishInitSCC and finish up $2d55(base) +$77c(offset)
; patch to disable CTS interrupts if we get them too fast
@a17end dc.b $09,$60 ; offset to this patch
dc.b @a19end-@a19 ; number of patchbytes
@a19 dc.b $a5,$88 ;lda CTSCount exceeded 5 transitions in 1 ms? $55(base)+$33(offset)
dc.b $c9,$05 ;cmp #5
dc.b $90,$0c ;bcc @fixTime no, then fix the time
dc.b $a9,$0f ;lda #15 yes, then disable CTS interrupts
dc.b $8d,$41,$f0 ;sta SCC_Ctl write to WR15
dc.b $a9,$80 ;lda #$80 bit 5 clear to disable CTS ints
dc.b $8d,$41,$f0 ;sta SCC_Ctl
dc.b $80,$12 ;bra @out go finish in ROM
;@fixTime
dc.b $a5,$89 ;lda LastTime get last count (remember it's a countdown timer)
dc.b $ed,$11,$f0 ;sbc TimerCounterH time elasped > threshold? $55(base)+$34(offset)
dc.b $c9,$08 ;cmp #threshold threshold is 1 ms≈ 8 ticks
dc.b $90,$07 ;bcc @update no, just increment <138>
dc.b $ad,$11,$f0 ;lda TimerCounterH yes, set new last time
dc.b $85,$89 ;sta LastTime $55(base)+$34(offset)
dc.b $64,$88 ;stz CTSCount and restart count $55(base)+$33(offset)
;@update inc the transition count
dc.b $e6,$88 ;inc CTSCount $55(base)+$33(offset)
;@out
dc.b $64,$6c ;stz CTSFlag do stuff we stomped on in overpatch $55(base)+$17(offset)
dc.b $a5,$58 ;lda RRO $55(base)+$03(offset)
dc.b $4c,$8f,$34 ;jmp BackToROM finish up in ROM $2d55(base) +$73a(offset)
; patch to close to time-out on the all sent loop
@a19end dc.b $09,$8b ; offset to this patch
dc.b @a22end-@a22 ; number of patchbytes
@a22 dc.b $a5,$FF ;ldx #$FF load up $FFFF for timeout loop
dc.b $c9,$FF ;ldy #$FF 24 cycles * .5 us/cycle * 64K ≈ .8 seconds
dc.b $a9,$01 ;@loop lda #1 read from RR1
dc.b $8d,$41,$f0 ;sta SCC_Ctl
dc.b $ad,$41,$f0 ;lda SCC_Ctl
dc.b $6a ;ror get all sent bit in carry
dc.b $b0,$06 ;bcs @done if allsent, then outta here
dc.b $ca ;dex not allsent, so keep waiting
dc.b $d0,$f2 ;bne @loop
dc.b $88 ;dey
dc.b $d0,$ef ;bne @loop
dc.b $4c,$cf,$2f ;@done jumpBacktoClose $2d55(base) +$27a(offset)
; patch to start the IOP timer
@a22end dc.b $09,$a3 ; offset to this patch
dc.b @a24end-@a24 ; number of patchbytes
@a24 dc.b $9c,$24,$f0 ;stz DMA_CntHi do code we stomped with patch
dc.b $a9,$ff ;lda #$FF
dc.b $8d,$11,$f0 ;sta TimerCounterH get the timer started (just need to write to it)
dc.b $4c,$f0,$2d ;@done jumpBacktoOpen $2d55(base) +$09b(offset)
@a24end dc.w 0 ; filler
DrvrBFix
; changes zero page init to clear all $55 bytes
; this one-byte change is inline.
dc.b $00,$09 ; offset to this patch
dc.b @b20end-@b20 ; number patchbytes
@b20 dc.b $55 ; y<-$55, the index to clear out z-page
; fixes the new location of the driver buffers
; new buffer start addr is $604d = $56aa(base) + $9a3(new offset)
@b20end dc.b $00,$46 ; offset to this patch
dc.b @b1end-@b1 ; number patchbytes
@b1 dc.b $a9,$60 ; lda #>Buffers (new high byte)
dc.b $a2,$4d ; lda #>Buffers (new low byte)
; fix one byte to load into DMA count
@b1end dc.b $00,$94 ; offset to this patch
dc.b @b2end-@b2 ; number patchbytes
@b2 dc.b $FB ; put FB in the DMA count instead of FF
; calls the fix to start the IOP timer since
; patch wouldn't fit inline
@b2end dc.b $00,$98 ; offset to this patch <138>
dc.b @b23end-@b23 ; number patchbytes <138>
; <138>
@b23 dc.b $4C,$4d,$60 ; jmp to fix at addr $604d = $56aa(base) +$9a3(offset) <138>
; calls the fix to CTSFlag on Open (see patch at $8D5) since the
; patch wouldn't fit inline
@b23end dc.b $01,$00 ; offset to this patch <37>
dc.b @b3end-@b3 ; number patchbytes <37>
; <37>
@b3 dc.b $4c,$80,$5F ; jmp to fix at addr $5F80 = $56aa(base) +$8D6(offset) <37>
; calls the fix to DoPollEvent (see patch at $880) since the
; patch wouldn't fit inline
@b3end dc.b $01,$2F ; offset to this patch
dc.b @b4end-@b4 ; number patchbytes
@b4 dc.b $20,$2a,$5F ; jsr to fix at address $56aa(base) +$880(offset)
; calls the fix to DMA code (see patch at 886) since the
; patch wouldn't fit inline
@b4end dc.b $01,$46 ; offset to this patch
dc.b @b5end-@b5 ; number patchbytes
@b5 dc.b $F0,$03 ; beq to just below
dc.b $4C,$30,$5F ; jmp here if DMA was NOT stopped by interrupt rtn $56aa(base)+$886(offset)
dc.b $4C,$57,$5F ; jmp here if DMA was stopped by interrupt rtn $56aa(base)+$8ad(offset)
; fix one byte to load into DMA count
@b5end dc.b $01,$6E ; offset to this patch
dc.b @b6end-@b6 ; number patchbytes
@b6 dc.b $FB ; put FB in the DMA count instead of FF
; calls patch to close to time-out on the all sent loop since the
; patch wouldn't fit inline
@b6end dc.b $02,$6F ; offset to this patch
dc.b @b21end-@b21 ; number patchbytes
@b21 dc.b $4C,$35,$60 ; jmp to fix at address $6035 = $56aa(base) +$98b(offset) <37>
; calls the fix to all sent in control calls (see patch at 8C6) since the <37>
; patch wouldn't fit inline <37>
@b21end dc.b $03,$39 ; offset to this patch <37>
dc.b @b7end-@b7 ; number patchbytes <37>
; <37>
@b7 dc.b $4C,$70,$5F ; jmp to fix at address $5F70 = $56aa(base) +$8C6(offset) <37>
; calls patch to add ext clking to control call 16 since the
; patch wouldn't fit inline
@b7end dc.b $4,$4a ; offset to this patch
dc.b @b12end-@b12
@b12 dc.b $4c,$8d,$5f ; jump to fix at address $5f8d= $56aa(base) + $8e3(offset)
; calls patch to disable CTS interrupts if we get them too fast since
; patch wouldn't fit inline
@b12end dc.b $07,$36 ; offset to this patch
dc.b @b18end-@b18
@b18 dc.b $4c,$0a,$60 ; jump to fix at address $600a= $56aa(base) + $960(offset)
; calls patch to set bit 3 of AsyncErr if break received since
; patch wouldn't fit inline
@b18end dc.b $07,$55 ; offset to this patch
dc.b @b14end-@b14
@b14 dc.b $4c,$d7,$5f ; jump to fix at address $5fd7= $56aa(base) + $92d(offset)
; calls patch to set clock divide bits for WR4 since
; patch wouldn't fit inline
@b14end dc.b $07,$79 ; offset to this patch
dc.b @b16end-@b16
@b16 dc.b $4c,$f6,$5f ; jump to fix at address $5ff6= $56aa(base) + $94c(offset)
; fixes the code at DoPollEvent to compare to DMA count,
; not the DMA address.
@b16end dc.b $08,$80 ; offset to this patch
dc.b @b8end-@b8 ; number patchbytes
@b8 dc.b $AD,$2B,$F0 ; lda DMACntLo
dc.b $C9,$FB ; cmp #$FB
dc.b $60 ; rts
; fixes DMA code to check for bytes left over in the SCC fifo
@b8end dc.b $08,$86 ; offset to this patch
dc.b @b9end-@b9 ; number patchbytes
@b9 dc.b $AD,$2A,$F0 ; lda DMA_AddrHi Set up temp pointer
dc.b $85,$AF ; sta TempBufPtr+1 into the DMA buffer. $aa(base)+$05(offset)
dc.b $64,$AE ; stz TempBufPtr $aa(base)+$04(offset)
dc.b $AC,$29,$F0 ; ldy DMA_AddrLo Get the byte offset into buffer
;@NxtChar
dc.b $AD,$40,$F0 ; lda SCC_Ctl Read RRO
dc.b $29,$01 ; and #Rx_CharAvail is there a receive char?
dc.b $F0,$2B ; beq @Done no chars, then we are done
dc.b $AD,$42,$F0 ; lda SCC_Data get the data char
dc.b $91,$AE ; sta (TempBufPtr),y store char in buffer $aa(base)+$04(offset)
dc.b $84,$D4 ; Sty HoldDMACount $aa(base)+$2a(offset)
dc.b $C8 ; iny
; if any errors reset the scc
dc.b $A9,$01 ; lda #1 read RR1
dc.b $8D,$40,$F0 ; sta SCC_Ctl
dc.b $AD,$40,$F0 ; lda SCC_Ctl
dc.b $29,$70 ; and #$70 parity, overrun, framing err?
dc.b $85,$B3 ; sta HoldRR1 save errors $aa(base)+$09(offset)
dc.b $F0,$E3 ; beq @NxtChar no get the next char
; Suppose Special Rx Int has turned off DMA.
; There could be chars in FIFO after interrupt.
; Driver only flags errors on last byte DMAd in.
; To insure this, drop all bytes after error.
; SHOULD BE FIXED WHEN DRIVER REVVED
;@ResetSCC
dc.b $A9,$30 ; lda #$30 send err reset to SCC
dc.b $8D,$40,$F0 ; sta SCC_Ctl
dc.b $AD,$42,$F0 ; lda SCC_Data flush SCC FIFO
dc.b $A9,$30 ; lda #$30 send err reset to SCC
dc.b $8D,$40,$F0 ; sta SCC_Ctl
dc.b $AD,$42,$F0 ; lda SCC_Data flush SCC FIFO
dc.b $A9,$30 ; lda #$30 send err reset to SCC
dc.b $8D,$40,$F0 ; sta SCC_Ctl
;@Done
dc.b $4C,$05,$58 ; jump back to our regularly scheduled code $56aa(base) +$15B(offset)
; fixes ctrl calls to wait for all sent from SCC before executing <37>
@b9end dc.b $08,$C6 ; offset to this patch <37>
dc.b @b10end-@b10 ; number patchbytes <37>
; <37>
;@wait_more <37>
@b10 dc.b $78 ; sei turn off interrupts <37>
dc.b $A9,$01 ; lda #$01 read RR1 <37>
dc.b $8D,$40,$F0 ; sta SCC_Ctl <37>
dc.b $AD,$40,$F0 ; lda SCC_Ctl <37>
dc.b $58 ; cli turn on interrupts <37>
dc.b $6A ; ror a test the all sent bit, bit 0 <37>
dc.b $90,$F3 ; bcc @wait_more <37>
dc.b $7C,$88,$5E ; jmp (ControlDispatch,x) <37>
; ControlDispatch at $5E88 = $56aa(base) + $7DE(offset) <37>
; fixes ctrl calls to wait for all sent from SCC before executing <37>
@b10end dc.b $08,$D6 ; offset to this patch <37>
dc.b @b11end-@b11 ; number patchbytes <37>
; <37>
; ctsFlag = 0 on input. Acc holds RRO value <37>
@b11 dc.b $29,$A0 ; and #$A0 isolate DTR and break bits <37>
dc.b $85,$AD ; sta holdRR0 $aa(base) + $17(offset) <37>
dc.b $29,$20 ; and #$20 is DTR asserted? <37>
dc.b $F0,$02 ; beq @1 yes, then CTSFlag stays 0 <37>
dc.b $C6,$C1 ; dec CTSFlag no, then CTSFlag goes to $FF CTSFlag at $aa(base) + $17(offset)
dc.b $4C,$AE,$57 ;@1 jmp backToCode at $57AE = $56aa(base) + $104 offset <37>
; adds external clocking control into bit 6 of the
; CtlOptions byte for control call 16
@b11end dc.b $08,$e3 ; offset to this patch
dc.b @b13end-@b13 ; number of patchbytes
@b13 dc.b $a5,$c8 ;lda CtlOptions get old clk bit $aa(base)+$1e(offset)
dc.b $29,$40 ;and #clkMsk bit 6
dc.b $aa ;tax
dc.b $ad,$e4,$02 ;lda C16_CtlOptions get new byte $200(base)+$e0(msg#)+$04
dc.b $a8 ;tay
dc.b $29,$40 ;and #clkMsk bit 6
dc.b $85,$c8 ;sta CtlOptions $aa(base)+$1e(offset)
dc.b $8a ;txa
dc.b $c5,$c8 ;cmp CtlOptions is old clock bit same as new? $aa(base)+$1e(offset)
dc.b $d0,$05 ;bne @switchIt nope, switch clk mode
dc.b $84,$c8 ;@out sty CtlOptions store new byte $aa(base)+$1e(offset)
dc.b $4c,$d4,$59 ;jmp DoControlEvent_Return $56aa(base) +$32a(offset)
dc.b $98 ;@switchIt tya
dc.b $0a ;asl shift into minus bit
dc.b $30,$14 ;bmi @ext
dc.b $a9,$50 ;@int lda #intClkSrc set int clk params
dc.b $8d,$6c,$5e ;sta WR11_Data $56aa(base) +$7c2(offset)
dc.b $a9,$01 ;lda #BRGEnbl
dc.b $8d,$72,$5e ;sta WR14_Data $56aa(base) +$7c8(offset)
dc.b $ad,$62,$5e ;lda WR4_data set clock divide to 16 $56aa(base) +$7b8(offset)
dc.b $09,$40 ;ora #dvd16Msk clock divide bit is bit 6
dc.b $8d,$62,$5e ;sta WR4_data in WR4 $56aa(base) +$7b8(offset)
dc.b $80,$12 ;bra @load
dc.b $a9,$28 ;@ext lda #extClkSrc set ext clk params
dc.b $8d,$6c,$5e ;sta WR11_Data $56aa(base) +$7c2(offset)
dc.b $a9,$00 ;lda #BRGDsbl
dc.b $8d,$72,$5e ;sta WR14_Data $56aa(base) +$7c8(offset)
dc.b $ad,$62,$5e ;lda WR4_data set clock divide to one $56aa(base) +$7b8(offset)
dc.b $29,$BF ;and #dvdOneMsk clock divide bit is bit 6
dc.b $8d,$62,$5e ;sta WR4_data in WR4 $56aa(base) +$7b8(offset)
dc.b $5a ;@load phy ; save the control byte
dc.b $64,$b8 ;stz HWHSenable disable hardware handshaking $aa(base)+$0e(offset)
dc.b $20,$49,$5e ;jsr DoInitSCC $56aa(base) +$79f(offset)
dc.b $7a ;ply
dc.b $80,$c8 ;bra @out
; patch to set bit 3 of AsyncErr if break received
@b13end dc.b $09,$2d ; offset to this patch
dc.b @b15end-@b15 ; number of patchbytes
@b15 dc.b $8a ;txa a=changed bits
dc.b $30,$03 ;bmi @change break changed
dc.b $4c,$02,$5e ;@done jmp ExtStatEnd $56aa(base) +$758(offset)
dc.b $a5,$ad ;@change lda LastRRO get break value $aa(base)+$03(offset)
dc.b $30,$05 ;bmi @post break was set
dc.b $ad,$42,$f0 ;lda SCC_Data break unset, discard null
dc.b $80,$f4 ;bra @done
dc.b $a9,$08 ;@post lda #$08 set bit 3
dc.b $24,$bc ;bit ResetAsyncErr has host read stats $aa(base)+$12(offset)
dc.b $10,$04 ;bpl @unread
dc.b $64,$bd ;stz AsyncErr $aa(base)+$13(offset)
dc.b $64,$bc ;stz ResetAsyncErr $aa(base)+$12(offset)
dc.b $05,$bd ;@unread ora AsyncErr $aa(base)+$13(offset)
dc.b $85,$bd ;sta AsyncErr $aa(base)+$13(offset)
dc.b $80,$e4 ;bra @done
; patch to set clock divide bits for WR4 and disable HWHS for external clocking
@b15end dc.b $09,$4c ; offset to this patch
dc.b @b17end-@b17 ; number of patchbytes
;acc=%0400xxxx default to divide-by-16
@b17 dc.b $da ;phx save reg
dc.b $aa ;tax save acc
dc.b $a5,$c8 ;lda CtlOptions are we ext clk'd? $aa(base)+$1e(offset)
dc.b $0a ;asl shift ext clk bit into minus bit
dc.b $30,$03 ;bmi @ext yes, go fix clk dvd bits
dc.b $8a ;@int txa no, just restore acc
dc.b $80,$03 ;bra @done
dc.b $8a ;@ext txa restore acc
dc.b $29,$0f ;and #$0f fix clk dvd bits to div-by-one
; dc.b $64,$b8 ;stz HWHSenable disable hardware handshaking $aa(base)+$0e(offset)
dc.b $fa ;@done plx restore reg
dc.b $8d,$62,$5e ;sta WR4_Data and write out WR4 value $56aa(base) +$7b8(offset)
dc.b $4c,$26,$5e ;jmp FinishInitSCC and finish up $56aa(base) +$77c(offset)
; patch to disable CTS interrupts if we get them too fast
@b17end dc.b $09,$60 ; offset to this patch
dc.b @b19end-@b19 ; number of patchbytes
@b19 dc.b $a5,$dd ;lda CTSCount exceeded 5 transitions in 1 ms? $aa(base)+$33(offset)
dc.b $c9,$05 ;cmp #5
dc.b $90,$0c ;bcc @fixTime no, then fix the time
dc.b $a9,$0f ;lda #15 yes, then disable CTS interrupts
dc.b $8d,$40,$f0 ;sta SCC_Ctl write to WR15
dc.b $a9,$80 ;lda #$80 bit 5 clear to disable CTS ints
dc.b $8d,$40,$f0 ;sta SCC_Ctl
dc.b $80,$12 ;bra @out go finish in ROM
;@fixTime
dc.b $a5,$de ;lda LastTime get last count (remember it's a countdown timer) $aa(base)+$34(offset)
dc.b $ed,$11,$f0 ;sbc TimerCounterH time elasped > threshold?
dc.b $c9,$08 ;cmp #threshold threshold is 1 ms≈ 8 ticks
dc.b $90,$07 ;bcc @update no, just increment <138>
dc.b $ad,$11,$f0 ;lda TimerCounterH yes, set new last time
dc.b $85,$de ;sta LastTime $aa(base)+$34(offset)
dc.b $64,$dd ;stz CTSCount and restart count $aa(base)+$33(offset)
;@update inc the transition count
dc.b $e6,$dd ;inc CTSCount $aa(base)+$33(offset)
;@out
dc.b $64,$c1 ;stz CTSFlag do stuff we stomped on in overpatch $aa(base)+$17(offset)
dc.b $a5,$ad ;lda RRO $aa(base)+$03(offset)
dc.b $4c,$e4,$5d ;jmp BackToROM finish up in ROM $56aa(base) +$73a(offset)
; patch to close to time-out on the all sent loop
@b19end dc.b $09,$8b ; offset to this patch
dc.b @b22end-@b22 ; number of patchbytes
@b22 dc.b $a5,$FF ;ldx #$FF load up $FFFF for timeout loop
dc.b $c9,$FF ;ldy #$FF 24 cycles * .5 us/cycle * 64K ≈ .8 seconds
dc.b $a9,$01 ;@loop lda #1 read from RR1
dc.b $8d,$40,$f0 ;sta SCC_Ctl
dc.b $ad,$40,$f0 ;lda SCC_Ctl
dc.b $6a ;ror get all sent bit in carry
dc.b $b0,$06 ;bcs @done if allsent, then outta here
dc.b $ca ;dex not allsent, so keep waiting
dc.b $d0,$f2 ;bne @loop
dc.b $88 ;dey
dc.b $d0,$ef ;bne @loop
dc.b $4c,$24,$59 ;@done jumpBacktoClose $56aa(base) +$27a(offset)
; patch to start the IOP timer
@b22end dc.b $09,$a3 ; offset to this patch
dc.b @b24end-@b24 ; number of patchbytes
@b24 dc.b $9c,$2c,$f0 ;stz DMA_CntHi do code we stomped with patch
dc.b $a9,$ff ;lda #$FF
dc.b $8d,$11,$f0 ;sta TimerCounterH get the timer started (just need to write to it)
dc.b $4c,$45,$57 ;@done jumpBacktoOpen $56aa(base) +$09b(offset)
@b24end dc.w 0 ; filler
;_______________________________________________________________________
;
; Routine: IOPMoveData
; Inputs: A0 - pointer to IOPMoveInfo paramater block
; Outputs: D0 - Result Code (NoErr/paramErr)
; Destroys: A0, A1, D0, D1, D2
; Calls: CopyToIOP, CopyFromIOP, CompareWithIop
; Called by: OsTrap Dispatch Table
;
; Function: Moves, or compares data between the IOP and the Host
; memories, using the parameters inthe IOPMoveInfo parameter
; block. Also has a special mode to apply patches to IOP
; memory as an atomic operation.
;
;_______________________________________________________________________
with IOPMoveInfo
IOPMoveData
; We can use the new protection scheme, if the first two instructions in the <115>
; patch are a bra.s followed by the jump to the old rom address.
bra.s @protection
@NoPatch
BackToTrap oldIOPMoveData ; no, then just execute ROM Code
@protection
; are we coming from the IOP serial driver open call?
cmpRA From_IOPOpenCall,OSTrapReturnAddressDepth(sp)
bne.s @NoPatch
@chkA lea DrvrAFix,a1 ; get address of our patchbytes
cmpi.w #DrvrAPicAddr,imIOPAddr(a0)
beq.s @doPatch
@chkB lea DrvrBFix,a1 ; get address of our patchbytes
cmpi.w #DrvrBPicAddr,imIOPAddr(a0)
bne.s @noPatch ; not our drivers? well, don't patch then
@doPatch
; Call the ROM to download the unpatched image
_IOPMoveData
; now patch the downloaded driver. Each section of patch bytes
; is preceded by an offset word and a count byte.
; a2 has start addr of our patch bytes.
moveq #numpatches-1,d1 ; number of patches (minus 1 for dbra)
move.w imIOPAddr(a0),d2 ; get base addr of downloaded driver
moveq #0,d0 ; for additions
move.w d0,imByteCount(a0) ; clear out high byte of count
@patchloop
move.w d2,d0 ; get base addr of downloaded driver
add.w (a1)+,d0 ; add in offset to patch start
move.w d0,imIOPAddr(a0) ; set dest addr for patchbytes
move.b (a1)+,imByteCount+1(a0) ; number patchbytes
move.l a1,imHostAddr(a0) ; set source addr of patchbytes
adda.w imByteCount(a0),a1 ; increment ptr past patchbytes
_IOPMoveData ; download the patch bytes
dbra d1,@patchloop ; go on to next patch
; note that when dbra expires, d0 will contain output for last IOPMove data
; performed, which is an approximation of what should be in d0
; note also that we've trashed the IOPMgr PB fields, but since the driver
; never refers to them again, and in the interest of STAYING SMALL, we'll
; ignore it.
rts
endwith
endproc
;
;
; End of Patch To IOPMoveData Trap to Fix IOP Serial Driver Control Call Bug
;____________________________________________________________________________ EH <33>
;____________________________________________________________________________
NewFLineRoutine PROC EXPORT
EXPORT OldFLineRoutine
cmp.w #$002C,6(sp) ;make sure that this is our stack frame. If not
bne.s OldFLineRoutine ;..then jump thru the old exception vector
MOVEM.L A0/D0,-(SP) ; Save these two registers <107>
move.l 8+2(sp),a0 ;get the address of the instruction word that caused
move.w (a0),d0 ;..this exception. Then copy the word into DO
and.w #%0000111000000000,d0 ;get just the co-processor ID from the instruction
cmp.w #%0000001000000000,d0 ;if its not one, then it isnt a FPU instruction
bne.s stackError ;..so return thru the old FPU replacement routine
lea continue,a0 ;change the saved return address to our continuation
move.l a0,8+2(sp) ;..point and return out of exception mode.
MOVEM.L (SP)+,A0/D0 ; Restore the regs <107>
rte
continue move.w #dsNoFPU,d0 ;this displays the dialog that lets the user
_SysError ;..return to the finder (FPU type)
stackError MOVEM.L (SP)+,A0/D0 ; Restore the regs <107>
OldFLineRoutine JMP $12345678 ; This gets filled in at install time <107>
ENDP
;____________________________________________________________________________
;----------------------------------------------------------------------------------------------------
; This routine will read the Time LowMem global without
; issuing the call to Egret. Egret will keep the time updated
; in the background without needing system intervention. The
; Egret will post a unsolicited time packet which will update the
; LowMem global when it is not able to post the Tick packet
; within one second.
;----------------------------------------------------------------------------------------------------
RdDateTimePtch PROC EXPORT
move.l Time,(a0) ; return the time to the caller
clr.w d0 ; return no error <74>
rts
ENDP
;----------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------
; This patch fixes a bug in Egret Manager TickHandler routine. <89><101>
; The routine will store the 32 bit time passed by Egret to the
; system if the packet is a ReadRealTime into TIME lowmen.
; Decrements the lowmem Time by one to compensate for the interrupt
; Handler incrementing it by one and then calls the LVL1DT interrupt
; handler.
; If the packet is a tick packet then it calls LVL1DT to increment the
; time setting and check the alarm state.
;
; Entry:
; A1.l = Points at Response data buffer At Flags byte:
;
; +---------+----------+---------+---------+---------//-------+
; | Attn | Pkt Type | Flags | Pkt Cmd | 8 Bytes data Max |
; +---------+----------+---------+---------+---------//-------+
;
; A2.l = Points at Egret Manager Globals
;
;----------------------------------------------------------------------------------------------------
TickHandler PROC EXPORT
WITH respPacket,EgretGlobals
subq.l #2,a1 ; point to the beginning of the Response data buffer
cmpi.b #TickPkt,RespType(a1) ; Check the Packet type
beq.s @CallLVL1DT ; If tick packet just call LVL1DT handler
;
; The packet was a readTime packet from Egret. Update the Time lowmem and
; adjust it to compensate for the increment in the LVL1DT handler.
;
move.l RespData(a1),Time ; write the new time in lowmem TIME
subq.l #1,Time ; adjust to compensate for increment in LVL1DT
;
; JUMP to routine pointed to by the Contents of LVL1DT
;
@CallLVL1DT
move.l VIA,a1 ; point to the VIA
move.l LVL1DT,a0 ; get vector
jmp (a0)
ENDWITH
ENDP
;----------------------------------------------------------------------------------------------------
; This patch saves the processor status register, calls the <101> SAM
; ShiftRegIrq routine in Egret Manager and then restore the
; status register and exits.
;----------------------------------------------------------------------------------------------------
EgretIRQPtch PROC Export
EXPORT Vector_Hold
move.w sr,-(sp) ; save the status register
@IrqJmp jsr $10000000 ; this JSR will call the routine pointed to by the old
; contents of LVL1DT+8 vector (ShiftRegIrq)
move.w (sp)+,sr ; restore the status register
rts
Vector_hold equ @IrqJmp+2 ; point to the operand field
ENDP
;----------------------------------------------------------------------------------------------------
; This patch fixes possible loss of data to the SCC by calling <101> SAM
; the Poll Proc when SCC data is available.
;----------------------------------------------------------------------------------------------------
EgretDispatchPtch PROC Export
EMJmpAddr equ $14868 ; Offset added to Contents of Rombase for jmp back to Rom Egret Manager
; <104> removed declarations for Pollstack,PollProc, and HiIntMsk
with EgretPB, EgretGlobals
bsr CheckPacket ; Validate the Packet type & command byte
bne @done ; Exit if Error packet
movea.l EgretBase,a2 ; a2 gets ptr to globals
movea.l VIA,a1 ; a1 points to VIA base
cmpi.b #specialPkt,pbCmdType(a0) ; is this a special command?
bne.s @EgretRestart
move.l a0,ADBpb(a2) ; yes, is to set the ADB param block (for autopoll data).
bra @done
@EgretRestart
move.w sr,-(sp) ; save SR
ori.w #hiIntMask,sr ; mask interrupts
btst.b #xcvrSes,vBufB(a1) ; does Egret want to abort?
beq.s @abort ; yes, wait for it to go away
bset.b #busy,flags(a2) ; not an abort, mark that we're busy.
beq.s @sendPackType ; we were not busy before, so try to send the first byte
@abort move.w (sp)+,sr ; we were busy, enable interrupts
bsr pollByte ; poll shift reg, calling handler if interrupts masked
bra.s @EgretRestart ; and keep waiting for busy to go away...
@sendPackType ; interrupts masked here
bset.b #sysSes,vBufB(a1) ; assert System Session (we're starting command packet)
bset.b #SRdir,vACR(a1) ; switch to output
move.b pbCmdType(a0),vSR(a1) ; send command packet to shift reg
bset.b #viaFull,vBufB(a1) ; tell Egret we sent it
;_________________________
; If PollProc exists, Poll the SCC and save any available data
; When the shift register irq comes in call the PollProc
; then process the shift register irq data
;
movem.l d0/d1/a0-a4/a6,-(sp) ; save some registers
lea @zero, a3
move.l sp,PollStack ; Pointer to buffer for polled bytes
btst.b #0,SccIopFlag ; Check if we are in IOP mode (On Eclipse...)
beq.s @wait
tst.l PollProc ; Check for a Poll Proc available
beq.s @wait ;
movea.l SccRd,a3 ; SCC may have data to get
movea.l a3,a6
addq.l #Actl,a3 ; Point to data available register (RR0)
addq.l #AData,a6 ; Point to the SCC data register
@wait btst.b #RxCa,(a3) ; Test for SCC data available
beq.s @2
move.b (a6),-(sp) ; Push the data on the stack
@2 btst.b #vShift,vIFR(a1) ; now wait for shift reg IRQ
beq.s @wait
cmpa.l PollStack,SP ; Is there any poll data
beq.s @NoSCCData
;
; We have SCC data and a Poll Proc to call. Go call it
;
pea @NoSCCData ; Return addr for PollProc
move.l PollProc,-(SP) ; Point to the PollProc
rts ; Call the PollProc
@zero dc.w 0
@NoSCCData movem.l (sp)+,d0/d1/a0-a4/a6 ; restore work registers
@VsrIrq
btst.b #xcvrSes,vBufB(a1) ; did Egret abort?
bne.s @accepted ; no, then it will accept our packet
bclr.b #SRdir,vACR(a1) ; yes, switch back to input
bclr.b #sysSes,vBufB(a1) ; ack the abort
bsr.s CallShiftRegIRQ ; handle it
bra.s @abort ; and wait
@accepted
JmpROM EMJmpAddr ; Jump back into Rom Egret Manager <107>
@done moveq #0,d0 ; no errors for now
rts
;________________________________________________________________________________________________
CallShiftRegIRQ
movem.l a0-a3/d0-d3,-(sp) ; save regs like interrupt handler does
movea.l Lvl1DT+8,a0 ; get the shift reg IRQ handler
jsr (a0) ; call it
movem.l (sp)+,a0-a3/d0-d3 ; restore regs
rts
;________________________________________________________________________________________________
; Routine: PollByte
;
; Function: This routine checks to see if level 1 interrupts are masked, exits if not.
; If masked, it polls the flag register for a shift reg interrupt, and
; calls the handler if found.
;
; Inputs: a1 - VIA base ptr
; a2 - globals pointer
;
; Outputs: none
;
; Destroys: d0,d1
;________________________________________________________________________________________________
PollByte
move.w sr,d0 ; get 68xxx interrupt mask
andi.w #hiIntMask,d0 ; are we at interrupt level?
beq.s @exit ; no, just exit
btst.b #vShift,vIFR(a1) ; yes, poll the shift reg
beq.s @exit ; no shift reg interrupt, return
bsr.s CallShiftRegIRQ ; yes, handle it
@exit rts
;________________________________________________________________________________________________
;
; Validate the Packet type and Command if Pseudo Pkt.
;
; If an error is encountered with the packet a error packet will be
; built in the pbParam area of the parameter block as if Egret had
; returned the packet. Also, the pbResult field will contain a System
; error code for bad parameter block format.
;
; Entry: A0 = Parameter block pointer
;
; Exit: sr.Z = 0 if valid packet/pseudocmd nonzero otherwise
;
_________________________________________________________________________________________________
CheckPacket
cmp.b #SpecialPkt,pbCmdType(a0) ; could be an ADB initialization packet
beq.s @OkExit
cmp.b #ErrorPkt,pbCmdType(a0) ; ADB ($00) and Pseudo ($01) only
bhi.s @BadPkt ; Invalid packet
cmp.b #PseudoPkt,pbCmdType(a0) ; Check for pseudo commands
bne.s @OkExit ; On Pseudo Packets check the command
cmp.b #MaxPseudoCmd,pbCmd(a0) ; Validate the Pseudo command number <bg>
bls.s @OkExit
@BadPseudo move.w #InvPseudo,pbParam(a0) ; report a pseudo command error
move.w pbCmdType(a0),pbParam+2(a0) ; we are faking an error packet
bra.s @ErrorExit
@BadPkt move.w #InvPkt,pbParam(a0) ; report invalid packet error
move.w pbCmdType(a0),pbParam+2(a0) ; we are faking an error packet
@ErrorExit move.w #paramErr,pbResult(a0) ; parameter error in result field
bra.s @Exit
@OkExit move.w #0,pbResult(a0) ; So far packet OK
@Exit rts
ENDWITH
ENDPROC
;------------------------------------------------------------------
;__________________________________________________________________________ <101> <BEGIN>
; PACK 4 overpatch code for MC68020 software SANE to correct binary-to
; decimal conversion bug which may cause an extra byte to be written to
; the destination decimal record.
;
; Copyright © 1990 Apple Computer, Inc. All rights reserved.
; Written by: Jon Okada.
;
; The overpatch code intercepts every PACK 4 call and determines if the SANE
; operation requested is a binary-to-decimal conversion. If it is not,
; control is passed to the original, underlying SANE engine. If it is,
; the SANE engine is called with output directed to a local decimal record,
; which is copied to the user's destination decimal record, taking care not
; to exceed the desired precision.
;
; Entry point is FP020PATCH. Upon entry, the stack is as follows:
;
; &return < SANE opword (2 bytes) < &dst < &src < &src2,
;
; where &src and &src2 may not be present, depending on the SANE operation
; requested by the caller.
PACK4inROM equ $73940 ;Offset from ROMBase to non-fpu PACK4.
FP020Patch PROC
MOVE.L D0,-(SP) ; STACK: D0sv < &ret < opcode < etc.
MOVEQ #$1F,D0 ; D0 <- opcode mask
AND.W 8(SP),D0 ; isolate opcode
CMPI.B #$0B,D0 ; binary-to-decimal conversion?
MOVEM.L (SP)+,D0 ; (restore register)
BEQ.S @DOBINDEC ; yes
jmpROM PACK4inROM ; Let PACK4 handle call.
;
; Binary-to-decimal conversion is accomplished via the underlying PACK 4
; implementation, but the result is directed to an intermediate buffer
;
@DOBINDEC:
LINK A6,#-28 ; reserve space for decimal record
MOVEM.L D0/A0-A1,-(SP) ; save registers
LEA -28(A6),A0 ; A0 <- addr of local decimal record
MOVE.L 18(A6),-(SP) ; push &src2
MOVE.L 14(A6),-(SP) ; push &src
MOVE.L A0,-(SP) ; push local decimal record addr
MOVE.W 8(A6),-(SP) ; push opword
jsrROM PACK4inROM ; call pack4.
MOVEA.L 10(A6),A1 ; A1 <- &dst
MOVE.L (A0)+,(A1)+ ; copy sign/exp to dst record
CLR.W D0 ; clear counter
MOVE.B (A0)+,D0 ; read decimal string length
MOVE.B D0,(A1)+ ; write it to dst record
SUBQ #1,D0 ; initialize loop counter
@1:
MOVE.B (A0)+,(A1)+ ; copy string to dst record
DBRA D0,@1
MOVEM.L (SP)+,D0/A0-A1 ; restore registers
UNLK A6 ; unlink
MOVE.L (SP),14(SP) ; move return addr up
ADDA.W #14,SP ; kill arguments on stack
RTS ; return to caller
ENDP
;__________________________________________________________________________ <101> <END>
;__________________________________________________________________________ <xyz> <cch 8/6/91>
; Routine: GetPageDescPatch
;
; Function: This routine is a patch to the GetPageDescPatch, which is
; an internal routine called by LockMemory and WriteProtectMemory.
; The bug it fixes is that the page descriptor pointer is
; converted from physical to logical twice in GetPageDesc.
; This patch is only needed on 68030 machines with ROM version $67C,
; sub-version 1.5 without VM.
;
; How: This is a come-from patch to the _Gestalt trap, which is
; called by the GetMMUInfo routine in GetReal.a. If the
; come-from patch is triggered, and the GetPageProc flag on
; the stack is set, the return address from GetPageDescProc is
; replaced with the address of a routine which fixes the
; result and returns to the original caller.
;
; Note: This patch is NOT reentrant. This is OK, however, since
; _LockMemory may not be called at interrupt level, which is
; the only way reentrancy could occur with this routine.
;
; Inputs: A0/D0 - parameters to gestalt
; (sp).L - address routine was called from plus 2
;
; Outputs: none
;
; Destroys: a1
;__________________________________________________________________________
GetMMUInfoPatchAddr EQU $40886d1e ; return address when Gestalt is called
SetCacheInhibitAddr EQU $408873a2 ; return address when correct swapMMUMode is called
getPageDesc EQU 7 ; getPageDesc selector
GetPageDescPatch PROC
EXPORT MemDispPatch
cmp.l #GetMMUInfoPatchAddr,$18(sp) ; check addr _Gestalt was called from
bne.s @skipPatch ; IF we had a match THEN
cmp.w #getPageDesc,$4e(sp) ; check if user wants the page descriptor
bne.s @skipPatch ; IF user wants a page descriptor THEN
lea GetPageDescRetAddr,a1 ; where to save getPageDesc return addr
move.l $50(sp),(a1) ; save return address to getMMUInfo
lea fixResult,a1 ; get address of routine to fix result
move.l a1,$50(sp) ; stuff it in the stack frame
; ENDIF
; ENDIF
@skipPatch BackToTrap origGestalt ; jump to original Gestalt trap
;-----------------
; getPageDesc fix up routine
;-----------------
fixResult
sub.l Phys2Log,a0 ; fix up result
jmp ([GetPageDescRetAddr]) ; jump back into normal code stream
GetPageDescRetAddr ; return address for getMMUInfo
dc.l $87654321
;__________________________________________________________________________ <10> <cch 8/6/91>
; Routine: MemDispPatch
;
; Function: This routine is a patch to the _VM trap. It fixes a bug
; in the Terror ROM which occurs when the page the stack is
; is is marked uncacheable in the MMU tables, then a subsequent
; PFLUSH'd is executed with data still in the cache.
;
; How: This is a simple patch which is installed only on 68030's when
; VM is not installed on Terror ROMs, version $67C, sub-version 1.5.
; It disables the data cache during all _VM calls with the exception
; of _GetPhysical.
;
; Inputs: A0-A1/D0 - parameters to _VM call
;
; Outputs: none
;
; Destroys: d1
;__________________________________________________________________________
GetPhysSel EQU 5
MemDispPatch
cmp.b #GetPhysSel,d0 ; check for get physical selector
beq.s @skipPatch ; IF this is anything but getPhysical THEN
movec cacr,d1 ; get cache value
move.w d1,-(sp) ; save cache state on stack
andi.w #$001f,d1 ; we want to save current instruction cache bits
addi.w #$0800,d1 ; value to flush data cache
movec d1,cacr ; flush and disable data cache
jsrTrap origMemDisp ; do original call
move.w (sp)+,d1 ; get original cache state
movec d1,cacr ; reenable caches
rts ; return to caller
@skipPatch ; ELSE
BackToTrap origMemDisp1 ; do original call
; ENDIF
ENDP
;__________________________________________________________________________ <10> <end>
;__________________________________________________________________________ <13><cch 8/28/91>
; Routine: FP68k patch for Terror-based 030 machines
;
; Inputs: stack has: <RET> <OPWORD> <ADRS1> <ADRS2> <ADRS3>
;
; Destroys: d1
;__________________________________________________________________________
QADDX EQU $408EC1E4
FP881CASE EQU $408EB50C
OMEGA881BASE EQU $408EB1FC
OPERRHANDLER EQU $408EDCE6
FP68kPatch PROC EXPORT
tst.b MMU32bit ; Are we in 24 bit mode?
beq.s @inMode24 ; -> Yes
@inMode32 cmp.l #$40800000,(SP) ; check address we're patching
bhs.s @dontBackpatch ; IF we're being called from ROM THEN
@CallOld BackToTrap origFP68k ; do original call
@inMode24 move.l D0,-(SP) ; save D0
move.l 4(SP),D0 ; get Return address in D0
and.l MaskBC,D0 ; poor man's strip address
cmp.l #$00800000,D0 ; Is the PC less than ROM?
movem.l (SP)+,D0 ; Restore D0
blo.s @CallOld ; -> Yes, Call the old Backpatch routine
; No. Fall into DontBackPatch
@dontBackpatch ; ELSE
SUBQ #2,SP ; MAKE A HOLE
MOVEM.L D0/A0,-(SP) ; SAVE 2 REGISTERS
LEA QADDX,A0 ; ALWAYS STORE &QADDX INTO ITS JUMP ISLAND
MOVE.L A0,$0B6E ; HOME SO TRAPS HAVE A POINT OF REFERENCE
MOVE.W 14(SP),D0 ; GET OPWORD INTO D0
ROL.W #8,D0 ; XXXX383F --> XXXX3F38 ... SWAP BYTES
LSL.B #2,D0 ; XXXX3F38 --> XXXX3FE0 ... SCRUNCH TOGETHER
BFEXTS D0{18:9},D0 ; D0 ::= INDEX := 8 * OPCODE + FORMAT
MOVE (FP881CASE,D0*2),D0 ; DO := OFFSET AT INDEX IN TABLE
LEA OMEGA881BASE,A0 ; GET OMEGABASE
ADD.L D0,A0 ; GO DO IT
MOVE.L 10(SP),12(SP) ; SLIDE RETURN ADDRESS ON TOP OF OPWORD
MOVE.L A0,8(SP) ; FILL RTS HOLE PROVIDED ABOVE
LEA OPERRHANDLER,A0 ; INSTALL OPERR TRAP HANDLER INTO
MOVE.L A0,$0D0 ; LOW-MEM VECTOR (SEE TABLE 7-6 882 MAN)
FMOVE.L FPCR,D0 ; ENABLE OPERAND ERROR TRAPPING
BSET #13,D0
FMOVE.L D0,FPCR
MOVEM.L (SP)+,D0/A0 ; RESTORE 2 REGISTERS
RTS ; DISPATCH
; ENDIF
ENDP
;__________________________________________________________________________ <13>
;----------------------------------------------------------------------------------------------------
;=========================================================================================
;=========================================================================================
;= =
;= END OF RESIDENT PATCH CODE SECTION =
;= =
;=========================================================================================
;=========================================================================================
EndOfPatch PROC EXPORT
;=========================================================================================
;=========================================================================================
;= =
;= PATCH INSTALL CODE IS BELOW THIS POINT =
;= =
;= Patches may fall into two different categories: =
;= 1. Required for both the Mac OS and A/UX =
;= 2. Required only for the Mac OS =
;= =
;= Macintosh OS-only patches are usually characterized by code which touches hardware =
;= directly, or patches for traps not supported by A/UX. The safest thing to do when =
;= in doubt is to check with your friendly A/UX representative (only a phone call =
;= away!). A/UX loads all patches, but conditionalizes the installation code. The =
;= first section of installation code which follows, is for patches required on both =
;= Mac OS and A/UX. The second section (further down), is for Mac OS-only patch =
;= installation code. =
;= =
;= To find a place to add your Mac OS and A/UX patch, search for 'EndBothSection' =
;= =
;= To find a place to add your Mac OS only patch, search for 'EndMacSection' =
;= =
;=========================================================================================
;=========================================================================================
PatchInit MAIN Export
Import EndOfPatch
Import StartPatch
Import Cutback
Import FixupTbl ; added FixupTbl <24July89smb>
MOVE.L D1,-(SP) ; Save our handle <1.1-4april89-CEL>
;____________________________________________________________________________
; Fixup patch addresses
;
; The Fixing up of addresses generated by the CMPRA, JSRROM & JMPROM
; Breaks down as follows:
;
; Addressing High Byte in Action
; mode: instruction:
; ---------- ------------ ------
; 24 bit NZ Do not alter the address in the instruction.
; Used with CMPRA to a ROM Resource.
; 32 bit NZ Mask out 12 high bits from the address
; in the instruction, leaving a ROM offset
; Then add in ROMBase.
; either Zero Normal Case. Add ROMBase to the address
; in the instruction.
;
; Registers:
; D0: Address Size Flag. Pos: 24 bit mode; Neg: 32 bit Mode
; D1: Entry from table of offsets of locations to be fixed up
; D2: (RomBase)
; A0: Pointer into table of offsets of locations to be fixed up.
; A1: Base of fixup table; also location from which offsets are computed.
move.l RomBase, D2
moveq #-1, D0
_StripAddress
lea FixupTbl, A0
move.l A0, A1
FixUpLooP move.l (A0)+, D1
beq.s @1
tst.b 0(A1, D1.L)
beq.s @AddIt
tst.l D0 ; If Address has any high bits set
bpl.s FixUpLoop ; 24 Bit mode; Dont alter this one.
and.w #$f, 0(A1, D1.L); 32 Bit Mode; Clear High 12 bits.
@AddIt add.l D2, 0(A1, D1.L) ; Normal Case: Add in ROMBase
bra.s FixUpLoop
@1
move.l jCacheFlush, a0 ; flush caches (make sure tables are consistent)
jsr (a0)
;=========================================================================================
;=========================================================================================
;= =
;= PATCH INSTALLATION CODE FOR BOTH MAC OS AND A/UX STARTS HERE =
;= =
;= Please be neat and follow the format =
;= =
;=========================================================================================
;=========================================================================================
;———————————————————————————————————————————————————————————————————————————— GGD <8.4>
; Fix _StripAddress to not check the MMStartMode bit of MMFlags at runtime,
; because the memory manager changes that bit when accessing ROM resources,
; and if an interrupt occurs while the bit is changed, calling _StripAddress
; from an interrupt routine (eg VBL task) might not work correctly. To correct
; this, we will install either a 24 or 32 bit version of _StripAddress once
; and eliminate the runtime check, making the code both faster and correct.
; NOTE: This is installed early in the patch file to reduce the chances of
; encountering this bug while installing the remaining patches.
StripAddressOld equ $0000D764 ; ROM offset of old StripAddress
StripAddress24 equ $0000D76C ; ROM offset of new 24 bit mode version
StripAddress32 equ $0000D770 ; ROM offset of new 32 bit mode version
FixStripAddress
lea OsTable+($55*4),a0 ; point to dispatch table entry (trap A055)
CmpRA StripAddressOld,(a0) ; see if it already patched (by A/UX maybe?)
bne.s @Done ; if already patched, don't patch again
moveq.l #StripAddress24-StripAddressOld,d0 ; get adjustment for 24 bit mode
btst.b #Systemis24bit,SystemInfo ; what kind of OS are we running
bne.s @patchIt ; if 24 bit OS, change it to 24 bit StripAddress
addq.l #StripAddress32-StripAddress24,d0 ; if 32 bit, adjust offset to 32 bit entry
@patchIt add.l d0,(a0) ; update the dispatch table entry
@done ; all done <8.4>
;———————————————————————————————————————————————————————————————————————————— <8>
; The TERROR ROM does not distinguish between a Tim and a Tim LC. We have to.
; We need to fix boxFlag if we're running on a Tim LC (a Tim w/o an FPU)
;
MOVE.L ROMBase,A0 ; Get Bas o ROM
CMPI.B #TERRORMinorVers,18(A0) ; Is this a TERROR 67C ROM?
BNE.S @DoneTimLC ; -> Nope, don't futz with anything
CMPI.B #boxPowerBook170,boxFlag ; Does the ROM think this is a Tim? <146>
BNE.S @DoneTimLC ; -> No, don't assume anything. Bail out.
MOVE.W HwCfgFlags,D0 ; Get them Hardware Config Flags
BTST.L #hwCbFPU,D0 ; Does we gots an FPU?
BNE.S @DoneTimLC ; -> Yes, we're not on a Tim LC. Exit.
BTST.L #hwCbPwrMgr,D0 ; Do we have a PowerMgr?
BEQ.S @DoneTimLC ; -> No. This is not a Portable of any kind
; We're on a TERROR $67C ROM with a PwrMgr and no FPU.
MOVE.B #boxPowerBook140,boxFlag ; We're on a Tim LC. Stuff the right boxFlag <146>
@DoneTimLC
;———————————————————————————————————————————————————————————————————————————— <130><131><8><9>
; The GestaltFuction.a file is used to build a ptch for machines without
; Gestalt in ROM, but it also contains fixes and improvements that are not
; in the ci ROMs OR in the GestaltPatches.a file... The changes are not
; trivial, so were punting and loading the Gestalt ptch on ci ROMs, too...
;
; Before we do, though, we throw away any storage that Gestalt has allocated.
;
move.l ExpandMem,A1
move.l ExpandMemRec.emGestalt(A1),A0 ; Get the ROM Gestalts Storage pointer
move.l A0,-(SP) ; Save the Ptr on the Stack
move.l (A0),-(SP) ; Save Gestalt's Selector table handle
PtchInst 5 ; Reinstall all of Gestalt ptch
move.l (SP)+,A0 ; Get the old Selector Table Handle
_DisposHandle ; Throw the storage away!
move.l (SP)+,A0 ; Get the storage Ptr
_DisposPtr ; Make it go away too!
;____________________________________________________________________________ NJC <1.6>
; ci Quickdraw ptch added 1/16/90 KON
;
PtchInst 26 ; ci Quickdraw patches
;____________________________________________________________________________ DAF <1.9>
; Install window manager fixes
;
InstToolTp newSetWinColor,$241
InstToolTp NewSetCtlColor,$243
;____________________________________________________________________________ dvb <3.5>
; Palette Mgr Patches
;
InstToolTp ptchInitPalettes,$290
InstToolTp ptchGetNewCWindow,$246 ;<10Nov89 KON>
InstToolTp ptchPMgrDispatch,$2A2 ; Changed a couple of dispatches dvb <8.3>
; Next, fix up the dispatch table
LEA pMgrProcs,A0
MOVE.L A0,D1 ; D1-> base of table
SUBQ.L #1,D1 ; Less 1, 'coz lobit = patched flag
MOVE #((pMgrProcsSize)/4)-1,D0 ; we'll loop for this many fields <107> (pMgrProcsSize)
@FixPMLoop MOVE.L (A0),D2 ; pull entry from table
BTST #0,D2
BEQ.S @FixPMLoopEnd
ADD.L D1,D2
@FixPMLoopEnd MOVE.L D2,(A0)+ ; stash correct address, bump A0
DBRA D0,@FixPMLoop ; and count down, including zero. dvb <8.3> end
;__________________________________________________________________________
;__________________________________________________________________________
FixBackSANE MOVE.L #'fpu ',D0 ; Gestalt FPU selector
_Gestalt ; Do it
MOVE.L A0,D0 ; Do we have an FPU?
BEQ @ReallyDone ; -> No, do nothing
MOVE.L ROMBase,A0 ; Get ROM base
CMPI.B #TERRORminorVers,18(A0) ; Is this TERROR 067C ROM?
BEQ @ReallyDone ; -> Yes, leave the ROM SANE enabled!
CMPI.B #ZYDECOminorVers,18(A0) ; Is this Zydeco 067C ROM?
BEQ @ReallyDone ; -> Yes, leave the ROM SANE enabled!
@DisableSANEinROM
MOVE.B ResLoad,-(SP) ; Save current resLoad state
MOVE.W CurMap,-(SP) ; Save Current Rsrc Map refNum
CLR.W CurMap ; Make the System the current Map (CurMap = 0)
SF ResLoad ; Don't actually read the rsrc
CLR.L -(SP) ; Result
MOVE.L #'PACK',-(SP) ; Type
MOVE.W #4,-(SP) ; Id 4
_Get1Resource
MOVE.L (SP)+,D0 ; Did we get it?
BEQ @Done ; -> No, PACK 4 is not on the disk. Exit Now! (Use the ROM SANE)
MOVE.L D0,-(SP)
_ReleaseResource ; Make the System SANE handle go away. (or we'll get it at the _RmveRsrc)
SF ResLoad ; Don't actually read the rsrc
CLR.L -(SP) ; Result
MOVE.L #'PACK',-(SP) ; Type
MOVE.W #5,-(SP) ; Id 5
_Get1Resource
MOVE.L (SP)+,D0 ; Did we get it?
BEQ @Done ; -> No, PACK 5 is not on the disk. Exit Now! (Use the ROM SANE)
MOVE.L D0,-(SP)
_ReleaseResource ; Make the System SANE handle go away. (or we'll get it at the _RmveRsrc)
ST RomMapInsert ; Put the ROM map in first
MOVE.W #1,CurMap ; Make the ROM map current
CLR.L -(SP) ; Result
MOVE.L #'PACK',-(SP) ; Type
MOVE.W #4,-(SP) ; Id 4
_Get1Resource
MOVE.L (SP)+,D0 ; Did we get it?
BEQ.S @Try45 ; -> No, try 4 five.
MOVE.L D0,-(SP) ; The Handle (save a copy of it)
MOVE.L ROMMapHndl,-(SP) ; Save this
MOVE.L #-1,ROMMapHndl ; To fool SetResAttr into letting use change ROM rsrc attrs
MOVE.L D0,-(SP) ; The Handle (push it. Push it good)
MOVE.W #$50,-(SP) ; A good value (Unprotected)
_SetResAttrs
MOVE.L (SP)+,ROMMapHndl
MOVE.W #1,CurMap ; Set CurMap to the ROM rsrc map
ST RomMapInsert ; Dont load the rsrc into memory
_RmveResource
@Try45 ST RomMapInsert ; Put the ROM map in first
CLR.L -(SP) ; Result
MOVE.L #'PACK',-(SP) ; Type
MOVE.W #5,-(SP) ; Id 5
_Get1Resource
MOVE.L (SP)+,D0 ; Did we get it?
BEQ.S @Done ; -> No, exit
MOVE.L D0,-(SP) ; The Handle (save a copy of it)
MOVE.L ROMMapHndl,-(SP) ; Save this
MOVE.L #-1,ROMMapHndl ; To fool SetResAttr into letting use change ROM rsrc attrs
MOVE.L D0,-(SP) ; The Handle (push it. Push it good)
MOVE.W #$50,-(SP) ; A good value (Unprotected)
_SetResAttrs
MOVE.L (SP)+,ROMMapHndl
MOVE.W #1,CurMap ; Set CurMap to the ROM rsrc map
ST RomMapInsert ; Dont load the rsrc into memory
_RmveResource
@Done MOVE.W (SP)+,CurMap ; Restore the current res map
MOVE.B (SP)+,resLoad ; Restore ResLoad
@ReallyDone
;__________________________________________________________________________
;__________________________________________________________________________
;____________________________________________________________________________ <2> RMP
; This patch is used to fix a problem in the MPW Shell on Eclipse. See above.
ROMVIA2DT equ $00009D70 ; ROM offset of old IOP interrupt handler
bra.s EclipseMPWPatchEnd ; skip over patch body into install code
EclipseMPWPatchStart
move.b #1<<ifCA2,VIFR(A1) ; reset the VIA2 interrupt flag
move.l #(%00001000<<24)+\ ; allow xmt msg 3 (ADB)
(%00001000<<16)+\ ; allow rcv msg 3 (ADB)
(0<<8)+\ ; this byte must be zero
1,d0 ; ADB is on SWIM IOP (IOP 1)
jmpROM IOPInterrupt ; handle the interrupt and return
EclipseMPWPatchEnd
@EclipseMPWPatchSize equ EclipseMPWPatchEnd-EclipseMPWPatchStart
cmpRA ROMVIA2DT,(VIA2DT+4*ifCA2) ; see if we have an IOP interrupt handler
bne.s @done ; if not, don't need to install it
moveq.l #@EclipseMPWPatchSize,d0; space needed
_NewPtr ,Sys,Clear ; allocate it
bne.s @done ; if can't allocate, don't install
movea.l a0,a1 ; dest address
lea EclipseMPWPatchStart,a0 ; source address
moveq.l #@EclipseMPWPatchSize,d0 ; byte count
_BlockMove ; copy the code
move.w sr,-(sp) ; save old int level
ori.w #HiIntMask,sr ; disable all ints
move.l a1,(Via2DT+4*ifCA2) ; install the new VIA2 interrupt handler
move.w (sp)+,sr ; restore the interrupt level
@done
; End of Eclipse Cmd-Shift-Esc patch
;____________________________________________________________________________ <2> RMP
;____________________________________________________________________________ GGD <2.0>
; SANE Package Optimization
;
; Optimize the SANE packages which are ROM Resources, by having the dispatch
; table entry point right to the first instruction of the package, instead
; of going through the Package Manager which finds the package by de-referencing
; a handle.
;
IF 1 THEN ; removed <4.6> <08/21/89 pke> re-enabled 11/29/89 <8.4>
OptimizePACKs
lea @PackOptTable,a3; point to the optimization table
@optLoop move.w (a3)+,d0 ; get the package number
bmi.s @done ; exit at end of list
move.w d0,-(sp) ; push the package number
_InitPack ; get the ROM resource, update AppPacks table
move.w (a3)+,d1 ; get the trap word
move.w (a3)+,a0 ; get the low mem address
move.l (a0),d0 ; get the handle
beq.s @optLoop ; if null, skip it
movea.l d0,a0 ; setup to de-reference it
move.l (a0),d0 ; get a pointer to the routine
beq.s @optLoop ; if null, skip it
movea.l d0,a0 ; setup pointer to code
cmpi.b #$60,(a0) ; see if first instruction is a BRA.S
bne.s @branchOptDone ; if not, don't optimize it
move.w (a0)+,d0 ; get the BRA.S instruction
ext.w d0 ; extend the branch displacement
adda.w d0,a0 ; update the entry point address
@branchOptDone
move.w d1,d0 ; setup the trap word
_SetTrapAddress ; go directly to the first instr of the package
bra.s @optLoop ; optimize the next package
@PackOptTable
dc.w 4 ; package number 4
_FP68K ; trap name for PACK 4
dc.w AppPacks+4*4 ; low mem address of handle to PACK 4
dc.w 5 ; package number 5
_Elems68K ; trap name for PACK 5
dc.w AppPacks+5*4 ; low mem address of handle to PACK 5
dc.w -1 ; package number -1, end of list
@done
ENDIF
;__________________________________________________________________________ <101> <BEGIN>
;
; Install PACK 4 patch if:
;
; - BoxFlag = 13 (//si - Erickson), or 14 (Mac LC - Elsie)
; and - No FPU present
; and - Current non-fpu PACK 4 lives at ROMBase + $73940
;
; NOTE: This code MUST execute after OptimizePACKs!
;
FP68KTrap equ $A9EB ;Trap number.
PACK4Handle equ AppPacks+16 ;Lomem contains PACK4 handle.
PACKID equ 4 ;Resource ID.
PACK4Patch
;
; Are we running on IIsi or LC?
;
; Commented out boxFlag check. Its not really needed. <107> SAM
; cmpi.b #boxMacLC,BoxFlag ;Is this an LC?
; beq.s @doPatch ;Yep, so install patch.
; cmpi.b #boxErickson,BoxFlag ;No, is it a IIsi?
; bne @endPACK4Patch ;Nope, so skip install.
;
; Yes, is there an FPU?
;
@doPatch move.l #gestaltFPUType,d0 ;Do we have an FPU?
_Gestalt
cmp.w #gestaltNoFPU,a0
bne @endPACK4Patch ;Yes, so don't install.
;
; Nope, does the current PACK4 live at ROMBase + $73940?
;
move.w #FP68KTrap,d0 ;Get trap number.
_GetTrapAddress ;Get current vector in a0.
cmpra PACK4inROM,a0 ;Matching address?
bne.s @endPACK4Patch ;Nope, so don't install.
;
; Yes, so install the patch...
;
move.w #FP68KTrap,d0 ;Get trap number.
lea FP020Patch,a0 ;Get address of our patch code.
_SetTrapAddress ;Patch it.
@endPACK4Patch
;__________________________________________________________________________ <101> <END>
;____________________________________________________________________________
; Gestalt parity calculation
;
; This code figures out if the board has parity capability, and if so,
; if there are parity SIMMs installed. It stores the result in the
; gestalt parity function in the resident portion of the patch above.
;
IMPORT parityValue
WITH DecoderInfo,ExpandMemRec,GestaltGlobals,ProductInfo
MACHINE MC68030
movem.l a3/a4/d3/d4,-(sp) ; save registers! <102>
movea.l ExpandMem,a0 ; get ptr to expandmem rec
movea.l emGestalt(a0),a0 ; get gestalt global ptr
clr.l d0 ; assume no parity, clear result <59>
cmpi.w #gestaltMacIIci,machType(a0) ; Mac IIci is first parity machine
blt @parityExit ; if before ci, definitely no parity
move.l UnivROMFlags,d1 ; get external feature bits
btst #PGCInstalled,d1 ; check if a parity chip exists
bne.s @checkPGC ; yep, go see if parity is enabled
move.l AddrMapFlags,d1 ; get universal info attributes
btst #RPUExists,d1 ; do we have an RPU chip?
bne.s @checkRPU ; then go check RPU
bra @parityExit ; if not, return zero as result
; checkPGC - check the parity VIA bit to see if it is enabled.
@checkPGC move.l VIA,a0 ; load up Via base address
btst #6,VBufB(a0) ; check if parity enabled
beq @parityOn ; if clear, parity is enabled
bra @parityOff ; otherwise, it's off
; checkRPU - First set RPU to generate bad parity, then access all four SIMMs in
; both banks by accessing location 0 and the last longword in memory.
; Parity is only fully active if all four SIMMs generate a parity interrupt.
; trashes a0/a1/a3/a4/d1-d4
@checkRPU movec cacr,d3 ; get contents of cache
move.l d3,-(sp) ; save them
move.l #$1111,d3 ; enable caches with bursting <32>
movec d3,cacr ; write into cache register <32>
move.l RomBase,a0 ; point to base of rom <32>
move.l #$2000,d3 ; cache size/long = 32k/4 = 8k <32>
@fillLoop tst.l (a0)+ ; load a long <32>
dbra d3,@fillLoop ; keep doing it for 8k <32>
move.l #$0808,d3 ; disable and freeze caches (bursting off)
movec d3,cacr ; write into cache register
move.l UnivInfoPtr,a0 ; get pointer to universal information
add.l (a0),a0 ; point to decoderInfo record
move.l RPUAddr(a0),a1 ; get RPU base address
move.l sp,d3 ; save our stack pointer
move.l AutoInt7,d4 ; save NMI vector
lea @parityInt,a4 ; address to return to from parity intrpt
lea @nmiHandler,a0 ; get address of our NMI handler
move #$2700,sr ; turn all interrupts off
move.l a0,AutoInt7 ; point vector to our handler
moveq #0,a3 ; check first bank (0 is in first bank)
@checkBank moveq #4-1,d2 ; check all four SIMMs
move.l (a3),d1 ; get contents of longword
@nextByte clr.l (a3) ; write a long with correct parity <44>
st.b rpuReset(a1) ; reset serial ptr
st.b (a1) ; write wrong parity mode
clr.b (a3,d2.w) ; write one SIMM with bad parity
st.b rpuReset(a1) ; reset serial ptr <105>
clr.b (a1) ; write good parity mode <105>
tst.l (a3) ; parity error if it's a parity SIMM
nop ; wait for an interrupt
nop
move.l d1,(a3) ; restore contents of longword
move #$2000,sr ; turn interrupts back on
move.l d4,AutoInt7 ; restore NMI vector
move.l (sp)+,d3 ; get original state of cache <17>
movec d3,cacr ; restore original state of cache <17>
bra.s @parityOff ; if we get here, it's a non-parity SIMM
@parityInt st.b rpuReset(a1) ; sync up RPU serial line
clr.b (a1) ; write good parity mode
dbra d2,@nextByte ; go check next SIMM
@allParityBank move.l d1,(a3) ; restore contents of longword
move.l a3,d1 ; did we just check location 0?
bne.s @restoreNMI ; if not, we're done and parity is on
movea.l ExpandMem,a0 ; get ptr to expandmem rec
movea.l emGestalt(a0),a0 ; get gestalt global ptr
movea.l memSize(a0),a3 ; total amount of memory
subq #4,a3 ; point to last longword in memory
bra.s @checkBank ; go check bank B
@restoreNMI move #$2000,sr ; turn interrupts back on
move.l d4,AutoInt7 ; restore NMI vector
move.l (sp)+,d3 ; get original state of cache <17>
movec d3,cacr ; restore original state of cache <17>
bra.s @parityOn ; go return that parity is on
; Interrupt handler for checkRPU routine. It is assumed that the NMI button is
; not pressed during this routine.
; d3 = stack pointer of routine
; a1 = RPU base address
; a4 = return address
@nmiHandler st.b rpuReset(a1) ; reset serial ptr
clr.b (a1) ; write good parity mode
st.b (a1) ; clear the parity error
move.l d3,sp ; restore the stack pointer
jmp (a4) ; return to the checkRPU routine
@parityOn bset #gestaltParityEnabled,d0 ; by here it is
@parityOff bset #gestaltHasParityCapability,d0 ; set parity capability bit
@parityExit lea parityValue,a0 ; get address of variable in gestalt function
move.l d0,(a0) ; save response in gestalt function
movem.l (sp)+,a3/a4/d3/d4 ; restore registers! <102>
ENDWITH
;____________________________________________________________________________
; Gestalt function patch installation
;
; These functions either did not make it in the Portable ROM, or changed
; between ROM final and System Disk final.
;
gestaltRBVAddr EQU 'rbv '
gestaltSCCReadAddr EQU 'sccr'
gestaltSCCWriteAddr EQU 'sccw'
gestaltVIA1Addr EQU 'via1'
gestaltVIA2Addr EQU 'via2'
gestaltSlotAttr EQU 'slot' ; removed in favor of gestaltNuBusConnectors <95>
gestaltFirstSlot EQU 'slt1' ; removed in favor of gestaltNuBusConnectors <95>
gestaltSlotCount EQU 'nubs' ; removed in favor of gestaltNuBusConnectors <95>
lea gestaltQDVers,a0 ; address of gestaltQDVersion patch
move.l #gestaltQuickdrawVersion,d0 ; selector to REPLACE
_ReplaceGestalt
lea gestaltAddrMode,a0 ; addr of gestaltAddressingModeAttr patch
move.l #gestaltAddressingModeAttr,d0 ; selector to REPLACE
_ReplaceGestalt
lea gestaltParity,a0 ; addr of gestaltParityAttr patch
move.l #gestaltParityAttr,d0 ; selector to REPLACE
_ReplaceGestalt
lea getGestaltVers,a0 ; addr of getGestaltVersion patch
move.l #gestaltVersion,d0 ; selector to REPLACE
_ReplaceGestalt
lea gestaltMisc,a0 ; addr of gestaltMisc patch
move.l #gestaltMiscAttr,d0 ; selector to ADD
_NewGestalt
lea gestaltNBCon,a0 ; addr of gestaltNuBusConnectors patch <95>
move.l #gestaltNuBusConnectors,d0 ; selector to ADD
_NewGestalt
lea gestaltUndef,a0 ; addr of gestaltUndef patch <95>
move.l #gestaltSlotAttr,d0 ; selector to REPLACE
_ReplaceGestalt
lea gestaltUndef,a0 ; addr of gestaltUndef patch <95>
move.l #gestaltFirstSlot,d0 ; selector to REPLACE
_ReplaceGestalt
lea gestaltUndef,a0 ; addr of gestaltUndef patch <95>
move.l #gestaltSlotCount,d0 ; selector to REPLACE
_ReplaceGestalt
lea gestaltNMgr,a0 ; addr of gestaltNotificationMgrAttr patch
move.l #gestaltNotificationMgrAttr,d0 ; selector to ADD
_NewGestalt
lea gestaltSerial,a0 ; addr of gestaltSerialAttr patch <95>
move.l #gestaltSerialAttr,d0 ; selector to ADD
_NewGestalt
lea gestaltUndef,a0 ; addr of gestaltUndef patch
move.l #gestaltRBVAddr,d0 ; selector to REPLACE
_ReplaceGestalt
lea gestaltUndef,a0 ; addr of gestaltUndef patch
move.l #gestaltSCCReadAddr,d0 ; selector to REPLACE
_ReplaceGestalt
lea gestaltUndef,a0 ; addr of gestaltUndef patch
move.l #gestaltSCCWriteAddr,d0 ; selector to REPLACE
_ReplaceGestalt
lea gestaltUndef,a0 ; addr of gestaltUndef patch
move.l #gestaltVIA1Addr,d0 ; selector to REPLACE
_ReplaceGestalt
lea gestaltUndef,a0 ; addr of gestaltUndef patch
move.l #gestaltVIA2Addr,d0 ; selector to REPLACE
_ReplaceGestalt
IF doScriptMgrGestalt AND (NOT installScriptMgrPtch27) THEN ; <6.1><50>
;____________________________________________________________________________ pke <2.5>
; Gestalt install for Script Mgr <2.5> <08/05/89 pke>
;
import gestaltScriptMgr,gestaltSMgrTable
lea gestaltSMgrTable,a3 ; table of Gestalt selectors
; and GetEnvirons verbs
@loopInstallGestalt
move.l (a3)+,d0 ; get next Gestalt selector
beq.s @doneInstallGestalt ; 0 means we're done
addq.l #2,a3 ; skip GetEnvirons verb
lea gestaltScriptMgr,a0 ; push gestaltFunction ProcPtr
_NewGestalt
; ignore OSErr in d0 (what can
; we do if it is not noErr?)
bra.s @loopInstallGestalt
@doneInstallGestalt
ENDIF ; <6.1>
;____________________________________________________________________________ dba <3.7>
; Install default colors 'clut' from System file
; Since the first InitGraf was before the ROvr code, the ROM 'clut' is
; always used. We want to use a better 'clut' from the System file.
; NOTE: This code is straight out of GrafAsm.a.
FixQDColors ; <4.7>
cmp.l #-1,QDColors ; is QDColors initialized? <4.7>
beq.s @done ; no, no need to fix it up <4.7>
SUBQ #4,SP ; make room for function result
MOVE #DefQDColors,-(SP) ; push resource ID
_GetCTable ; get default colors
MOVE.L QDColors,a0 ; get pointer to QDColors
MOVE.L (SP),A1 ; get handle to default colors
MOVE.L (A1),A1 ; point to default colors
ADD #CTTable,A1 ; skip over header
MOVEQ #15,D0 ; need to move 16 longs
@nextLong MOVE.L (A1)+,(A0)+ ; move a long
DBRA D0,@nextLong ; => repeat for all longs
_DisposCTable ; dispose of color table
@done ; <4.7>
;____________________________________________________________________________ dba <3.0>
; Install Menu Manager patches
;
InstToolTp NewInitProcMenu,$8
InstToolTp NewMenuSelect,$13D
IF NOT SPLINE_FONT THEN
;____________________________________________________________________________ cel <5>
; Install NewRSect Patch for DrawText zero width chars
;
setTrap NewRSect,$AB21
ENDIF
;____________________________________________________________________________ DAF <4.1>
; This really didn't get in until <5.1>
;
; Install SetEntries patch
InstToolTp mySaveEntries,$249
InstToolTp mySetEntries,$23F ; < 124 >
;____________________________________________________________________________ pke <4.6>
; Install patches to UprString,CmpString,RelString (OK for A/UX)
InstOSTp NewUprString,$54
InstOSTp NewCmpString,$3C
InstOSTp NewRelString,$50
;____________________________________________________________________________ DDG <58>
; Install vector for the “FPU not installed” dialog box if we dont have an
; FPU or an MMU
move.l #gestaltFPUType,d0 ;do we have an FPU ?
_Gestalt
cmp.w #gestaltNoFPU,a0 ;if this is NOT noFPU, then we skip
bne.s @skipInstall ;..the installation of this patch
lea NewFLineRoutine,a0 ;get the address of our F-Line routine into A0
lea OldFLineRoutine,a1 ;get the address of the JMP to the old F-Line routine
lea Line1111,A2
move.l (A2),2(A1) ; Save the old Vector <107> SAM
move.l A0,(A2) ; Make 1111 traps come to us first <107> SAM
@skipInstall
;----------------------------------------------------------------------------------------------------
;__________*** This set of routines gets run only if we have a REgret chip ***_________________
WITH ProductInfo
; <101> SAM
MOVE.L UnivROMFlags,D0 ; Do we have a REgret?
AND.B #ClockMask,D0 ; (bits 4-6) <107> SAM (Use ClockMask!)
CMP.B #ClockEgret,D0 ; Is bit 5 on?
BNE.S @EndOfEgretOnly ; -> Nope, skip this install code
;----------------------------------------------------------------------------------------------------
; This patch bypasses the physical read of egret when reading the time. The time is automatically
; updated in the background, therefore the low mem global always reflects the acurate time.
; (REgret only)
;----------------------------------------------------------------------------------------------------
InstOSTp RdDateTimePtch,$39
;----------------------------------------------------------------------------------------------------
; Install the TickHandler Patch into the TickComp vector kept in <89><101>
; the Egret Manager Global variables.
; (REgret only)
;----------------------------------------------------------------------------------------------------
WITH EgretGlobals
; Dont need to turn off IRQs here. <107> SAM
; move.w sr,-(sp) ; no interruptions
; ori.w #LVL7IRQ,sr
lea TickHandler,a0 ; get TickHandler address
move.l EgretBase,a1 ; point to EgretManager Globals
move.l a0,tickComp(a1) ; setup vector to new tick handler
; move.w (sp)+,sr ; restore interrupt state
ENDWITH
;----------------------------------------------------------------------------------------------------
; This patch will save the processor status register, call the <101> SAM
; ShiftRegIrq routine in Egret Manager and then restore the
; status register and exits.
; (REgret only)
;----------------------------------------------------------------------------------------------------
lea Vector_hold,a1 ; point to the interrupt vector placeholder
move.l LVL1DT+8,(a1) ; shift register interrupt handler
lea EgretIRQPtch,a1 ; Point to the patch
move.l a1,LVL1DT+8
;----------------------------------------------------------------------------------------------------
; This patch fixes possible loss of data to the SCC by calling <101> SAM
; the Poll Proc when SCC data is available.
; (REgret only)
;----------------------------------------------------------------------------------------------------
InstOSTp EgretDispatchPtch, $92
@EndOfEgretOnly
ENDWITH
;__________________________ End of REgret Only Section ______________________________________
;----------------------------------------------------------------------------------------------------
move.l MinusOne, $B50 ; clean up after netbooting socket listener.<78>
;----------------------------------------------------------------------------------------------------
;____________________________________________________________________________ pke <90>
; Move Script Mgr patches here so they are installed for A/UX. <90>
; Currently assumes that installScriptMgrPtch39 and installScriptMgrPtch27 are
; true, but this may be changed, so the inner conditionals are being left in.
IF doScriptMgrForAUX THEN ; <90>
IF installScriptMgrPtch39 THEN ; <50>
PtchInst 39 ; <42>
ENDIF
IF installScriptMgrPtch27 THEN ; <50>
PtchInst 27 ; <5.7>
ENDIF
ENDIF ; <90>
EndBothSection
;=========================================================================================
;=========================================================================================
;= =
;= ALL PATCHES BELOW THIS POINT ARE INSTALLED ON THE MACINTOSH OS ONLY. ALL PATCHES =
;= ABOVE THIS POINT ARE INSTALLED BOTH THE MAC OS AND A/UX. =
;= =
;=========================================================================================
;=========================================================================================
; Runtime check to determine whether we are running A/UX. If so, skip this section
; of patch install code.
move.w HwCfgFlags,d0 ; check em the compulsive way
btst.l #hwCbAUX,d0 ; is it A/UX time?
bne skipMacOnlyPatches ; if so skip the mac-only patches
;=========================================================================================
;=========================================================================================
;= =
;= PATCH INSTALLATION CODE FOR THE MAC OS ONLY STARTS HERE =
;= =
;= Please be neat and follow the format =
;= =
;=========================================================================================
;=========================================================================================
;____________________________________________________________________________ ggd <2.2/2.7>
; Slot Interrupt patch
;
; Patches _SIntInstall, and reverses Slot interrupt queue order
;
PatchSIntInstall
Import SIntInstall
With SlotIntQElement,slotIntGlobals
; We reverse the order of equal priority elements in the queue for Aurora, such that
; they again blissfully agree with what the Mac II does for Equal Priorities
; turn off interrupts since we are mucking with a queue
move.w SR, -(sp)
ori.w #HiIntMask,SR ; disable all ints
InstOSTp SIntInstall,$A075 ; install the new trap
; cycle thru the slots for reversing queue order
moveq #TotalSlots-1,d1 ; set up for dbra
@nextQueue lea ([SlotQDT],d1.w*4,slotIntQHeads),a0 ; get address of queue header
movea.l (a0),a1 ; get ptr to first queue element
clr.l (a0) ; destroy old queue
bra.s @start ; re-install the elements
@loop movea.l a1,a0 ; set up for SIntinstall
movea.l SQLink(a1),a1 ; save out ptr to next queue element
move.l d1,d0 ; set up for call
_SIntInstall ; re-install the queue element
@start move.l a1,d0 ; test for end of queue
bne.s @loop ; loop until end of queue
@queueDone dbra d1,@nextQueue
; re-enable interrupts now that we are finished mucking
move.w (sp)+, SR
;____________________________________________________________________________ djw <2.4>
; Slot manager PRAM patch
;
; Fixes a problem in InitPRAMRecs where when initializing slot PRAM from a
; PRAM initialization record from the declaration ROM, the board id would
; not be set correctly. This code writes the correct board id to the slot
; PRAM for all good cards.
GetBoardROM Equ $0000636E ; addr of GetBoard routine in ROM <2.7>
With spBlock,sInfoRecord
FixSlotPRAM
suba.w #spBlockSize,sp ; alloc spBlock
movea.l sp,a0 ; a0 = ptr to spBlock
subq.l #8,sp ; alloc space for pram buffer
movea.l sp,a1 ; a1 = ptr to pram read/write buffer
clr.l (a1) ; clr pram buffer (8 bytes)
clr.l 4(a1)
clr.b spSlot(a0) ; start from slot zero
; Loop through the slots and check if the board id in PRAM matches the
; board id on the declaration ROM. If not, then write the correct one
; to PRAM.
move.w sr,-(sp) ; save status reg
ori.w #HiIntMask,sr ; disable interrupts
@Loop
jsrROM GetBoardROM ; jsr into ROM to GetBoard routine to get board sRsrc
bne.s @EndLoop ; no board sRsrc - skip this slot
movea.l spResult(a0),a2 ; a2 = ptr to sInfo record
tst.w siInitStatusA(a2) ; test card status
bmi.s @EndLoop ; bad slot - skip it
move.b #Boardid,spId(a0) ; read board id field from board sRsrc
_sReadWord
bne.s @EndLoop ; board id is gone - must be a bad slot
move.w spResult+2(a0),d1 ; reg d1 = board id from decl rom
move.l a1,spResult(a0) ; pass ptr to buffer
_sReadPRAMRec
bne.s @EndLoop ; cannot read PRAM - bad slot
; Compare PRAM board id with declaration ROM board id. If different, update
; the PRAM board id.
cmp.w (a1),d1 ; same board id's?
beq.s @EndLoop ; same - go to next slot
move.w d1,(a1) ; update board id in buffer
move.l a1,spsPointer(a0) ; set pointer to write buffer
_InitSlotPRAM
@EndLoop
addq.b #1,spSlot(a0) ; inc to next slot
cmp.b #sLastSlot,spSlot(a0)
ble.s @Loop ; continue till all slots are done
move.w (sp)+,sr ; restore interrupts
adda.w #spBlockSize+8,sp
Endwith
;____________________________________________________________________________ djw <3.6>
; Slot manager pInitEntry patch
;
; Install the pInitEntry patch which corrects the spId passed to _sFindDevBase
; from _InsertSRTRec.
;
Import pInitEntry
lea pInitEntry,a0 ; entry point for resident patch
move.l a0,([SDMJmpTblPtr],InitEntry*4) ; insert addr in slot mgr tbl
;____________________________________________________________________________ DAF <2.6>
; TFB Video Driver Override
;
INCLUDE 'VideoPatch.a'
;________________________________________________________________ <4.3><08/21/89 pke>
; Patch to Pack6 to fix Script Manager routines (which are not
; supported by A/UX).
;
IF doScriptMgrPack6Fix AND (NOT installScriptMgrPtch39) THEN ; <42><50>
InstToolTp ptchPack6,$1ED
ENDIF
;____________________________________________________________________________
; Bump Script Manager version number for IntlForce bug fix (SysVers < $700) pke <5.3>
; Set Script Manager version (SysVers >= $700) pke <5.7>
; redo using new symbol smgrVersPTCHRom pke <5.9>
IF doScriptMgrSetROMVers AND (NOT installScriptMgrPtch39) THEN ; <42><50>
With SMgrRecord
GetSMgrCore a0
move.w #smgrVersPTCHRom,smgrVersion(a0)
EndWith
ENDIF
;____________________________________________________________________________
; Initialize additional Script Manager vectors pke <5.4>
; Add CallInterface pke <5.9>
; Add NewSwapIcon (7.0 only, moved to ptch 39) pke <6.2>
IF doScriptMgrNewVectors AND (NOT installScriptMgrPtch27) THEN ; <42><50>
ROMSMgrCalcRect EQU $1E1C2
ROMSMgrInitFonts EQU $1E21C
ROMCallInterface EQU $1E3B0 ; <5.9>
With SMgrRecord
GetSMgrCore a0
leaRom ROMSMgrCalcRect,a1
move.l a1,sVectSMgrCalcRect(a0)
leaRom ROMSMgrInitFonts,a1
move.l a1,sVectSMgrInitFonts(a0)
leaRom ROMCallInterface,a1 ; <5.9>
move.l a1,sVectCallInterface(a0) ; <5.9>
EndWith
ENDIF
;____________________________________________________________________________ pke <5.7>
; Install Script Manager 7.0 extensions, ROM patches
; Moved these installs up if doScriptMgrForAUX is true. <90>
IF NOT doScriptMgrForAUX THEN ; <90>
IF installScriptMgrPtch39 THEN ; <50>
PtchInst 39 ; <42>
ENDIF
IF installScriptMgrPtch27 THEN ; <50>
PtchInst 27 ; <5.7>
ENDIF
ENDIF ; <90>
;____________________________________________________________________________ pke <7.8>
; Install patches for Script Manager routines InitDateCache, String2Date
IF doScriptMgrStr2DatFix AND (NOT installScriptMgrPtch39) THEN ; <42><50>
smInitDateCacheOff equ -16 ; DispTable offset for InitDateCache
smString2DateOff equ -20 ; DispTable offset for String2Date
With SMgrRecord
GetSMgrCore a1
move.l smgrDispTable(a1),a1
lea NewInitDateCache,a0
move.l a0,smInitDateCacheOff(a1)
lea NewString2Date,a0
move.l a0,smString2DateOff(a1)
EndWith
ENDIF
;____________________________________________________________________________ pke <8.0>
; Install Script Manager tail patch to _GetIndADB, fixes the way SwapKybd
; clears dead key state in ADB keyboard driver data structure
IF doScriptMgrRstKCHRFix AND (NOT installScriptMgrPtch39) THEN ; <42><50>
PatchOSJump oldGetIndADB,$78 ; set addr for BackToTrap
InstOSTp ptchGetIndADB,$78 ; …and then install patch
ENDIF
;____________________________________________________________________________ pke <8.5>
; Install Script Manager patch to LwrString so it handles 2-byte chars
IF doScriptMgrLwrString2 AND (NOT installScriptMgrPtch27) THEN ; <8.5><50>
PatchOSJump oldLwrString,$56 ; set addr for BackToTrap
InstOSTp ptchLwrString,$56 ; …and then install patch
ENDIF
;____________________________________________________________________________ EVA <7.1><123>
; Install Async Serial Driver Vector Address
Import SerialPatch
InstOSTp SerialPatch,$A0BE
SERDVersion equ 5
; install new version number
move.l #5*4,d0 ; first serial DCE is 5th entry in Utbl
moveq #4-1,d1 ; index through 4 dce's (adjusted for dbra)
@next movea.l UTableBase,a0 ; get ptr to the unit table
movea.l 0(a0,d0.w),a0 ; get DCE handle
movea.l (a0),a0 ; get DCE ptr
move.w #SERDVersion,dCtlQueue(a0) ; post new version
addq #4,d0 ; get next DCE
dbra d1,@next
;____________________________________________________________________________ GGD <8.4>
; Install ADB Polling patch for ViaADB implementations only
;
; If we are running on a machine with ViaADB (ie. No IOPs), then we allocate a
; block for this patch, copy the code into it, and install it (saving heap space
; on machines that don't need it).
;
; This patch changes Auto/SRQ polling to only poll device addresses which have entries
; in the device table.
OldFDBShiftInt equ $0000a700 ; ROM offset of old FDBShiftInt
SendByte2Rtn equ $0000A6D0 ; ROM offset of return from second @sendNextByte call
GetByte2Rtn equ $0000A63C ; ROM offset of return from second @getNextByte call
ROM@sendNextByte equ $0000A6E6 ; ROM offset of @sendNextByte label
ROM@fetchLoop equ $0000A63A ; ROM offset of @fetchLoop label
ROM@handleSRQ equ $0000A724 ; ROM offset of SRQ handling code
ROM@skipUpdate equ $0000A738 ; ROM offset of ReqDoneVIA exit without updating ADDR
InstallADBPollPatch
cmpRA OldFDBShiftInt,Lvl1dt+8 ; see if correct shift int handler to patch
bne.s @exit ; if not, don't patch it (might not be VIA based ADB)
lea ADBPollPatchStart,a1 ; get address of code to copy
move.l (a1),d0 ; length of code
_NewPtr ,SYS ; allocate space for the code
bne.s @exit ; if couldn't allocate, don't install it
move.l (a1)+,d0 ; length of code
exg.l a0,a1 ; setup src/dst for block move
_BlockMove ; copy the code
move.l a1,Lvl1DT+8 ; install new shift int handler
@exit bra.w ADBPollPatchEnd ; jump around patch body
ADBPollPatchStart
dc.l ADBPollPatchEnd-ADBPollPatchStart-4
with ADBVars
;_______________________________________________________________________
; Routine: FDBShiftInt
; Inputs: A1 - base address of VIA1 (setup by IntHnd)
; Outputs: A1 - base address of VIA1
; A3 - pointer to ADBBase
; ccr.z - result of BTST #vFDBInt,vBufB(a1)
;
; Function: handles shift interrupt, resumes asynchronous processing
;_______________________________________________________________________
FDBShiftInt movea.l ADBBase,a3 ; point to ADB globals in low memory
movea.l ShiftIntResume(a3),a0 ; get address to resume at
cmpRA SendByte2Rtn,a0 ; see if resuming from sending second byte
beq.s SendPatch ; if so, use the patched code
cmpRA GetByte2Rtn,a0 ; see if resuming from fetching second byte
beq.s FetchPatch ; if so, use the patched code
btst.b #vFDBInt,vBufB(a1) ; test the FDBInt~ status
jmp (a0) ; resume async processing
SendPatch btst.b #vFDBInt,vBufB(a1) ; test the FDBInt~ status
bne.s @sendLoop ; if no SRQ, send the data
bset.b #fDBSRQ,FDBAuFlag(a3) ; remember that a service request was returned
@sendLoop tst.b fDBCnt(a3) ; see if end of buffer reached
beq.s ReqDoneVIA ; leave when count is zero, no reply data
jsrROM ROM@sendNextByte ; send another byte
bra.s @sendLoop ; loop until count exhausted
FetchPatch btst.b #vFDBInt,vBufB(a1) ; test the FDBInt~ status
beq.s @fetchDone ; exit if end of data reached
cmpi.b #8,fDBCnt(a3) ; see if end of buffer reached
bhs.s @fetchDone ; keep fetching until end of data
jmpROM ROM@fetchLoop
@fetchDone btst.b #fDBNoReply,FDBAuFlag(a3) ; see if buffer data is valid
seq.b d0 ; $FF if data is valid, $00 if no reply
and.b d0,fDBCnt(a3) ; set count to zero if timeout
* bra.s ReqDoneVIA
ReqDoneVIA move.b FDBAuFlag(a3),d0 ; get the flags
move.b fDBCmd(a3),d1 ; get the command
moveq.l #(1<<fDBSRQ),d3 ; mask to test for SRQ pending
and.b d0,d3 ; isolate the bit
neg.l d3 ; set bit 31 if SRQ pending
move.b d1,d3 ; insert the command byte
lsr.b #4,d1 ; isolate the device address
tst.l d3 ; was there an SRQ?
bpl.s @noSRQ ; if not, don't advance poll address
jmpROM ROM@handleSRQ ; otherwise, go handle the SRQ
@noSRQ move.w DevMap(a3),d2 ; list of possible address to search
btst.l d1,d2 ; see if it is in the table
beq.s @skipUpdate ; if not, don't switch to that address
move.b d1,PollAddr(a3) ; remember where to auto/SRQ poll next
@skipUpdate jmpROM ROM@skipUpdate ; back to ROM, just past the update
ADBPollPatchEnd
; End of ADB Polling patch for ViaADB implementations
;____________________________________________________________________________ GGD <8.4>
;____________________________________________________________________________ GGD <8.4>
; Install a Time Manager Task to simulate the 60.15Hz pseudo VBL for OSS based systems.
;
; If we are running on a machine with an OSS, then we allocate a block for this patch,
; copy the code into it, and install it (saving heap space on machines that don't need it).
;
; This patch corrects the pseudo VBL frequency on OSS based systems, the OSS generates
; a 60.00Hz interrupt, but the Macintosh Pseudo VBL rate should be 60.14742 Hz.
; To correct this, we simply ignore and disable the OSS interrupt, and use the
; Time Manager to generate interrupts at the correct rate.
FixMPWShell equ 1 ; Temporarily fix CMD-Period <25>
; This same patch is also modified to fix a problem in the MPW Shell on Zone-5.
; The real bug is in the MPW Shell, but we will temporarily fix it here until they
; have a chance to rev, so that we don't hear bitching from developers.
; The MPW Shell will sometimes cut back the stack from within a patch they make to
; PostEvent, when CMD-Period is pressed. Therefore, it may never return back to the
; keyboard driver, which never returns to the ADBManager, which never returns to the
; IOP Manager, which never returns to the Deferred Task Manager, which never returns
; to the Interrupt Handler, which never returns to whatever code was running at the
; time of the interrupt (which may have been another interrupt). This causes data
; structures to be left in inconsistent states, such as the deferred task manager thinks
; that a deferred task is still running, and won't run any new tasks.
; The work around is to not run ADB as a deferred task, and instead run it at level 1 <25>
ROMLevel1OSSInt equ $00009B50 ; ROM offset of old Level1OSSInt
ServiceIntMMU equ $00009B68 ; ROM offset of ServiceIntMMU
if FixMPWShell then ; <25>
IOPInterrupt equ $00005036 ; ROM offset of IOP Manager interrupt handler <25>
ContinueOssLevel1Decode equ $00009D8E ; ROM offset of continuation of OssLevel1Decode <25>
else ; <25>
ContinueOssLevel1Decode equ $00009D88 ; ROM offset of continuation of OssLevel1Decode
endif ; <25>
OssVBL60HzInt equ $00009DF0 ; ROM offset of OssVBL60HzInt
IntRegs reg a0-a3/d0-d3 ; registers saved by all interrupt handlers
bra.s Oss60HzPatchEnd ; skip over patch body into install code
Oss60HzPatchStart
Oss60HzTimeHandler
movea.l a1,a0 ; point to the TMTask
move.l #-16626,d0 ; 16.626 ms, 60.14742 Hz (pseudo VBL rate)
movea.l jPrimeTime,a1 ; point to the routine
jsr (a1) ; initiate the delay
movea.l OSS,a1 ; get OSS chip base address
jmpROM OssVBL60HzInt ; run the VBL interrupt
OssLevel1Decode
movea.l OSS,a1 ; get OSS chip base address
move.w OSSIntStat(a1),d0 ; see who is interrupting
bclr.l #OSSIntVBL60Hz,d0 ; ignore OSS 60Hz pseudo VBL interrupt
if FixMPWShell then ; <25>
btst #OSSIntIOPSWIM,d0 ; check SWIM IOP first <25>
beq.s OSSPSwmMasked ; if no SWIM IOP Interrupt, skip it <25>
moveq.l #7,d1 ; mask for int level <25>
and.b OSSMskPSwm(a1),d1 ; see if SWIM IOP was disabled <25>
beq.s OSSPSwmMasked ; if disabled, ignore it <25>
move.l #(%00001000<<24)+\ ; allow xmt msg 3 (ADB) <25>
(%00001000<<16)+\ ; allow rcv msg 3 (ADB) <25>
(0<<8)+\ ; this byte must be zero <25>
1,d0 ; ADB is on SWIM IOP (IOP 1) <25>
jmpROM IOPInterrupt ; handle the interrupt and return <25>
OSSPSwmMasked ; <25>
endif ; <25>
jmpROM ContinueOssLevel1Decode ; resume with the ROM code
Level1OSSInt
movem.l IntRegs,-(SP) ; preserve registers
lea OssLevel1Decode,a3 ; use the OSS level 1 dispatcher
jmpROM ServiceIntMMU ; call primary interrupt dispatcher
Oss60HzPatchEnd
@PatchSize equ Oss60HzPatchEnd-Oss60HzPatchStart
cmpRA ROMLevel1OSSInt,AutoInt1; see if we have an OSS interrupt handler
bne.s @done ; if not, don't need to install it
moveq.l #tmXQSize+@PatchSize,d0 ; space needed
_NewPtr ,Sys,Clear ; allocate it
bne.s @done ; if can't allocate, don't install
movea.l a0,a2 ; save a copy
lea Oss60HzPatchStart,a0 ; source address
lea tmXQSize(a2),a1 ; dest address
moveq.l #@PatchSize,d0 ; byte count
_BlockMove ; copy the code
lea Oss60HzTimeHandler-Oss60HzPatchStart(a1),a0 ; point to the handler
move.l a0,tmAddr(a2) ; initialize the task address
movea.l a2,a0 ; get the time manager task address
move.l #'eada',(a0) ; put in magic signature (see VM for details) <139>
_InsXTime ; install the task (fixed frequency)
move.l #-16626,d0 ; 60.14742 Hz (pseudo VBL rate)
movea.l jPrimeTime,a2 ; point to the routine
lea Level1OSSInt-Oss60HzPatchStart(a1),a1
move.l Ticks,d1 ; get the current time
@sync cmp.l Ticks,d1 ; sync with the VBL manager
beq.s @sync ; wait for it to change
move.w sr,-(sp) ; save old int level
ori.w #HiIntMask,sr ; disable all ints
move.l a1,AutoInt1 ; install the new level 1 handler
movea.l OSS,a1 ; get the OSS base
clr.b OSSMsk60Hz(a1) ; disable the OSS 60Hz interrupt source
move.w (sp)+,sr ; restore the interrupt level
jsr (a2) ; start the pseudo VBL timer
@done
; End of OSS VBL frequency patch
;____________________________________________________________________________ GGD <8.4>
;____________________________________________________________________________ SWC <8.8>
; RecoverHandle() patch for 32-bit Memory Manager
IMPORT v24RecoverHandle,v32RecoverHandle
JRecoverHandle EQU $6C ;offset into 32-bit Memory Manager's vector table
LEA v24RecoverHandle,A0 ;patch in the 24-bit version of RecoverHandle
MOVE.L A0,JMemMgr24+JRecoverHandle
LEA v32RecoverHandle,A0 ;patch in the 32-bit version of RecoverHandle
MOVE.L A0,JMemMgr32+JRecoverHandle
; End of RecoverHandle() patch install
;____________________________________________________________________________ SWC <8.8>
;____________________________________________________________________________ RMP <12>
; SetHandleSize() patch for 32-bit Memory Manager
IMPORT v32SetHandleSize
JSetHandleSize EQU $64 ;offset into 32-bit Memory Manager's vector table
LEA v32SetHandleSize,A0 ;patch in the 32-bit version of SetHandleSize
MOVE.L A0,JMemMgr32+JSetHandleSize
; End of SetHandleSize() patch install
;____________________________________________________________________________ RMP <12>
;____________________________________________________________________________ CSL
; SetPtrSize() patch for 32-bit Memory Manager
IMPORT v32SetPtrSize
JSetPtrSize EQU $4C ;offset into 32-bit Memory Manager's vector table
LEA v32SetPtrSize,A0 ;patch in the 32-bit version of SetPtrSize
MOVE.L A0,JMemMgr32+JSetPtrSize
; End of SetPtrSize() patch install
;____________________________________________________________________________ CSL
IF 0 THEN
;____________________________________________________________________________ jwk <19>
;
; Patch in FastReadOSS() and FastWriteOSS() ROM routines to use the SCSIDMA chip.
;
WITH ROMHeader, scsiGlobalRecord
ROMFastWriteOSS EQU $00009042
ROMFastReadOSS EQU $000092ea
cmpi.b #boxF19,BoxFlag ; is it an F19 ?
bne.s @jwkNoInstall ; only applies to F19's
move.w #$11f0,d0 ; check for any final F19 ROM
movea.l ROMBase,a1 ; point to the base of the ROM
and.w ROMRelease(a1),d0 ; we'll take 1.1f1, 1.1f2, etc.
cmpi.w #$11f0,d0 ; is it a 1.1f… ROM ?
bne.s @jwkNoInstall ; only install on a Zone5 with 1.1f… ROM's
; <57> 04-22-90 csd
; commented out the installation of SCSI DMA so we stop trashing
; hard disks on the IIfx.
movea.l SCSIGlobals,a1 ; point to SCSI Manager globals
move.l #250*10000,G_Reserved1(a1) ; set up 250ms byte-to-byte timeout
leaROM ROMFastWriteOSS,a0
; move.l a0,jvVFWO(a1) ; use DMA code for SCSIWBlind
leaROM ROMFastReadOSS,a0
; move.l a0,jvVFRO(a1) ; use DMA code for SCSIRBlind
@jwkNoInstall
ENDWITH
;
; End of FastReadOSS() and FastWriteOSS() patch install
;____________________________________________________________________________ jwk <19>
ENDIF
;____________________________________________________________________________ jwk <29>
;
; Patch in chaining SCSI bus error handler
;
TestFor SCSI96_1Exists ; check universal tables for C96 SCSI Chip <3>
bne.s @ChaningBErrDone ; has C96 - do not install patch (or die) <3>
WITH scsiGlobalRecord
movea.l SCSIGlobals,a1 ; point to SCSI Manager globals
lea.l BusErrHandler,a0 ; point to bus error handler patch
move.l a0,jvBusErr(a1) ; patch vector in the globals
ENDWITH
@ChaningBErrDone
;_________________________________________________________________________________________ <119> djw
; Install SCSI fix for Quantum 7.9 rom fix
with scsiGlobalRecord
; Check the universal tables in this ROM version for a SCSI DMA chip (the GDU). If
; the GDU exist, then we must be on a Mac IIfx (dammed overpatch ROM's). The Quantum
; fix cannot be applied to the IIfx because on the GDU, *ACK cannot be controlled.
TestFor SCSIDMAExists ; check universal tables for SCSI DMA
bne.s @noSCSIpatch ; has SCSI DMA - do not install patch
TestFor SCSI96_1Exists ; check universal tables for C96 SCSI Chip <136>
bne.s @noSCSIpatch ; has C96 - do not install patch (or die) <136>
; Apply the patch to this Mac IIci family ROM
lea QuantumWBlindIIci,a0 ; a0 = TIB interpreter patch
move.l a0,jvWBlind(a1) ; replace vector
lea FastWriteFix,a0 ; patch to FastWrite data xfer routine
move.l a0,jvVFWO(a1) ; virtual fast writes (hhsk)
move.l a0,jvVFW(a1) ; virtual fast writes (hhsk)
@noSCSIpatch
;_________________________________________________________________________________________ <122> djw
; Install SCSIDispatch patch for VM conflict
;
; Patch SCSIDispatch back to ROM to avoid the situation where VM patches SCSIDispatch
; before patches, and after patches. VM will be in the chain of patches twice. This
; coupled with the SCSI mgr calling the file system gets into a circular calling sequence
; of the SCSI mgr calling VM and VM calling the SCSI mgr.
@ROMSCSIDispatch Equ $00007460 ; offset to SCSIDispatch in ROM
movea.l RomBase,a0 ; get base of ROM
adda.l #@ROMSCSIDispatch,a0 ; add offset to SCSIDispatch in ROM
setTrapA0 $a815 ; patch SCSIDispatch to ROM
;____________________________________________________________________________
;
; <54> Install patch to IOPMsgRequest to fix IOP Serial Driver Ctrl Call bug
;____________________________________________________________________________
IMPORT IOPMsgRequest
move.w sr, -(sp) ; disable interrupts while we patch
ori.w #HiIntMask,sr
;
; Install the patch only if IOPMsgRequest trap already exists
;
gettrapA0 $A087 ; get IOPMsgRequest trap addr
move.l a0,a1 ; set it aside
gettrapA0 $A89F ; get unimplemented trap addr
cmpa.l a0,a1 ; check 'em
beq.s @noTrap ; nope, so don't install patch
PatchOSJump oldIOPMsgRequest,$87 ; Stash original IOPMsgRequest routine <12>
InstOSTp IOPMsgRequest,$87 ; replace IOPMsgRequest trap <12>
@noTrap
; restore state
move.w (sp)+,sr ; disable interrupts while we patch
;____________________________________________________________________________
;
; <54> End Install patch to IOPMsgRequest to fix IOP Serial Driver Ctrl Call bug
;____________________________________________________________________________
;____________________________________________________________________________ GGD <28>
; Patch the Deferred Task Manager Task Dispatcher to re-enable interrupts upon
; exiting to fix QuickMail servers (for now at least), because they call through
; jDisptch at application level and wind up with all interrupts being masked,
; and the Task Dispatcher expects to only be called from then end of an interrupt
; handler, which will restore the interrupt level via an RTE.
PatchOSJump ROMvDisptch,$B9 ; set addr for BackToTrap
InstOSTp NewvDisptch,$B9 ; …and then install patch
; End of Deferred Task Manager Task Dispatcher Patch Installation
;____________________________________________________________________________ GGD <28>
;____________________________________________________________________________ EH <4>
; Patch the secondary dispatcher for the Level 4 IOP interrupt handler
;
; This patch fixes some of the serial thruput problems encountered on Apollo
; and the TimLC when the CPUs are running in 24 bit mode. These are the first (slow)
; machines to run in 32 bit mode a good portion of the time. Every time we
; take an interrupt the primary interrupt handler switches the CPU into 24 bit
; mode, forcing cache flushes and generally incurring a lot of overhead. At high
; serial baud rates, this overhead interferes with our ability to keep pace.
;
; The solution is to NOT take an interrupt for each received character, but
; rather to empty out the SCC FIFO before returning to the primary interrupt
; dispatch. So we patch the secondary dispatcher to call the serial driver's
; interrupt routines, rather than jumping to them. The service routine then
; returns to the secondary dispatcher, with checks to see if there is another
; character available on either port. If there is another character pending,
; the secondary dispatch routine loops to dispatch to the new interrupt (that
; must be pending) rather than returning to the primary dispatcher (and incurring
; the overhead).
;
; we do this ONLY FOR CHANNEL A, since it's the only one that's documented to be
; fast, and also so that appletalk won't pound us at its 230Kbaud rate.
;
; The Serial Driver Rx and SC interrupt service routines are patched in conjuction
; with this so that if a device manager request completes, we exit to the primary
; dispatcher regardless of whether a character is pending. This way we exit the
; interrupt handlers completely at least once per device manager request, allowing
; things like deferred tasks to run more in sequence.
;
; <6> fix the Farallon MacRecorder bug
; modified patch to test for port A RxChar and loop back only if we are servicing
; a channel A interrupt. For port B we just jump to service routine like ROM code.
;
; <7> fix patch <6>
; Port B dispatcher fixed to call serial service routines and to have same number
; of bytes before the rts so that async serial driver Rx and SCx patches (which
; fiddle with return address on stack) return to the proper place.
;
; <10> for VM, patch level 4 autovector pointed to by vbr, not just the zero-offset.
ROMLevel4SccInt equ $00009b20 ; ROM offset of old SCCIOPBypassInt
IntRegsSize equ 8*4 ; size of IntRegs in bytes, must change if IntRegs changes
SccDT equ Lvl2DT ; Dispatch table for SCC interrupts
bra.s SCCPatchEnd ; branch to install code
SCCPatchStart
;
; this is the secondary dispatcher code we are patching
;
SCCIOPBypassInt
SccDecode MOVE.L SCCRd,A0 ; get SCC read address
MOVE.B (A0),D0 ; read to sync up SCC (just to be safe)
MOVE.L SCCWr,A1 ; get SCC channel B write control address
SccDecodeCommon
MOVE.B #2,(A1) ; point to SCC register 2, B channel
LEA SccDT,A2 ; point to dispatch table and delay
MOVEQ #$0E,D0 ; 'and mask' and extra delay
AND.B (A0),D0 ; read the modified interrupt vector
CMPI.B #8,D0 ; channel A interrupt?
bge.S @GoChannelA ; branch if for A <6>
MOVE.L 0(A2,D0.W*2),A2 ; get dispatch vector <6>
jsr (A2) ; call service routine <6> <7>
bra.s @fixedRTS ; fill in the 10 bytes as for port A <7>
dcb.b 8,0 ; so that Rx,SCx handlers return properly <7>
@fixedRTS rts
@GoChannelA ; <6>
ADDQ #2,A0 ; adjust SCC addresses for port A
ADDQ #2,A1
@GoLvl2
MOVE.L 0(A2,D0.W*2),A2 ; get dispatch vector
jsr (A2) ; call service routine <6>
; note we return here UNLESS we finish a device manager request
; note this is 10 bytes-- CHANGE THE SCC RxIntHnd patch equate if this changes!!!!!
movea.l SCCRd,a0 ; point to SCC read base address <6>
btst.b #RxCA,2(a0) ; SCC data available on channel A? <6>
bne.s SCCDecode ; data available, so dispatch again <6>
; note we return here if we are finishing a device manager request
rts ; return to primary dispatcher <6>
SCCIOPBypassIntEnd ; for IOP patch below <7>
SCCIOPBypassIntSize equ SCCIOPBypassIntEnd-SCCIOPBypassInt; <7>
;
;
; this is the primary dispatch code we patch in order to get to the secondary dispatcher
;
Level4SccInt
movem.l IntRegs,-(SP) ; preserve registers
lea SCCIOPBypassInt,a3 ; use the SCC IOP interrupt dispatcher
jmpROM ServiceIntMMU ; call primary interrupt dispatcher
SccPatchEnd
@SccPatchSize equ SccPatchEnd-SccPatchStart
;
; this is the install code for the patch
;
cmpRA ROMLevel4SccInt,AutoInt4 ; see if we have an SCC bypass interrupt handler
bne.s @done ; if not, don't need to install it
moveq.l #@SccPatchSize,d0 ; space needed
_NewPtr ,Sys,Clear ; allocate it
bne.s @done ; if can't allocate, don't install
movea.l a0,a1 ; dest address
lea SccPatchStart,a0 ; source address
moveq.l #@SccPatchSize,d0 ; byte count
_BlockMove ; copy the code
move.w sr,-(sp) ; save old int level
ori.w #HiIntMask,sr ; disable all ints
lea Level4SccInt-SccPatchStart(a1),a1 ; get offset to primary dispatcher code
move.l a1,AutoInt4 ; install the new level 4 handler
movec vbr,a0 ; get the vbr in case VM moved it <10>
move.l a1,AutoInt4(a0) ; install the new level 4 handler <10>
move.w (sp)+,sr ; restore the interrupt level
@done
; End of Lvl4Int secondary dispatcher patch
;____________________________________________________________________________ EH <4>
;____________________________________________________________________________ EH <30>
; Patch the SCCIOP interrupt handler to set all completion flags to immediate.
;
; If we are running on a machine with an OSS, then we allocate a block for this patch,
; copy the code into it, and install it (saving heap space on machines that don't need it).
;
; This patch fixes things so that TIMBUKTU/REMOTE, slime code that it is, will
; run on a Zone 5 in IOP mode. Timbuktu/Remote makes SYNCHRONOUS read calls to
; the IOP Serial driver FROM A VBL TASK. Sometimes the VBL gets called when the
; IOP Manager completion routine (for a call from the serial driver) is waiting
; to run (as a deferred task).
; The result is that the synchronous call waits in the Device Manager for IODone
; to be called, but IODone is called by the serial driver, which is returned to
; from the IOP Manager completion routine, which is NEVER returned to because we
; made a synchronous call from an elevated interrupt level and are now just sitting
; in a loop in the device manager: DEADLOCK.
;
; The reason Timbuktu/Remote worked on previous Macs is that the bypass driver
; does NOT use a deferred task to call IODone.
;
; The work around is to not call the IOP Manager completion routines for the SCC
; as deferred tasks, but instead call them at level 1 (immediately).
;
; <10> for VM, patch level 4 autovector pointed to by vbr, not just the zero-offset.
ROMLevel4SccIopInt equ $00009B10 ; ROM offset of old Level4SccIopInt
bra.s SccIopPatchEnd ; skip over patch body into install code
SCCIopPatchStart
SCCIopInt
move.l #(%11111111<<24)+\ ; complete xmt msgs 0..7 immediate
(%11111111<<16)+\ ; complete rcv msg 0..7 immediate
(0<<8)+\ ; this byte must be zero
0,d0 ; SCC IOP number 0
jmpROM IOPInterrupt ; handle the interrupt and return
Level4SccIopInt
movem.l IntRegs,-(SP) ; preserve registers
lea SccIopInt,a3 ; use the SCC IOP interrupt dispatcher
jmpROM ServiceIntMMU ; call primary interrupt dispatcher
SccIopPatchEnd
@SccIopPatchSize equ SccIopPatchEnd-SccIopPatchStart
cmpRA ROMLevel4SccIopInt,AutoInt4; see if we have an SCC IOP interrupt handler
bne.s @done ; if not, don't need to install it
moveq.l #@SccIopPatchSize,d0 ; space needed
_NewPtr ,Sys,Clear ; allocate it
bne.s @done ; if can't allocate, don't install
movea.l a0,a1 ; dest address
movea.l a0,a2 ; save dest addr <7>
lea SccIopPatchStart,a0 ; source address
moveq.l #@SccIopPatchSize,d0 ; byte count
_BlockMove ; copy the code
;patch the bypass interrupt handler
moveq.l #SCCIOPBypassIntSize,d0 ; space needed
_NewPtr ,Sys,Clear ; allocate it
bne.s @done ; if can't allocate, don't install
movea.l a0,a1 ; dest address
lea SCCIOPBypassInt,a0 ; source address
moveq.l #SCCIOPBypassIntSize,d0 ; byte count
_BlockMove ; copy the code
; install the patches
move.w sr,-(sp) ; save old int level
ori.w #HiIntMask,sr ; disable all ints
movea.l IOPmgrVars,a0 ; get IOP mgr globals <7>
move.w #SccIopNum,d0 ; get SCC IOP number as index <7>
; fortunately the IOPInfoPtrs are declared at offset zero to IOPMgrVars <7>
; as shown here below <7>
; IOPMgrGlobals record {IOPInfoPtrs},increment ; globals used by the IOP manager <7>
move.l (a0,d0.w*4),d0 ; get SCCIOP info pointer <7>
move.l d0,a0 ; <7>
with IOPInfo ; <7>
move.l a1,BypassHandler(a0) ; a1-> secondary SCC dispatcher <7>
endwith ; <7>
lea Level4SccIOPInt-SccIopPatchStart(a2),a1 ;a2-> primary handler <7>
move.l a1,AutoInt4 ; install the new level 4 handler
movec vbr,a0 ; get the vbr in case VM moved it <10>
move.l a1,AutoInt4(a0) ; install the new level 4 handler <10>
move.w (sp)+,sr ; restore the interrupt level
@done
; End of SccIopInt patch
;____________________________________________________________________________ EH <30>
;____________________________________________________________________________ EH <33>
;
; Install patch to IOPMoveData to fix IOP Serial Driver DMA Hang bug
;
IMPORT IOPMoveData
;save state
move.w sr, -(sp) ; disable interrupts while we patch
ori.w #HiIntMask,sr
movem.l a0/d0-d1,-(sp) ; save some registers
; Install patch only if IOPMoveData trap already exists
clr.l d0 ; clear result
move.w #UnimplementedTrap,d0 ; get loc of unimplemented trap
_GetTrapAddress ,newTool ; get the address into A0
move.l a0,d1 ; save it for a sec
move.l #$A088,d0 ; trap ID to check for IOPMoveData
_GetTrapAddress ,NewOS ; get the address of it
cmp.l a0,d1 ; is it implemented?
beq.s @noTrap ; nope, so don't install patch
PatchOSJump oldIOPMoveData,$88 ; set addr for BackToTrap
InstOSTp IOPMoveData,$88 ; implemented, so install new trap addr
@noTrap
; restore state
movem.l (sp)+,a0/d0-d1 ; restore saved registers
move.w (sp)+,sr ; disable interrupts while we patch
;
;
; End Install patch to IOPMoveData to fix IOP Serial Driver DMA Hang bug
;____________________________________________________________________________ EH <33>
;____________________________________________________________________________ <10> <cch 8/6/91>
;
; Install patch to getPageDesc and _VM. These patches take effect only on
; 68030 machines with the Terror ROM, version $67c, sub-version 1.5 when VM
; is disabled.
;
ROMVers EQU $08
ROMSubVers EQU $12
VMGlobals EQU $b78
IMPORT GetPageDescPatch
; check to see if we're on the Terror ROM, subversion 1.5.
cmp.b #cpu68030,CPUFlag ; check if we're on an 030
bne.s @skipPatch ; ignore if not
move.l RomBase,a0 ; get base of ROM
cmp.w #TERRORmajorVers,ROMVers(a0); check major version
bne.s @skipPatch ; ignore if incorrect version
cmp.b #TERRORminorVers,ROMSubvers(a0); check subversion
bne.s @skipPatch ; ignore if incorrect version
tst.l VMGlobals ; check if VM is running
bpl.s @skipPatch ; ignore if VM is on
; patch _Gestalt
PatchOSJump origGestalt,$AD ; set addr for BackToTrap to orig _Gestalt
InstOSTp GetPageDescPatch,$AD ; implemented, so install new trap addr
PatchOSJump origMemDisp,$5C ; set addr for JsrTrap back to orig _VM
PatchOSJump origMemDisp1,$5C ; set addr for BackToTrap back to orig _VM
InstOSTp MemDispPatch,$5C ; implemented, so install new trap addr
@skipPatch
;
;
; End Install patch to getPageDesc proc
;____________________________________________________________________________ <10> <cch 8/6/91>
;____________________________________________________________________________ <13> <cch 8/28/91>
;
; Install patch to flush after backpatching fp68k calls made from ROM on
; 68030 running Terror.
;
FP68kPatchInstall
; check to see if we're on the Terror ROM, subversion 1.5.
cmp.b #cpu68030,CPUFlag ; check if we're on an 030
bne.s @skipPatch ; ignore if not
move.l RomBase,a0 ; get base of ROM
cmp.w #TERRORmajorVers,ROMVers(a0) ; check major version
bne.s @skipPatch ; ignore if incorrect version
cmp.b #TERRORminorVers,ROMSubvers(a0) ; check subversion
bne.s @skipPatch ; ignore if incorrect version
MOVE.W HwCfgFlags,D0 ; Get them Hardware Config Flags <14> SAM
BTST.L #hwCbFPU,D0 ; Does we gots an FPU? <14>
BEQ.S @skipPatch ; -> No, don't patch <14>
; patch _FP68k ($A9EB)
PatchToolJump origFP68k,$1EB ; set addr for BackToTrap to orig _Gestalt
InstToolTp FP68kPatch,$1EB ; implemented, so install new trap addr
@skipPatch
;
;
; End Install patch to fp68k
;____________________________________________________________________________ <13> <cch 8/28/91>
EndMacSection
;=========================================================================================
;=========================================================================================
;= =
;= END OF MAC-ONLY INSTALL CODE SECTION =
;= =
;=========================================================================================
;=========================================================================================
skipMacOnlyPatches ; above code is for Mac OS only
;————————————————————————————————————————————————————————————————————————————————————————
;############################### END PATCH INSTALL CODE #################################
;————————————————————————————————————————————————————————————————————————————————————————
CalcPatchSize
Lea StartPatch,A1 ; start of patch code
Lea EndOfPatch,A0 ; end of patch code
Sub.l A1,A0 ; calc size of resident code
Move.l A0,D0 ; SetHandleSize takes new size in D0
Move.l (SP)+,A0 ; restore the handle passed by SysPatch
Bra CutBack ; go cut the install code off and exit
ENDPROC
UsesPtchInst ; Patchinstll code Macro <1.1-4april89-CEL>
; added Proc FixupTbl from PatchIIROM.a <24July89smb>
Proc
Export FixupTbl
;################## TABLE OF LOCATIONS TO BE OFFSET BY [ROMBase] ####################
;
; Table contains one entry for each reference to a ROM address from the
; JmpROM, JsrROM, and CmpRA macros. &RomFixIndex is a count of the total
; number of these references, and is also used to synthesize the label
; names for them. The reference labels have the form
; RXXX000, RXXX001, RXXX002, ...
; See the Macro definitions for JmpROM, JsrROM and CmpRA (near the top of
; this file) for more info.
;
; MkTbl is a macro only because assembler while loops will not work
; outside of macros.
;
MACRO
MkTbl
gbla &RomFixIndex
while &RomFixIndex <> 0 do
&RomFIxIndex seta &RomFixIndex - 1
dc.l RXXX&I2S(&ROMFIXINDEX,-3) - FixUpTbl
endwhile
dc.l 0 ; Zero entry marks end of table
ENDM
FixupTbl MkTbl
;########################### END PATCHES CUT BACK CODE ################################
EndProc
END