; ; 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 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 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> 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 ; 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 ; move.l d3,d4 ; JMPRom RomResizePaletteplusEight ptchZapLinks ; Following code is spliced out of CQD:PaletteMgr.a ; 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? 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 move winID(a6),-(SP) ; push window ID _GetNewPalette ; fetchez la palette move.l (sp)+,d0 ; well? 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 move D1,-(sp) ; push cUpdates AWC.PB459 _SetPalette ; 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< ; 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? 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 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 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 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> ;____________________________________________________________________________ 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 @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 MOVE.L sDrvrSw(A2),srrDrvrSw(A1) ; copy ; 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 move.l 16(SP),D0 ; get D0 = return address 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 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 ; bclr #7,XmitBits(A2) ; no, clear the DTR bit bclr #7,WR5AVal(A2) ; @1 bclr #3,XmitBits(A2) ; always clear Tx enable 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 ; 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 ; 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) beq CtlSwitchCTSClock ; 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 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 <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 . . . <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 ; @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 ; 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 RTS ; jump to it 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 Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue RTS ; jump to it ; ----- 32 bit version ----- a32SetSize MoveM.L D1-D6/A0-A3,-(SP) ;Save registers. <18Apr85> Move.L A0,A2 ;Points to block text. Move.B MPtag32-BlkData32(A2),-(SP) ;save flags of block 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. Move.L BlkSize32(A2),D2 ;Get physical size. 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 AddA.L BlkSize32(A3),A3 ;bump on to next block 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) ; BEq.S @CoalFree ;Eq => free block found Move.L BlkSize32(A3),D0 ;get block size 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 AddA.L BlkSize32(A3),A3 ;bump on to next block Tst.B TagBC32(A3) BEq.S @CoalFLoop ;Eq => more free space! Clr.L TagBC32(A0) ;clear 1st long word of block Move.L D0,BlkSize32(A0) ;update size of coalesced block 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 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 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 Clr.L TagBC32(A0) ;set free block Move.L D0,BlkSize32(A0) ;Force size of free block (don't need A0 now) 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!!!! Move.B (SP),MPtag32(A0) ;restore the tags from home on the stack 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 Clr.L TagBC32(A0) ;free block 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 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 JSRROM a32MakeSpace ;Try making room after this block. BClr #Lock,MPtag32(A0) ;Unlock block @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 BClr #Purge,MPtag32-BlkData32(A3);Unlock block 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. 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. 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. ; Neg.L D0 ;Minus size of new space. ; BSR.S AdjustFree ;Account for less free space. JSRROM SubtractFree ;Account for less free space. @SSShrink ;Shrink the block. Sub.L D3,D4 ;Number of bytes to shrink block. Cmp.L #MinFree32,D4 ;sFree < MinFree? 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. 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 ; Move.B (SP)+,MPtag32-BlkData32(A3) ;Restore MP flag byte. Move.B (SP)+,MPtag32(A0) ;Restore MP flag byte. @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 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 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? <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 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> ; 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> ;__________________________________________________________________________ ; 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> ; 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> ;__________________________________________________________________________ <13> ; Routine: FP68k patch for Terror-based 030 machines ; ; Inputs: stack has: ; ; 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< 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> ; ; 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> ;____________________________________________________________________________ ; 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< ;____________________________________________________________________________ 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> ; ; 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> ;____________________________________________________________________________ <13> ; ; 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> 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