mac-rom/Patches/PatchIIciROM.a
Elliot Nunn 0ba83392d4 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-09-20 18:04:16 +08:00

9813 lines
376 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; 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 GestaltÕs 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, donÕt include InternalOnlyEqu.a (already in dump
; file).
; <142> 8/30/91 DTY Define isUniversal here since itÕs 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 DarinÕs 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 itÕs 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 itÕs 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 donÕt 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 RealityÕs 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 didnÕt 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 ;donÕt 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, donÕt 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 weÕre 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, donÕt 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 weÕre 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, donÕt 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 weÕre 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, donÕt 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 itÕs not one, then it isnÕt 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 weÕre 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 GestaltÕs 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 donÕt 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